diff options
Diffstat (limited to 'xorg-server')
96 files changed, 41709 insertions, 41475 deletions
diff --git a/xorg-server/Xext/Makefile.am b/xorg-server/Xext/Makefile.am index 8a604c3e7..cb432e00e 100644 --- a/xorg-server/Xext/Makefile.am +++ b/xorg-server/Xext/Makefile.am @@ -1,140 +1,133 @@ -# libXext.la: includes all extensions and should be linked into Xvfb,
-# Xnest, Xdmx and Xprt
-# libXextbuiltin.la: includes those extensions that are built directly into
-# Xorg by default
-# libXextmodule.la: includes those extensions that are built into a module
-# that Xorg loads
-if XORG
-noinst_LTLIBRARIES = libXext.la libXextbuiltin.la libXextmodule.la
-else
-noinst_LTLIBRARIES = libXext.la
-endif
-
-INCLUDES = -I$(top_srcdir)/hw/xfree86/dixmods/extmod
-
-AM_CFLAGS = $(DIX_CFLAGS)
-
-if XORG
-sdk_HEADERS = xvdix.h xvmcext.h geext.h geint.h shmint.h syncsdk.h
-endif
-
-# Sources always included in libXextbuiltin.la & libXext.la
-BUILTIN_SRCS = \
- bigreq.c \
- geext.c \
- shape.c \
- sleepuntil.c \
- sleepuntil.h \
- sync.c \
- syncsdk.h \
- syncsrv.h \
- xcmisc.c \
- xtest.c
-
-# Sources always included in libXextmodule.la & libXext.la. That's right, zero.
-MODULE_SRCS =
-MODULE_LIBS =
-
-# Optional sources included if extension enabled by configure.ac rules
-
-# MIT Shared Memory extension
-MITSHM_SRCS = shm.c shmint.h
-if MITSHM
-BUILTIN_SRCS += $(MITSHM_SRCS)
-endif
-
-# XVideo extension
-XV_SRCS = xvmain.c xvdisp.c xvmc.c xvdix.h xvmcext.h xvdisp.h
-if XV
-MODULE_SRCS += $(XV_SRCS)
-endif
-
-# XResource extension: lets clients get data about per-client resource usage
-RES_SRCS = xres.c
-if RES
-MODULE_SRCS += $(RES_SRCS)
-endif
-
-# MIT ScreenSaver extension
-SCREENSAVER_SRCS = saver.c
-if SCREENSAVER
-MODULE_SRCS += $(SCREENSAVER_SRCS)
-endif
-
-# Xinerama extension: making multiple video devices act as one virtual screen
-XINERAMA_SRCS = panoramiX.c panoramiX.h panoramiXh.h panoramiXsrv.h panoramiXprocs.c panoramiXSwap.c
-if XINERAMA
-BUILTIN_SRCS += $(XINERAMA_SRCS)
-if XORG
-sdk_HEADERS += panoramiXsrv.h panoramiX.h
-endif
-endif
-
-# X-ACE extension: provides hooks for building security policy extensions
-# like XC-Security, X-SELinux & XTSol
-XACE_SRCS = xace.c xace.h xacestr.h
-if XACE
-BUILTIN_SRCS += $(XACE_SRCS)
-if XORG
-sdk_HEADERS += xace.h xacestr.h
-endif
-endif
-
-# SELinux extension: provides SELinux policy support for X objects
-# requires X-ACE extension
-XSELINUX_SRCS = xselinux_ext.c xselinux_hooks.c xselinux_label.c xselinux.h xselinuxint.h
-if XSELINUX
-MODULE_SRCS += $(XSELINUX_SRCS)
-MODULE_LIBS += $(SELINUX_LIBS)
-endif
-
-# Security extension: multi-level security to protect clients from each other
-XCSECURITY_SRCS = security.c securitysrv.h
-if XCSECURITY
-BUILTIN_SRCS += $(XCSECURITY_SRCS)
-endif
-
-XCALIBRATE_SRCS = xcalibrate.c
-if XCALIBRATE
-BUILTIN_SRCS += $(XCALIBRATE_SRCS)
-# XCalibrate needs tslib
-endif
-
-# XF86 Big Font extension
-BIGFONT_SRCS = xf86bigfont.c xf86bigfontsrv.h
-if XF86BIGFONT
-BUILTIN_SRCS += $(BIGFONT_SRCS)
-endif
-
-# DPMS extension
-DPMS_SRCS = dpms.c dpmsproc.h
-if DPMSExtension
-MODULE_SRCS += $(DPMS_SRCS)
-endif
-
-# Now take all of the above, mix well, bake for 10 minutes and get libXext*.la
-
-libXext_la_SOURCES = $(BUILTIN_SRCS) $(MODULE_SRCS)
-libXext_la_LIBADD = $(MODULE_LIBS)
-
-if XORG
-libXextbuiltin_la_SOURCES = $(BUILTIN_SRCS)
-
-libXextmodule_la_SOURCES = $(MODULE_SRCS)
-libXextmodule_la_LIBADD = $(MODULE_LIBS)
-endif
-
-EXTRA_DIST = \
- $(MITSHM_SRCS) \
- $(XV_SRCS) \
- $(RES_SRCS) \
- $(SCREENSAVER_SRCS) \
- $(XACE_SRCS) \
- $(XCSECURITY_SRCS) \
- $(XSELINUX_SRCS) \
- $(XCALIBRATE_SRCS) \
- $(XINERAMA_SRCS) \
- $(BIGFONT_SRCS) \
- $(DPMS_SRCS) \
- $(GE_SRCS)
-
+# libXext.la: includes all extensions and should be linked into Xvfb, +# Xnest, Xdmx and Xprt +# libXextbuiltin.la: includes those extensions that are built directly into +# Xorg by default +# libXextmodule.la: includes those extensions that are built into a module +# that Xorg loads +if XORG +noinst_LTLIBRARIES = libXext.la libXextbuiltin.la libXextmodule.la +else +noinst_LTLIBRARIES = libXext.la +endif + +INCLUDES = -I$(top_srcdir)/hw/xfree86/dixmods/extmod + +AM_CFLAGS = $(DIX_CFLAGS) + +if XORG +sdk_HEADERS = xvdix.h xvmcext.h geext.h geint.h shmint.h syncsdk.h +endif + +# Sources always included in libXextbuiltin.la & libXext.la +BUILTIN_SRCS = \ + bigreq.c \ + geext.c \ + shape.c \ + sleepuntil.c \ + sleepuntil.h \ + sync.c \ + syncsdk.h \ + syncsrv.h \ + xcmisc.c \ + xtest.c + +# Sources always included in libXextmodule.la & libXext.la. That's right, zero. +MODULE_SRCS = +MODULE_LIBS = + +# Optional sources included if extension enabled by configure.ac rules + +# MIT Shared Memory extension +MITSHM_SRCS = shm.c shmint.h +if MITSHM +BUILTIN_SRCS += $(MITSHM_SRCS) +endif + +# XVideo extension +XV_SRCS = xvmain.c xvdisp.c xvmc.c xvdix.h xvmcext.h xvdisp.h +if XV +MODULE_SRCS += $(XV_SRCS) +endif + +# XResource extension: lets clients get data about per-client resource usage +RES_SRCS = xres.c +if RES +MODULE_SRCS += $(RES_SRCS) +endif + +# MIT ScreenSaver extension +SCREENSAVER_SRCS = saver.c +if SCREENSAVER +MODULE_SRCS += $(SCREENSAVER_SRCS) +endif + +# Xinerama extension: making multiple video devices act as one virtual screen +XINERAMA_SRCS = panoramiX.c panoramiX.h panoramiXh.h panoramiXsrv.h panoramiXprocs.c panoramiXSwap.c +if XINERAMA +BUILTIN_SRCS += $(XINERAMA_SRCS) +if XORG +sdk_HEADERS += panoramiXsrv.h panoramiX.h +endif +endif + +# X-ACE extension: provides hooks for building security policy extensions +# like XC-Security, X-SELinux & XTSol +XACE_SRCS = xace.c xace.h xacestr.h +if XACE +BUILTIN_SRCS += $(XACE_SRCS) +if XORG +sdk_HEADERS += xace.h xacestr.h +endif +endif + +# SELinux extension: provides SELinux policy support for X objects +# requires X-ACE extension +XSELINUX_SRCS = xselinux_ext.c xselinux_hooks.c xselinux_label.c xselinux.h xselinuxint.h +if XSELINUX +MODULE_SRCS += $(XSELINUX_SRCS) +MODULE_LIBS += $(SELINUX_LIBS) +endif + +# Security extension: multi-level security to protect clients from each other +XCSECURITY_SRCS = security.c securitysrv.h +if XCSECURITY +BUILTIN_SRCS += $(XCSECURITY_SRCS) +endif + +# XF86 Big Font extension +BIGFONT_SRCS = xf86bigfont.c xf86bigfontsrv.h +if XF86BIGFONT +BUILTIN_SRCS += $(BIGFONT_SRCS) +endif + +# DPMS extension +DPMS_SRCS = dpms.c dpmsproc.h +if DPMSExtension +MODULE_SRCS += $(DPMS_SRCS) +endif + +# Now take all of the above, mix well, bake for 10 minutes and get libXext*.la + +libXext_la_SOURCES = $(BUILTIN_SRCS) $(MODULE_SRCS) +libXext_la_LIBADD = $(MODULE_LIBS) + +if XORG +libXextbuiltin_la_SOURCES = $(BUILTIN_SRCS) + +libXextmodule_la_SOURCES = $(MODULE_SRCS) +libXextmodule_la_LIBADD = $(MODULE_LIBS) +endif + +EXTRA_DIST = \ + $(MITSHM_SRCS) \ + $(XV_SRCS) \ + $(RES_SRCS) \ + $(SCREENSAVER_SRCS) \ + $(XACE_SRCS) \ + $(XCSECURITY_SRCS) \ + $(XSELINUX_SRCS) \ + $(XINERAMA_SRCS) \ + $(BIGFONT_SRCS) \ + $(DPMS_SRCS) \ + $(GE_SRCS) + diff --git a/xorg-server/Xext/xcalibrate.c b/xorg-server/Xext/xcalibrate.c deleted file mode 100644 index a16c11bab..000000000 --- a/xorg-server/Xext/xcalibrate.c +++ /dev/null @@ -1,297 +0,0 @@ -/*
- * Copyright © 2003 Philip Blundell
- *
- * Permission to use, copy, modify, distribute, and sell this software and its
- * documentation for any purpose is hereby granted without fee, provided that
- * the above copyright notice appear in all copies and that both that
- * copyright notice and this permission notice appear in supporting
- * documentation, and that the name of Philip Blundell not be used in
- * advertising or publicity pertaining to distribution of the software without
- * specific, written prior permission. Philip Blundell makes no
- * representations about the suitability of this software for any purpose. It
- * is provided "as is" without express or implied warranty.
- *
- * PHILIP BLUNDELL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
- * EVENT SHALL PHILIP BLUNDELL BE LIABLE FOR ANY SPECIAL, INDIRECT OR
- * CONSEQUENTIAL DAMAGES OR ANY 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 THIS SOFTWARE.
- */
-
-#ifdef HAVE_KDRIVE_CONFIG_H
-#include <kdrive-config.h>
-#endif
-
-
-#include <X11/X.h>
-#include <X11/Xproto.h>
-#include "misc.h"
-#include "os.h"
-#include "dixstruct.h"
-#include "extnsionst.h"
-#include "swaprep.h"
-#include "protocol-versions.h"
-
-#include <X11/extensions/xcalibrateproto.h>
-#include <X11/extensions/xcalibratewire.h>
-
-extern void (*tslib_raw_event_hook)(int x, int y, int pressure, void *closure);
-extern void *tslib_raw_event_closure;
-
-static CARD8 XCalibrateReqCode;
-int XCalibrateEventBase;
-int XCalibrateReqBase;
-int XCalibrateErrorBase;
-
-static ClientPtr xcalibrate_client;
-
-static void
-xcalibrate_event_hook (int x, int y, int pressure, void *closure)
-{
- ClientPtr pClient = (ClientPtr) closure;
- xXCalibrateRawTouchscreenEvent ev;
-
- ev.type = XCalibrateEventBase + X_XCalibrateRawTouchscreen;
- ev.x = x;
- ev.y = y;
- ev.pressure = pressure;
-
- WriteEventsToClient (pClient, 1, (xEvent *) &ev);
-}
-
-static int
-ProcXCalibrateQueryVersion (ClientPtr client)
-{
- REQUEST(xXCalibrateQueryVersionReq);
- xXCalibrateQueryVersionReply rep;
- CARD16 client_major, client_minor; /* not used */
-
- REQUEST_SIZE_MATCH (xXCalibrateQueryVersionReq);
-
- client_major = stuff->majorVersion;
- client_minor = stuff->minorVersion;
-
- fprintf(stderr, "%s(): called\n", __func__);
-
- rep.type = X_Reply;
- rep.length = 0;
- rep.sequenceNumber = client->sequence;
- rep.majorVersion = SERVER_XCALIBRATE_MAJOR_VERSION;
- rep.minorVersion = SERVER_XCALIBRATE_MINOR_VERSION;
- if (client->swapped) {
- int n;
- swaps(&rep.sequenceNumber, n);
- swapl(&rep.length, n);
- swaps(&rep.majorVersion, n);
- swaps(&rep.minorVersion, n);
- }
- WriteToClient(client, sizeof (xXCalibrateQueryVersionReply), (char *)&rep);
- return Success;
-}
-
-static int
-SProcXCalibrateQueryVersion (ClientPtr client)
-{
- REQUEST(xXCalibrateQueryVersionReq);
- int n;
-
- REQUEST_SIZE_MATCH (xXCalibrateQueryVersionReq);
- swaps(&stuff->majorVersion,n);
- swaps(&stuff->minorVersion,n);
- return ProcXCalibrateQueryVersion(client);
-}
-
-static int
-ProcXCalibrateSetRawMode (ClientPtr client)
-{
- REQUEST(xXCalibrateRawModeReq);
- xXCalibrateRawModeReply rep;
-
- REQUEST_SIZE_MATCH (xXCalibrateRawModeReq);
-
- memset (&rep, 0, sizeof (rep));
- rep.type = X_Reply;
- rep.sequenceNumber = client->sequence;
-
- if (stuff->on)
- {
- if (xcalibrate_client == NULL)
- {
- /* Start calibrating. */
- xcalibrate_client = client;
- tslib_raw_event_hook = xcalibrate_event_hook;
- tslib_raw_event_closure = client;
- rep.status = GrabSuccess;
- }
- else
- {
- rep.status = AlreadyGrabbed;
- }
- }
- else
- {
- if (xcalibrate_client == client)
- {
- /* Stop calibrating. */
- xcalibrate_client = NULL;
- tslib_raw_event_hook = NULL;
- tslib_raw_event_closure = NULL;
- rep.status = GrabSuccess;
-
- /* Cycle input off and on to reload configuration. */
- KdDisableInput ();
- KdEnableInput ();
- }
- else
- {
- rep.status = AlreadyGrabbed;
- }
- }
-
- if (client->swapped)
- {
- int n;
-
- swaps (&rep.sequenceNumber, n);
- swaps (&rep.status, n);
- }
- WriteToClient(client, sizeof (rep), (char *) &rep);
- return Success;
-}
-
-static int
-SProcXCalibrateSetRawMode (ClientPtr client)
-{
- REQUEST(xXCalibrateRawModeReq);
- int n;
-
- REQUEST_SIZE_MATCH (xXCalibrateRawModeReq);
-
- swaps(&stuff->on, n);
-
- return ProcXCalibrateSetRawMode(client);
-}
-
-static int
-ProcXCalibrateScreenToCoord (ClientPtr client)
-{
- REQUEST(xXCalibrateScreenToCoordReq);
- xXCalibrateScreenToCoordReply rep;
-
- REQUEST_SIZE_MATCH (xXCalibrateScreenToCoordReq);
-
- memset (&rep, 0, sizeof (rep));
- rep.type = X_Reply;
- rep.sequenceNumber = client->sequence;
- rep.x = stuff->x;
- rep.y = stuff->y;
-
- KdScreenToPointerCoords(&rep.x, &rep.y);
-
- if (client->swapped)
- {
- int n;
-
- swaps (&rep.x, n);
- swaps (&rep.y, n);
- }
- WriteToClient(client, sizeof (rep), (char *) &rep);
- return Success;
-}
-
-static int
-SProcXCalibrateScreenToCoord (ClientPtr client)
-{
- REQUEST(xXCalibrateScreenToCoordReq);
- int n;
-
- REQUEST_SIZE_MATCH (xXCalibrateScreenToCoordReq);
-
- swaps(&stuff->x, n);
- swaps(&stuff->y, n);
-
- return ProcXCalibrateScreenToCoord(client);
-}
-
-static int
-ProcXCalibrateDispatch (ClientPtr client)
-{
- REQUEST(xReq);
- switch (stuff->data) {
- case X_XCalibrateQueryVersion:
- return ProcXCalibrateQueryVersion(client);
- case X_XCalibrateRawMode:
- return ProcXCalibrateSetRawMode(client);
- case X_XCalibrateScreenToCoord:
- return ProcXCalibrateScreenToCoord(client);
-
- default: break;
- }
-
- return BadRequest;
-}
-
-static int
-SProcXCalibrateDispatch (ClientPtr client)
-{
- REQUEST(xReq);
- int n;
-
- swaps(&stuff->length,n);
-
- switch (stuff->data) {
- case X_XCalibrateQueryVersion:
- return SProcXCalibrateQueryVersion(client);
- case X_XCalibrateRawMode:
- return SProcXCalibrateSetRawMode(client);
- case X_XCalibrateScreenToCoord:
- return SProcXCalibrateScreenToCoord(client);
-
- default: break;
- }
-
- return BadRequest;
-}
-
-static void
-XCalibrateClientCallback (CallbackListPtr *list,
- pointer closure,
- pointer data)
-{
- NewClientInfoRec *clientinfo = (NewClientInfoRec *) data;
- ClientPtr pClient = clientinfo->client;
-
- if (clientinfo->setup == NULL
- && xcalibrate_client != NULL
- && xcalibrate_client == pClient)
- {
- /* Stop calibrating. */
- xcalibrate_client = NULL;
- tslib_raw_event_hook = NULL;
- tslib_raw_event_closure = NULL;
- }
-}
-
-void
-XCalibrateExtensionInit(void)
-{
- ExtensionEntry *extEntry;
-
- if (!AddCallback (&ClientStateCallback, XCalibrateClientCallback, 0))
- return;
-
- extEntry = AddExtension(XCALIBRATE_NAME, XCalibrateNumberEvents, XCalibrateNumberErrors,
- ProcXCalibrateDispatch, SProcXCalibrateDispatch,
- NULL, StandardMinorOpcode);
-
- if (!extEntry)
- return;
-
- XCalibrateReqCode = (unsigned char)extEntry->base;
- XCalibrateEventBase = extEntry->eventBase;
- XCalibrateErrorBase = extEntry->errorBase;
-
- xcalibrate_client = 0;
-}
diff --git a/xorg-server/Xext/xselinux_hooks.c b/xorg-server/Xext/xselinux_hooks.c index 57e49c090..f1d8e5d2f 100644 --- a/xorg-server/Xext/xselinux_hooks.c +++ b/xorg-server/Xext/xselinux_hooks.c @@ -1,935 +1,935 @@ -/************************************************************
-
-Author: Eamon Walsh <ewalsh@tycho.nsa.gov>
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-this permission notice appear in supporting documentation. This permission
-notice shall be included in all copies or substantial portions of the
-Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
-AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-********************************************************/
-
-/*
- * Portions of this code copyright (c) 2005 by Trusted Computer Solutions, Inc.
- * All rights reserved.
- */
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#include <sys/socket.h>
-#include <stdio.h>
-#include <stdarg.h>
-
-#include <libaudit.h>
-
-#include <X11/Xatom.h>
-#include "selection.h"
-#include "inputstr.h"
-#include "scrnintstr.h"
-#include "windowstr.h"
-#include "propertyst.h"
-#include "extnsionst.h"
-#include "xacestr.h"
-#include "../os/osdep.h"
-#define _XSELINUX_NEED_FLASK_MAP
-#include "xselinuxint.h"
-
-
-/* structure passed to auditing callback */
-typedef struct {
- ClientPtr client; /* client */
- DeviceIntPtr dev; /* device */
- char *command; /* client's executable path */
- unsigned id; /* resource id, if any */
- int restype; /* resource type, if any */
- int event; /* event type, if any */
- Atom property; /* property name, if any */
- Atom selection; /* selection name, if any */
- char *extension; /* extension name, if any */
-} SELinuxAuditRec;
-
-/* private state keys */
-DevPrivateKeyRec subjectKeyRec;
-DevPrivateKeyRec objectKeyRec;
-DevPrivateKeyRec dataKeyRec;
-
-/* audit file descriptor */
-static int audit_fd;
-
-/* atoms for window label properties */
-static Atom atom_ctx;
-static Atom atom_client_ctx;
-
-/* The unlabeled SID */
-static security_id_t unlabeled_sid;
-
-/* forward declarations */
-static void SELinuxScreen(CallbackListPtr *, pointer, pointer);
-
-/* "true" pointer value for use as callback data */
-static pointer truep = (pointer)1;
-
-
-/*
- * Performs an SELinux permission check.
- */
-static int
-SELinuxDoCheck(SELinuxSubjectRec *subj, SELinuxObjectRec *obj,
- security_class_t class, Mask mode, SELinuxAuditRec *auditdata)
-{
- /* serverClient requests OK */
- if (subj->privileged)
- return Success;
-
- auditdata->command = subj->command;
- errno = 0;
-
- if (avc_has_perm(subj->sid, obj->sid, class, mode, &subj->aeref,
- auditdata) < 0) {
- if (mode == DixUnknownAccess)
- return Success; /* DixUnknownAccess requests OK ... for now */
- if (errno == EACCES)
- return BadAccess;
- ErrorF("SELinux: avc_has_perm: unexpected error %d\n", errno);
- return BadValue;
- }
-
- return Success;
-}
-
-/*
- * Labels a newly connected client.
- */
-static void
-SELinuxLabelClient(ClientPtr client)
-{
- int fd = XaceGetConnectionNumber(client);
- SELinuxSubjectRec *subj;
- SELinuxObjectRec *obj;
- security_context_t ctx;
-
- subj = dixLookupPrivate(&client->devPrivates, subjectKey);
- obj = dixLookupPrivate(&client->devPrivates, objectKey);
-
- /* Try to get a context from the socket */
- if (fd < 0 || getpeercon_raw(fd, &ctx) < 0) {
- /* Otherwise, fall back to a default context */
- ctx = SELinuxDefaultClientLabel();
- }
-
- /* For local clients, try and determine the executable name */
- if (XaceIsLocal(client)) {
- struct ucred creds;
- socklen_t len = sizeof(creds);
- char path[PATH_MAX + 1];
- size_t bytes;
-
- memset(&creds, 0, sizeof(creds));
- if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &creds, &len) < 0)
- goto finish;
-
- snprintf(path, PATH_MAX + 1, "/proc/%d/cmdline", creds.pid);
- fd = open(path, O_RDONLY);
- if (fd < 0)
- goto finish;
-
- bytes = read(fd, path, PATH_MAX + 1);
- close(fd);
- if (bytes <= 0)
- goto finish;
-
- strncpy(subj->command, path, COMMAND_LEN - 1);
- }
-
-finish:
- /* Get a SID from the context */
- if (avc_context_to_sid_raw(ctx, &subj->sid) < 0)
- FatalError("SELinux: client %d: context_to_sid_raw(%s) failed\n",
- client->index, ctx);
-
- obj->sid = subj->sid;
- freecon(ctx);
-}
-
-/*
- * Labels initial server objects.
- */
-static void
-SELinuxLabelInitial(void)
-{
- int i;
- XaceScreenAccessRec srec;
- SELinuxSubjectRec *subj;
- SELinuxObjectRec *obj;
- security_context_t ctx;
- pointer unused;
-
- /* Do the serverClient */
- subj = dixLookupPrivate(&serverClient->devPrivates, subjectKey);
- obj = dixLookupPrivate(&serverClient->devPrivates, objectKey);
- subj->privileged = 1;
-
- /* Use the context of the X server process for the serverClient */
- if (getcon_raw(&ctx) < 0)
- FatalError("SELinux: couldn't get context of X server process\n");
-
- /* Get a SID from the context */
- if (avc_context_to_sid_raw(ctx, &subj->sid) < 0)
- FatalError("SELinux: serverClient: context_to_sid(%s) failed\n", ctx);
-
- obj->sid = subj->sid;
- freecon(ctx);
-
- srec.client = serverClient;
- srec.access_mode = DixCreateAccess;
- srec.status = Success;
-
- for (i = 0; i < screenInfo.numScreens; i++) {
- /* Do the screen object */
- srec.screen = screenInfo.screens[i];
- SELinuxScreen(NULL, NULL, &srec);
-
- /* Do the default colormap */
- dixLookupResourceByType(&unused, screenInfo.screens[i]->defColormap,
- RT_COLORMAP, serverClient, DixCreateAccess);
- }
-}
-
-/*
- * Labels new resource objects.
- */
-static int
-SELinuxLabelResource(XaceResourceAccessRec *rec, SELinuxSubjectRec *subj,
- SELinuxObjectRec *obj, security_class_t class)
-{
- int offset;
- security_id_t tsid;
-
- /* Check for a create context */
- if (rec->rtype & RC_DRAWABLE && subj->win_create_sid) {
- obj->sid = subj->win_create_sid;
- return Success;
- }
-
- if (rec->parent)
- offset = dixLookupPrivateOffset(rec->ptype);
-
- if (rec->parent && offset >= 0) {
- /* Use the SID of the parent object in the labeling operation */
- PrivateRec **privatePtr = DEVPRIV_AT(rec->parent, offset);
- SELinuxObjectRec *pobj = dixLookupPrivate(privatePtr, objectKey);
- tsid = pobj->sid;
- } else {
- /* Use the SID of the subject */
- tsid = subj->sid;
- }
-
- /* Perform a transition to obtain the final SID */
- if (avc_compute_create(subj->sid, tsid, class, &obj->sid) < 0) {
- ErrorF("SELinux: a compute_create call failed!\n");
- return BadValue;
- }
-
- return Success;
-}
-
-
-/*
- * Libselinux Callbacks
- */
-
-static int
-SELinuxAudit(void *auditdata,
- security_class_t class,
- char *msgbuf,
- size_t msgbufsize)
-{
- SELinuxAuditRec *audit = auditdata;
- ClientPtr client = audit->client;
- char idNum[16];
- const char *propertyName, *selectionName;
- int major = -1, minor = -1;
-
- if (client) {
- REQUEST(xReq);
- if (stuff) {
- major = stuff->reqType;
- minor = MinorOpcodeOfRequest(client);
- }
- }
- if (audit->id)
- snprintf(idNum, 16, "%x", audit->id);
-
- propertyName = audit->property ? NameForAtom(audit->property) : NULL;
- selectionName = audit->selection ? NameForAtom(audit->selection) : NULL;
-
- return snprintf(msgbuf, msgbufsize,
- "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
- (major >= 0) ? "request=" : "",
- (major >= 0) ? LookupRequestName(major, minor) : "",
- audit->command ? " comm=" : "",
- audit->command ? audit->command : "",
- audit->dev ? " xdevice=\"" : "",
- audit->dev ? audit->dev->name : "",
- audit->dev ? "\"" : "",
- audit->id ? " resid=" : "",
- audit->id ? idNum : "",
- audit->restype ? " restype=" : "",
- audit->restype ? LookupResourceName(audit->restype) : "",
- audit->event ? " event=" : "",
- audit->event ? LookupEventName(audit->event & 127) : "",
- audit->property ? " property=" : "",
- audit->property ? propertyName : "",
- audit->selection ? " selection=" : "",
- audit->selection ? selectionName : "",
- audit->extension ? " extension=" : "",
- audit->extension ? audit->extension : "");
-}
-
-static int
-SELinuxLog(int type, const char *fmt, ...)
-{
- va_list ap;
- char buf[MAX_AUDIT_MESSAGE_LENGTH];
- int rc, aut;
-
- switch (type) {
- case SELINUX_INFO:
- aut = AUDIT_USER_MAC_POLICY_LOAD;
- break;
- case SELINUX_AVC:
- aut = AUDIT_USER_AVC;
- break;
- default:
- aut = AUDIT_USER_SELINUX_ERR;
- break;
- }
-
- va_start(ap, fmt);
- vsnprintf(buf, MAX_AUDIT_MESSAGE_LENGTH, fmt, ap);
- rc = audit_log_user_avc_message(audit_fd, aut, buf, NULL, NULL, NULL, 0);
- va_end(ap);
- LogMessageVerb(X_WARNING, 0, "%s", buf);
- return 0;
-}
-
-/*
- * XACE Callbacks
- */
-
-static void
-SELinuxDevice(CallbackListPtr *pcbl, pointer unused, pointer calldata)
-{
- XaceDeviceAccessRec *rec = calldata;
- SELinuxSubjectRec *subj;
- SELinuxObjectRec *obj;
- SELinuxAuditRec auditdata = { .client = rec->client, .dev = rec->dev };
- security_class_t cls;
- int rc;
-
- subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey);
- obj = dixLookupPrivate(&rec->dev->devPrivates, objectKey);
-
- /* If this is a new object that needs labeling, do it now */
- if (rec->access_mode & DixCreateAccess) {
- SELinuxSubjectRec *dsubj;
- dsubj = dixLookupPrivate(&rec->dev->devPrivates, subjectKey);
-
- if (subj->dev_create_sid) {
- /* Label the device with the create context */
- obj->sid = subj->dev_create_sid;
- dsubj->sid = subj->dev_create_sid;
- } else {
- /* Label the device directly with the process SID */
- obj->sid = subj->sid;
- dsubj->sid = subj->sid;
- }
- }
-
- cls = IsPointerDevice(rec->dev) ? SECCLASS_X_POINTER : SECCLASS_X_KEYBOARD;
- rc = SELinuxDoCheck(subj, obj, cls, rec->access_mode, &auditdata);
- if (rc != Success)
- rec->status = rc;
-}
-
-static void
-SELinuxSend(CallbackListPtr *pcbl, pointer unused, pointer calldata)
-{
- XaceSendAccessRec *rec = calldata;
- SELinuxSubjectRec *subj;
- SELinuxObjectRec *obj, ev_sid;
- SELinuxAuditRec auditdata = { .client = rec->client, .dev = rec->dev };
- security_class_t class;
- int rc, i, type;
-
- if (rec->dev)
- subj = dixLookupPrivate(&rec->dev->devPrivates, subjectKey);
- else
- subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey);
-
- obj = dixLookupPrivate(&rec->pWin->devPrivates, objectKey);
-
- /* Check send permission on window */
- rc = SELinuxDoCheck(subj, obj, SECCLASS_X_DRAWABLE, DixSendAccess,
- &auditdata);
- if (rc != Success)
- goto err;
-
- /* Check send permission on specific event types */
- for (i = 0; i < rec->count; i++) {
- type = rec->events[i].u.u.type;
- class = (type & 128) ? SECCLASS_X_FAKEEVENT : SECCLASS_X_EVENT;
-
- rc = SELinuxEventToSID(type, obj->sid, &ev_sid);
- if (rc != Success)
- goto err;
-
- auditdata.event = type;
- rc = SELinuxDoCheck(subj, &ev_sid, class, DixSendAccess, &auditdata);
- if (rc != Success)
- goto err;
- }
- return;
-err:
- rec->status = rc;
-}
-
-static void
-SELinuxReceive(CallbackListPtr *pcbl, pointer unused, pointer calldata)
-{
- XaceReceiveAccessRec *rec = calldata;
- SELinuxSubjectRec *subj;
- SELinuxObjectRec *obj, ev_sid;
- SELinuxAuditRec auditdata = { .client = NULL };
- security_class_t class;
- int rc, i, type;
-
- subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey);
- obj = dixLookupPrivate(&rec->pWin->devPrivates, objectKey);
-
- /* Check receive permission on window */
- rc = SELinuxDoCheck(subj, obj, SECCLASS_X_DRAWABLE, DixReceiveAccess,
- &auditdata);
- if (rc != Success)
- goto err;
-
- /* Check receive permission on specific event types */
- for (i = 0; i < rec->count; i++) {
- type = rec->events[i].u.u.type;
- class = (type & 128) ? SECCLASS_X_FAKEEVENT : SECCLASS_X_EVENT;
-
- rc = SELinuxEventToSID(type, obj->sid, &ev_sid);
- if (rc != Success)
- goto err;
-
- auditdata.event = type;
- rc = SELinuxDoCheck(subj, &ev_sid, class, DixReceiveAccess, &auditdata);
- if (rc != Success)
- goto err;
- }
- return;
-err:
- rec->status = rc;
-}
-
-static void
-SELinuxExtension(CallbackListPtr *pcbl, pointer unused, pointer calldata)
-{
- XaceExtAccessRec *rec = calldata;
- SELinuxSubjectRec *subj, *serv;
- SELinuxObjectRec *obj;
- SELinuxAuditRec auditdata = { .client = rec->client };
- int rc;
-
- subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey);
- obj = dixLookupPrivate(&rec->ext->devPrivates, objectKey);
-
- /* If this is a new object that needs labeling, do it now */
- /* XXX there should be a separate callback for this */
- if (obj->sid == NULL) {
- security_id_t sid;
-
- serv = dixLookupPrivate(&serverClient->devPrivates, subjectKey);
- rc = SELinuxExtensionToSID(rec->ext->name, &sid);
- if (rc != Success) {
- rec->status = rc;
- return;
- }
-
- /* Perform a transition to obtain the final SID */
- if (avc_compute_create(serv->sid, sid, SECCLASS_X_EXTENSION,
- &obj->sid) < 0) {
- ErrorF("SELinux: a SID transition call failed!\n");
- rec->status = BadValue;
- return;
- }
- }
-
- /* Perform the security check */
- auditdata.extension = rec->ext->name;
- rc = SELinuxDoCheck(subj, obj, SECCLASS_X_EXTENSION, rec->access_mode,
- &auditdata);
- if (rc != Success)
- rec->status = rc;
-}
-
-static void
-SELinuxSelection(CallbackListPtr *pcbl, pointer unused, pointer calldata)
-{
- XaceSelectionAccessRec *rec = calldata;
- SELinuxSubjectRec *subj;
- SELinuxObjectRec *obj, *data;
- Selection *pSel = *rec->ppSel;
- Atom name = pSel->selection;
- Mask access_mode = rec->access_mode;
- SELinuxAuditRec auditdata = { .client = rec->client, .selection = name };
- security_id_t tsid;
- int rc;
-
- subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey);
- obj = dixLookupPrivate(&pSel->devPrivates, objectKey);
-
- /* If this is a new object that needs labeling, do it now */
- if (access_mode & DixCreateAccess) {
- rc = SELinuxSelectionToSID(name, subj, &obj->sid, &obj->poly);
- if (rc != Success)
- obj->sid = unlabeled_sid;
- access_mode = DixSetAttrAccess;
- }
- /* If this is a polyinstantiated object, find the right instance */
- else if (obj->poly) {
- rc = SELinuxSelectionToSID(name, subj, &tsid, NULL);
- if (rc != Success) {
- rec->status = rc;
- return;
- }
- while (pSel->selection != name || obj->sid != tsid) {
- if ((pSel = pSel->next) == NULL)
- break;
- obj = dixLookupPrivate(&pSel->devPrivates, objectKey);
- }
-
- if (pSel)
- *rec->ppSel = pSel;
- else {
- rec->status = BadMatch;
- return;
- }
- }
-
- /* Perform the security check */
- rc = SELinuxDoCheck(subj, obj, SECCLASS_X_SELECTION, access_mode,
- &auditdata);
- if (rc != Success)
- rec->status = rc;
-
- /* Label the content (advisory only) */
- if (access_mode & DixSetAttrAccess) {
- data = dixLookupPrivate(&pSel->devPrivates, dataKey);
- if (subj->sel_create_sid)
- data->sid = subj->sel_create_sid;
- else
- data->sid = obj->sid;
- }
-}
-
-static void
-SELinuxProperty(CallbackListPtr *pcbl, pointer unused, pointer calldata)
-{
- XacePropertyAccessRec *rec = calldata;
- SELinuxSubjectRec *subj;
- SELinuxObjectRec *obj, *data;
- PropertyPtr pProp = *rec->ppProp;
- Atom name = pProp->propertyName;
- SELinuxAuditRec auditdata = { .client = rec->client, .property = name };
- security_id_t tsid;
- int rc;
-
- /* Don't care about the new content check */
- if (rec->access_mode & DixPostAccess)
- return;
-
- subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey);
- obj = dixLookupPrivate(&pProp->devPrivates, objectKey);
-
- /* If this is a new object that needs labeling, do it now */
- if (rec->access_mode & DixCreateAccess) {
- rc = SELinuxPropertyToSID(name, subj, &obj->sid, &obj->poly);
- if (rc != Success) {
- rec->status = rc;
- return;
- }
- }
- /* If this is a polyinstantiated object, find the right instance */
- else if (obj->poly) {
- rc = SELinuxPropertyToSID(name, subj, &tsid, NULL);
- if (rc != Success) {
- rec->status = rc;
- return;
- }
- while (pProp->propertyName != name || obj->sid != tsid) {
- if ((pProp = pProp->next) == NULL)
- break;
- obj = dixLookupPrivate(&pProp->devPrivates, objectKey);
- }
-
- if (pProp)
- *rec->ppProp = pProp;
- else {
- rec->status = BadMatch;
- return;
- }
- }
-
- /* Perform the security check */
- rc = SELinuxDoCheck(subj, obj, SECCLASS_X_PROPERTY, rec->access_mode,
- &auditdata);
- if (rc != Success)
- rec->status = rc;
-
- /* Label the content (advisory only) */
- if (rec->access_mode & DixWriteAccess) {
- data = dixLookupPrivate(&pProp->devPrivates, dataKey);
- if (subj->prp_create_sid)
- data->sid = subj->prp_create_sid;
- else
- data->sid = obj->sid;
- }
-}
-
-static void
-SELinuxResource(CallbackListPtr *pcbl, pointer unused, pointer calldata)
-{
- XaceResourceAccessRec *rec = calldata;
- SELinuxSubjectRec *subj;
- SELinuxObjectRec *obj;
- SELinuxAuditRec auditdata = { .client = rec->client };
- Mask access_mode = rec->access_mode;
- PrivateRec **privatePtr;
- security_class_t class;
- int rc, offset;
-
- subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey);
-
- /* Determine if the resource object has a devPrivates field */
- offset = dixLookupPrivateOffset(rec->rtype);
- if (offset < 0) {
- /* No: use the SID of the owning client */
- class = SECCLASS_X_RESOURCE;
- privatePtr = &clients[CLIENT_ID(rec->id)]->devPrivates;
- obj = dixLookupPrivate(privatePtr, objectKey);
- } else {
- /* Yes: use the SID from the resource object itself */
- class = SELinuxTypeToClass(rec->rtype);
- privatePtr = DEVPRIV_AT(rec->res, offset);
- obj = dixLookupPrivate(privatePtr, objectKey);
- }
-
- /* If this is a new object that needs labeling, do it now */
- if (access_mode & DixCreateAccess && offset >= 0) {
- rc = SELinuxLabelResource(rec, subj, obj, class);
- if (rc != Success) {
- rec->status = rc;
- return;
- }
- }
-
- /* Collapse generic resource permissions down to read/write */
- if (class == SECCLASS_X_RESOURCE) {
- access_mode = !!(rec->access_mode & SELinuxReadMask); /* rd */
- access_mode |= !!(rec->access_mode & ~SELinuxReadMask) << 1; /* wr */
- }
-
- /* Perform the security check */
- auditdata.restype = rec->rtype;
- auditdata.id = rec->id;
- rc = SELinuxDoCheck(subj, obj, class, access_mode, &auditdata);
- if (rc != Success)
- rec->status = rc;
-
- /* Perform the background none check on windows */
- if (access_mode & DixCreateAccess && rec->rtype == RT_WINDOW) {
- rc = SELinuxDoCheck(subj, obj, class, DixBlendAccess, &auditdata);
- if (rc != Success)
- ((WindowPtr)rec->res)->forcedBG = TRUE;
- }
-}
-
-static void
-SELinuxScreen(CallbackListPtr *pcbl, pointer is_saver, pointer calldata)
-{
- XaceScreenAccessRec *rec = calldata;
- SELinuxSubjectRec *subj;
- SELinuxObjectRec *obj;
- SELinuxAuditRec auditdata = { .client = rec->client };
- Mask access_mode = rec->access_mode;
- int rc;
-
- subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey);
- obj = dixLookupPrivate(&rec->screen->devPrivates, objectKey);
-
- /* If this is a new object that needs labeling, do it now */
- if (access_mode & DixCreateAccess) {
- /* Perform a transition to obtain the final SID */
- if (avc_compute_create(subj->sid, subj->sid, SECCLASS_X_SCREEN,
- &obj->sid) < 0) {
- ErrorF("SELinux: a compute_create call failed!\n");
- rec->status = BadValue;
- return;
- }
- }
-
- if (is_saver)
- access_mode <<= 2;
-
- rc = SELinuxDoCheck(subj, obj, SECCLASS_X_SCREEN, access_mode, &auditdata);
- if (rc != Success)
- rec->status = rc;
-}
-
-static void
-SELinuxClient(CallbackListPtr *pcbl, pointer unused, pointer calldata)
-{
- XaceClientAccessRec *rec = calldata;
- SELinuxSubjectRec *subj;
- SELinuxObjectRec *obj;
- SELinuxAuditRec auditdata = { .client = rec->client };
- int rc;
-
- subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey);
- obj = dixLookupPrivate(&rec->target->devPrivates, objectKey);
-
- rc = SELinuxDoCheck(subj, obj, SECCLASS_X_CLIENT, rec->access_mode,
- &auditdata);
- if (rc != Success)
- rec->status = rc;
-}
-
-static void
-SELinuxServer(CallbackListPtr *pcbl, pointer unused, pointer calldata)
-{
- XaceServerAccessRec *rec = calldata;
- SELinuxSubjectRec *subj;
- SELinuxObjectRec *obj;
- SELinuxAuditRec auditdata = { .client = rec->client };
- int rc;
-
- subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey);
- obj = dixLookupPrivate(&serverClient->devPrivates, objectKey);
-
- rc = SELinuxDoCheck(subj, obj, SECCLASS_X_SERVER, rec->access_mode,
- &auditdata);
- if (rc != Success)
- rec->status = rc;
-}
-
-
-/*
- * DIX Callbacks
- */
-
-static void
-SELinuxClientState(CallbackListPtr *pcbl, pointer unused, pointer calldata)
-{
- NewClientInfoRec *pci = calldata;
-
- switch (pci->client->clientState) {
- case ClientStateInitial:
- SELinuxLabelClient(pci->client);
- break;
-
- default:
- break;
- }
-}
-
-static void
-SELinuxResourceState(CallbackListPtr *pcbl, pointer unused, pointer calldata)
-{
- ResourceStateInfoRec *rec = calldata;
- SELinuxSubjectRec *subj;
- SELinuxObjectRec *obj;
- WindowPtr pWin;
-
- if (rec->type != RT_WINDOW)
- return;
- if (rec->state != ResourceStateAdding)
- return;
-
- pWin = (WindowPtr)rec->value;
- subj = dixLookupPrivate(&wClient(pWin)->devPrivates, subjectKey);
-
- if (subj->sid) {
- security_context_t ctx;
- int rc = avc_sid_to_context_raw(subj->sid, &ctx);
- if (rc < 0)
- FatalError("SELinux: Failed to get security context!\n");
- rc = dixChangeWindowProperty(serverClient,
- pWin, atom_client_ctx, XA_STRING, 8,
- PropModeReplace, strlen(ctx), ctx, FALSE);
- if (rc != Success)
- FatalError("SELinux: Failed to set label property on window!\n");
- freecon(ctx);
- } else
- FatalError("SELinux: Unexpected unlabeled client found\n");
-
- obj = dixLookupPrivate(&pWin->devPrivates, objectKey);
-
- if (obj->sid) {
- security_context_t ctx;
- int rc = avc_sid_to_context_raw(obj->sid, &ctx);
- if (rc < 0)
- FatalError("SELinux: Failed to get security context!\n");
- rc = dixChangeWindowProperty(serverClient,
- pWin, atom_ctx, XA_STRING, 8,
- PropModeReplace, strlen(ctx), ctx, FALSE);
- if (rc != Success)
- FatalError("SELinux: Failed to set label property on window!\n");
- freecon(ctx);
- } else
- FatalError("SELinux: Unexpected unlabeled window found\n");
-}
-
-
-static int netlink_fd;
-
-static void
-SELinuxBlockHandler(void *data, struct timeval **tv, void *read_mask)
-{
-}
-
-static void
-SELinuxWakeupHandler(void *data, int err, void *read_mask)
-{
- if (FD_ISSET(netlink_fd, (fd_set *)read_mask))
- avc_netlink_check_nb();
-}
-
-void
-SELinuxFlaskReset(void)
-{
- /* Unregister callbacks */
- DeleteCallback(&ClientStateCallback, SELinuxClientState, NULL);
- DeleteCallback(&ResourceStateCallback, SELinuxResourceState, NULL);
-
- XaceDeleteCallback(XACE_EXT_DISPATCH, SELinuxExtension, NULL);
- XaceDeleteCallback(XACE_RESOURCE_ACCESS, SELinuxResource, NULL);
- XaceDeleteCallback(XACE_DEVICE_ACCESS, SELinuxDevice, NULL);
- XaceDeleteCallback(XACE_PROPERTY_ACCESS, SELinuxProperty, NULL);
- XaceDeleteCallback(XACE_SEND_ACCESS, SELinuxSend, NULL);
- XaceDeleteCallback(XACE_RECEIVE_ACCESS, SELinuxReceive, NULL);
- XaceDeleteCallback(XACE_CLIENT_ACCESS, SELinuxClient, NULL);
- XaceDeleteCallback(XACE_EXT_ACCESS, SELinuxExtension, NULL);
- XaceDeleteCallback(XACE_SERVER_ACCESS, SELinuxServer, NULL);
- XaceDeleteCallback(XACE_SELECTION_ACCESS, SELinuxSelection, NULL);
- XaceDeleteCallback(XACE_SCREEN_ACCESS, SELinuxScreen, NULL);
- XaceDeleteCallback(XACE_SCREENSAVER_ACCESS, SELinuxScreen, truep);
-
- /* Tear down SELinux stuff */
- audit_close(audit_fd);
- avc_netlink_release_fd();
- RemoveBlockAndWakeupHandlers(SELinuxBlockHandler, SELinuxWakeupHandler,
- NULL);
- RemoveGeneralSocket(netlink_fd);
-
- avc_destroy();
-}
-
-void
-SELinuxFlaskInit(void)
-{
- struct selinux_opt avc_option = { AVC_OPT_SETENFORCE, (char *)0 };
- security_context_t ctx;
- int ret = TRUE;
-
- switch(selinuxEnforcingState) {
- case SELINUX_MODE_ENFORCING:
- LogMessage(X_INFO, "SELinux: Configured in enforcing mode\n");
- avc_option.value = (char *)1;
- break;
- case SELINUX_MODE_PERMISSIVE:
- LogMessage(X_INFO, "SELinux: Configured in permissive mode\n");
- avc_option.value = (char *)0;
- break;
- default:
- avc_option.type = AVC_OPT_UNUSED;
- break;
- }
-
- /* Set up SELinux stuff */
- selinux_set_callback(SELINUX_CB_LOG, (union selinux_callback)SELinuxLog);
- selinux_set_callback(SELINUX_CB_AUDIT, (union selinux_callback)SELinuxAudit);
-
- if (selinux_set_mapping(map) < 0) {
- if (errno == EINVAL) {
- ErrorF("SELinux: Invalid object class mapping, disabling SELinux support.\n");
- return;
- }
- FatalError("SELinux: Failed to set up security class mapping\n");
- }
-
- if (avc_open(&avc_option, 1) < 0)
- FatalError("SELinux: Couldn't initialize SELinux userspace AVC\n");
-
- if (security_get_initial_context_raw("unlabeled", &ctx) < 0)
- FatalError("SELinux: Failed to look up unlabeled context\n");
- if (avc_context_to_sid_raw(ctx, &unlabeled_sid) < 0)
- FatalError("SELinux: a context_to_SID call failed!\n");
- freecon(ctx);
-
- /* Prepare for auditing */
- audit_fd = audit_open();
- if (audit_fd < 0)
- FatalError("SELinux: Failed to open the system audit log\n");
-
- /* Allocate private storage */
- if (!dixRegisterPrivateKey(subjectKey, PRIVATE_XSELINUX, sizeof(SELinuxSubjectRec)) ||
- !dixRegisterPrivateKey(objectKey, PRIVATE_XSELINUX, sizeof(SELinuxObjectRec)) ||
- !dixRegisterPrivateKey(dataKey, PRIVATE_XSELINUX, sizeof(SELinuxObjectRec)))
- FatalError("SELinux: Failed to allocate private storage.\n");
-
- /* Create atoms for doing window labeling */
- atom_ctx = MakeAtom("_SELINUX_CONTEXT", 16, TRUE);
- if (atom_ctx == BAD_RESOURCE)
- FatalError("SELinux: Failed to create atom\n");
- atom_client_ctx = MakeAtom("_SELINUX_CLIENT_CONTEXT", 23, TRUE);
- if (atom_client_ctx == BAD_RESOURCE)
- FatalError("SELinux: Failed to create atom\n");
-
- netlink_fd = avc_netlink_acquire_fd();
- AddGeneralSocket(netlink_fd);
- RegisterBlockAndWakeupHandlers(SELinuxBlockHandler, SELinuxWakeupHandler,
- NULL);
-
- /* Register callbacks */
- ret &= AddCallback(&ClientStateCallback, SELinuxClientState, NULL);
- ret &= AddCallback(&ResourceStateCallback, SELinuxResourceState, NULL);
-
- ret &= XaceRegisterCallback(XACE_EXT_DISPATCH, SELinuxExtension, NULL);
- ret &= XaceRegisterCallback(XACE_RESOURCE_ACCESS, SELinuxResource, NULL);
- ret &= XaceRegisterCallback(XACE_DEVICE_ACCESS, SELinuxDevice, NULL);
- ret &= XaceRegisterCallback(XACE_PROPERTY_ACCESS, SELinuxProperty, NULL);
- ret &= XaceRegisterCallback(XACE_SEND_ACCESS, SELinuxSend, NULL);
- ret &= XaceRegisterCallback(XACE_RECEIVE_ACCESS, SELinuxReceive, NULL);
- ret &= XaceRegisterCallback(XACE_CLIENT_ACCESS, SELinuxClient, NULL);
- ret &= XaceRegisterCallback(XACE_EXT_ACCESS, SELinuxExtension, NULL);
- ret &= XaceRegisterCallback(XACE_SERVER_ACCESS, SELinuxServer, NULL);
- ret &= XaceRegisterCallback(XACE_SELECTION_ACCESS, SELinuxSelection, NULL);
- ret &= XaceRegisterCallback(XACE_SCREEN_ACCESS, SELinuxScreen, NULL);
- ret &= XaceRegisterCallback(XACE_SCREENSAVER_ACCESS, SELinuxScreen, truep);
- if (!ret)
- FatalError("SELinux: Failed to register one or more callbacks\n");
-
- /* Label objects that were created before we could register ourself */
- SELinuxLabelInitial();
-}
+/************************************************************ + +Author: Eamon Walsh <ewalsh@tycho.nsa.gov> + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +this permission notice appear in supporting documentation. This permission +notice shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +********************************************************/ + +/* + * Portions of this code copyright (c) 2005 by Trusted Computer Solutions, Inc. + * All rights reserved. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include <sys/socket.h> +#include <stdio.h> +#include <stdarg.h> + +#include <libaudit.h> + +#include <X11/Xatom.h> +#include "selection.h" +#include "inputstr.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include "propertyst.h" +#include "extnsionst.h" +#include "xacestr.h" +#include "client.h" +#include "../os/osdep.h" +#define _XSELINUX_NEED_FLASK_MAP +#include "xselinuxint.h" + + +/* structure passed to auditing callback */ +typedef struct { + ClientPtr client; /* client */ + DeviceIntPtr dev; /* device */ + char *command; /* client's executable path */ + unsigned id; /* resource id, if any */ + int restype; /* resource type, if any */ + int event; /* event type, if any */ + Atom property; /* property name, if any */ + Atom selection; /* selection name, if any */ + char *extension; /* extension name, if any */ +} SELinuxAuditRec; + +/* private state keys */ +DevPrivateKeyRec subjectKeyRec; +DevPrivateKeyRec objectKeyRec; +DevPrivateKeyRec dataKeyRec; + +/* audit file descriptor */ +static int audit_fd; + +/* atoms for window label properties */ +static Atom atom_ctx; +static Atom atom_client_ctx; + +/* The unlabeled SID */ +static security_id_t unlabeled_sid; + +/* forward declarations */ +static void SELinuxScreen(CallbackListPtr *, pointer, pointer); + +/* "true" pointer value for use as callback data */ +static pointer truep = (pointer)1; + + +/* + * Performs an SELinux permission check. + */ +static int +SELinuxDoCheck(SELinuxSubjectRec *subj, SELinuxObjectRec *obj, + security_class_t class, Mask mode, SELinuxAuditRec *auditdata) +{ + /* serverClient requests OK */ + if (subj->privileged) + return Success; + + auditdata->command = subj->command; + errno = 0; + + if (avc_has_perm(subj->sid, obj->sid, class, mode, &subj->aeref, + auditdata) < 0) { + if (mode == DixUnknownAccess) + return Success; /* DixUnknownAccess requests OK ... for now */ + if (errno == EACCES) + return BadAccess; + ErrorF("SELinux: avc_has_perm: unexpected error %d\n", errno); + return BadValue; + } + + return Success; +} + +/* + * Labels a newly connected client. + */ +static void +SELinuxLabelClient(ClientPtr client) +{ + int fd = XaceGetConnectionNumber(client); + SELinuxSubjectRec *subj; + SELinuxObjectRec *obj; + security_context_t ctx; + + subj = dixLookupPrivate(&client->devPrivates, subjectKey); + obj = dixLookupPrivate(&client->devPrivates, objectKey); + + /* Try to get a context from the socket */ + if (fd < 0 || getpeercon_raw(fd, &ctx) < 0) { + /* Otherwise, fall back to a default context */ + ctx = SELinuxDefaultClientLabel(); + } + + /* For local clients, try and determine the executable name */ + if (XaceIsLocal(client)) { + /* Get cached command name if CLIENTIDS is enabled. */ + const char *cmdname = GetClientCmdName(client); + Bool cached = (cmdname != NULL); + /* If CLIENTIDS is disabled, figure out the command name from + * scratch. */ + if (!cmdname) + { + pid_t pid = DetermineClientPid(client); + if (pid != -1) + DetermineClientCmd(pid, &cmdname, NULL); + } + + if (!cmdname) + goto finish; + + strncpy(subj->command, cmdname, COMMAND_LEN - 1); + + if (!cached) + free((void *) cmdname); /* const char * */ + } + +finish: + /* Get a SID from the context */ + if (avc_context_to_sid_raw(ctx, &subj->sid) < 0) + FatalError("SELinux: client %d: context_to_sid_raw(%s) failed\n", + client->index, ctx); + + obj->sid = subj->sid; + freecon(ctx); +} + +/* + * Labels initial server objects. + */ +static void +SELinuxLabelInitial(void) +{ + int i; + XaceScreenAccessRec srec; + SELinuxSubjectRec *subj; + SELinuxObjectRec *obj; + security_context_t ctx; + pointer unused; + + /* Do the serverClient */ + subj = dixLookupPrivate(&serverClient->devPrivates, subjectKey); + obj = dixLookupPrivate(&serverClient->devPrivates, objectKey); + subj->privileged = 1; + + /* Use the context of the X server process for the serverClient */ + if (getcon_raw(&ctx) < 0) + FatalError("SELinux: couldn't get context of X server process\n"); + + /* Get a SID from the context */ + if (avc_context_to_sid_raw(ctx, &subj->sid) < 0) + FatalError("SELinux: serverClient: context_to_sid(%s) failed\n", ctx); + + obj->sid = subj->sid; + freecon(ctx); + + srec.client = serverClient; + srec.access_mode = DixCreateAccess; + srec.status = Success; + + for (i = 0; i < screenInfo.numScreens; i++) { + /* Do the screen object */ + srec.screen = screenInfo.screens[i]; + SELinuxScreen(NULL, NULL, &srec); + + /* Do the default colormap */ + dixLookupResourceByType(&unused, screenInfo.screens[i]->defColormap, + RT_COLORMAP, serverClient, DixCreateAccess); + } +} + +/* + * Labels new resource objects. + */ +static int +SELinuxLabelResource(XaceResourceAccessRec *rec, SELinuxSubjectRec *subj, + SELinuxObjectRec *obj, security_class_t class) +{ + int offset; + security_id_t tsid; + + /* Check for a create context */ + if (rec->rtype & RC_DRAWABLE && subj->win_create_sid) { + obj->sid = subj->win_create_sid; + return Success; + } + + if (rec->parent) + offset = dixLookupPrivateOffset(rec->ptype); + + if (rec->parent && offset >= 0) { + /* Use the SID of the parent object in the labeling operation */ + PrivateRec **privatePtr = DEVPRIV_AT(rec->parent, offset); + SELinuxObjectRec *pobj = dixLookupPrivate(privatePtr, objectKey); + tsid = pobj->sid; + } else { + /* Use the SID of the subject */ + tsid = subj->sid; + } + + /* Perform a transition to obtain the final SID */ + if (avc_compute_create(subj->sid, tsid, class, &obj->sid) < 0) { + ErrorF("SELinux: a compute_create call failed!\n"); + return BadValue; + } + + return Success; +} + + +/* + * Libselinux Callbacks + */ + +static int +SELinuxAudit(void *auditdata, + security_class_t class, + char *msgbuf, + size_t msgbufsize) +{ + SELinuxAuditRec *audit = auditdata; + ClientPtr client = audit->client; + char idNum[16]; + const char *propertyName, *selectionName; + int major = -1, minor = -1; + + if (client) { + REQUEST(xReq); + if (stuff) { + major = stuff->reqType; + minor = MinorOpcodeOfRequest(client); + } + } + if (audit->id) + snprintf(idNum, 16, "%x", audit->id); + + propertyName = audit->property ? NameForAtom(audit->property) : NULL; + selectionName = audit->selection ? NameForAtom(audit->selection) : NULL; + + return snprintf(msgbuf, msgbufsize, + "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", + (major >= 0) ? "request=" : "", + (major >= 0) ? LookupRequestName(major, minor) : "", + audit->command ? " comm=" : "", + audit->command ? audit->command : "", + audit->dev ? " xdevice=\"" : "", + audit->dev ? audit->dev->name : "", + audit->dev ? "\"" : "", + audit->id ? " resid=" : "", + audit->id ? idNum : "", + audit->restype ? " restype=" : "", + audit->restype ? LookupResourceName(audit->restype) : "", + audit->event ? " event=" : "", + audit->event ? LookupEventName(audit->event & 127) : "", + audit->property ? " property=" : "", + audit->property ? propertyName : "", + audit->selection ? " selection=" : "", + audit->selection ? selectionName : "", + audit->extension ? " extension=" : "", + audit->extension ? audit->extension : ""); +} + +static int +SELinuxLog(int type, const char *fmt, ...) +{ + va_list ap; + char buf[MAX_AUDIT_MESSAGE_LENGTH]; + int rc, aut; + + switch (type) { + case SELINUX_INFO: + aut = AUDIT_USER_MAC_POLICY_LOAD; + break; + case SELINUX_AVC: + aut = AUDIT_USER_AVC; + break; + default: + aut = AUDIT_USER_SELINUX_ERR; + break; + } + + va_start(ap, fmt); + vsnprintf(buf, MAX_AUDIT_MESSAGE_LENGTH, fmt, ap); + rc = audit_log_user_avc_message(audit_fd, aut, buf, NULL, NULL, NULL, 0); + va_end(ap); + LogMessageVerb(X_WARNING, 0, "%s", buf); + return 0; +} + +/* + * XACE Callbacks + */ + +static void +SELinuxDevice(CallbackListPtr *pcbl, pointer unused, pointer calldata) +{ + XaceDeviceAccessRec *rec = calldata; + SELinuxSubjectRec *subj; + SELinuxObjectRec *obj; + SELinuxAuditRec auditdata = { .client = rec->client, .dev = rec->dev }; + security_class_t cls; + int rc; + + subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey); + obj = dixLookupPrivate(&rec->dev->devPrivates, objectKey); + + /* If this is a new object that needs labeling, do it now */ + if (rec->access_mode & DixCreateAccess) { + SELinuxSubjectRec *dsubj; + dsubj = dixLookupPrivate(&rec->dev->devPrivates, subjectKey); + + if (subj->dev_create_sid) { + /* Label the device with the create context */ + obj->sid = subj->dev_create_sid; + dsubj->sid = subj->dev_create_sid; + } else { + /* Label the device directly with the process SID */ + obj->sid = subj->sid; + dsubj->sid = subj->sid; + } + } + + cls = IsPointerDevice(rec->dev) ? SECCLASS_X_POINTER : SECCLASS_X_KEYBOARD; + rc = SELinuxDoCheck(subj, obj, cls, rec->access_mode, &auditdata); + if (rc != Success) + rec->status = rc; +} + +static void +SELinuxSend(CallbackListPtr *pcbl, pointer unused, pointer calldata) +{ + XaceSendAccessRec *rec = calldata; + SELinuxSubjectRec *subj; + SELinuxObjectRec *obj, ev_sid; + SELinuxAuditRec auditdata = { .client = rec->client, .dev = rec->dev }; + security_class_t class; + int rc, i, type; + + if (rec->dev) + subj = dixLookupPrivate(&rec->dev->devPrivates, subjectKey); + else + subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey); + + obj = dixLookupPrivate(&rec->pWin->devPrivates, objectKey); + + /* Check send permission on window */ + rc = SELinuxDoCheck(subj, obj, SECCLASS_X_DRAWABLE, DixSendAccess, + &auditdata); + if (rc != Success) + goto err; + + /* Check send permission on specific event types */ + for (i = 0; i < rec->count; i++) { + type = rec->events[i].u.u.type; + class = (type & 128) ? SECCLASS_X_FAKEEVENT : SECCLASS_X_EVENT; + + rc = SELinuxEventToSID(type, obj->sid, &ev_sid); + if (rc != Success) + goto err; + + auditdata.event = type; + rc = SELinuxDoCheck(subj, &ev_sid, class, DixSendAccess, &auditdata); + if (rc != Success) + goto err; + } + return; +err: + rec->status = rc; +} + +static void +SELinuxReceive(CallbackListPtr *pcbl, pointer unused, pointer calldata) +{ + XaceReceiveAccessRec *rec = calldata; + SELinuxSubjectRec *subj; + SELinuxObjectRec *obj, ev_sid; + SELinuxAuditRec auditdata = { .client = NULL }; + security_class_t class; + int rc, i, type; + + subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey); + obj = dixLookupPrivate(&rec->pWin->devPrivates, objectKey); + + /* Check receive permission on window */ + rc = SELinuxDoCheck(subj, obj, SECCLASS_X_DRAWABLE, DixReceiveAccess, + &auditdata); + if (rc != Success) + goto err; + + /* Check receive permission on specific event types */ + for (i = 0; i < rec->count; i++) { + type = rec->events[i].u.u.type; + class = (type & 128) ? SECCLASS_X_FAKEEVENT : SECCLASS_X_EVENT; + + rc = SELinuxEventToSID(type, obj->sid, &ev_sid); + if (rc != Success) + goto err; + + auditdata.event = type; + rc = SELinuxDoCheck(subj, &ev_sid, class, DixReceiveAccess, &auditdata); + if (rc != Success) + goto err; + } + return; +err: + rec->status = rc; +} + +static void +SELinuxExtension(CallbackListPtr *pcbl, pointer unused, pointer calldata) +{ + XaceExtAccessRec *rec = calldata; + SELinuxSubjectRec *subj, *serv; + SELinuxObjectRec *obj; + SELinuxAuditRec auditdata = { .client = rec->client }; + int rc; + + subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey); + obj = dixLookupPrivate(&rec->ext->devPrivates, objectKey); + + /* If this is a new object that needs labeling, do it now */ + /* XXX there should be a separate callback for this */ + if (obj->sid == NULL) { + security_id_t sid; + + serv = dixLookupPrivate(&serverClient->devPrivates, subjectKey); + rc = SELinuxExtensionToSID(rec->ext->name, &sid); + if (rc != Success) { + rec->status = rc; + return; + } + + /* Perform a transition to obtain the final SID */ + if (avc_compute_create(serv->sid, sid, SECCLASS_X_EXTENSION, + &obj->sid) < 0) { + ErrorF("SELinux: a SID transition call failed!\n"); + rec->status = BadValue; + return; + } + } + + /* Perform the security check */ + auditdata.extension = rec->ext->name; + rc = SELinuxDoCheck(subj, obj, SECCLASS_X_EXTENSION, rec->access_mode, + &auditdata); + if (rc != Success) + rec->status = rc; +} + +static void +SELinuxSelection(CallbackListPtr *pcbl, pointer unused, pointer calldata) +{ + XaceSelectionAccessRec *rec = calldata; + SELinuxSubjectRec *subj; + SELinuxObjectRec *obj, *data; + Selection *pSel = *rec->ppSel; + Atom name = pSel->selection; + Mask access_mode = rec->access_mode; + SELinuxAuditRec auditdata = { .client = rec->client, .selection = name }; + security_id_t tsid; + int rc; + + subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey); + obj = dixLookupPrivate(&pSel->devPrivates, objectKey); + + /* If this is a new object that needs labeling, do it now */ + if (access_mode & DixCreateAccess) { + rc = SELinuxSelectionToSID(name, subj, &obj->sid, &obj->poly); + if (rc != Success) + obj->sid = unlabeled_sid; + access_mode = DixSetAttrAccess; + } + /* If this is a polyinstantiated object, find the right instance */ + else if (obj->poly) { + rc = SELinuxSelectionToSID(name, subj, &tsid, NULL); + if (rc != Success) { + rec->status = rc; + return; + } + while (pSel->selection != name || obj->sid != tsid) { + if ((pSel = pSel->next) == NULL) + break; + obj = dixLookupPrivate(&pSel->devPrivates, objectKey); + } + + if (pSel) + *rec->ppSel = pSel; + else { + rec->status = BadMatch; + return; + } + } + + /* Perform the security check */ + rc = SELinuxDoCheck(subj, obj, SECCLASS_X_SELECTION, access_mode, + &auditdata); + if (rc != Success) + rec->status = rc; + + /* Label the content (advisory only) */ + if (access_mode & DixSetAttrAccess) { + data = dixLookupPrivate(&pSel->devPrivates, dataKey); + if (subj->sel_create_sid) + data->sid = subj->sel_create_sid; + else + data->sid = obj->sid; + } +} + +static void +SELinuxProperty(CallbackListPtr *pcbl, pointer unused, pointer calldata) +{ + XacePropertyAccessRec *rec = calldata; + SELinuxSubjectRec *subj; + SELinuxObjectRec *obj, *data; + PropertyPtr pProp = *rec->ppProp; + Atom name = pProp->propertyName; + SELinuxAuditRec auditdata = { .client = rec->client, .property = name }; + security_id_t tsid; + int rc; + + /* Don't care about the new content check */ + if (rec->access_mode & DixPostAccess) + return; + + subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey); + obj = dixLookupPrivate(&pProp->devPrivates, objectKey); + + /* If this is a new object that needs labeling, do it now */ + if (rec->access_mode & DixCreateAccess) { + rc = SELinuxPropertyToSID(name, subj, &obj->sid, &obj->poly); + if (rc != Success) { + rec->status = rc; + return; + } + } + /* If this is a polyinstantiated object, find the right instance */ + else if (obj->poly) { + rc = SELinuxPropertyToSID(name, subj, &tsid, NULL); + if (rc != Success) { + rec->status = rc; + return; + } + while (pProp->propertyName != name || obj->sid != tsid) { + if ((pProp = pProp->next) == NULL) + break; + obj = dixLookupPrivate(&pProp->devPrivates, objectKey); + } + + if (pProp) + *rec->ppProp = pProp; + else { + rec->status = BadMatch; + return; + } + } + + /* Perform the security check */ + rc = SELinuxDoCheck(subj, obj, SECCLASS_X_PROPERTY, rec->access_mode, + &auditdata); + if (rc != Success) + rec->status = rc; + + /* Label the content (advisory only) */ + if (rec->access_mode & DixWriteAccess) { + data = dixLookupPrivate(&pProp->devPrivates, dataKey); + if (subj->prp_create_sid) + data->sid = subj->prp_create_sid; + else + data->sid = obj->sid; + } +} + +static void +SELinuxResource(CallbackListPtr *pcbl, pointer unused, pointer calldata) +{ + XaceResourceAccessRec *rec = calldata; + SELinuxSubjectRec *subj; + SELinuxObjectRec *obj; + SELinuxAuditRec auditdata = { .client = rec->client }; + Mask access_mode = rec->access_mode; + PrivateRec **privatePtr; + security_class_t class; + int rc, offset; + + subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey); + + /* Determine if the resource object has a devPrivates field */ + offset = dixLookupPrivateOffset(rec->rtype); + if (offset < 0) { + /* No: use the SID of the owning client */ + class = SECCLASS_X_RESOURCE; + privatePtr = &clients[CLIENT_ID(rec->id)]->devPrivates; + obj = dixLookupPrivate(privatePtr, objectKey); + } else { + /* Yes: use the SID from the resource object itself */ + class = SELinuxTypeToClass(rec->rtype); + privatePtr = DEVPRIV_AT(rec->res, offset); + obj = dixLookupPrivate(privatePtr, objectKey); + } + + /* If this is a new object that needs labeling, do it now */ + if (access_mode & DixCreateAccess && offset >= 0) { + rc = SELinuxLabelResource(rec, subj, obj, class); + if (rc != Success) { + rec->status = rc; + return; + } + } + + /* Collapse generic resource permissions down to read/write */ + if (class == SECCLASS_X_RESOURCE) { + access_mode = !!(rec->access_mode & SELinuxReadMask); /* rd */ + access_mode |= !!(rec->access_mode & ~SELinuxReadMask) << 1; /* wr */ + } + + /* Perform the security check */ + auditdata.restype = rec->rtype; + auditdata.id = rec->id; + rc = SELinuxDoCheck(subj, obj, class, access_mode, &auditdata); + if (rc != Success) + rec->status = rc; + + /* Perform the background none check on windows */ + if (access_mode & DixCreateAccess && rec->rtype == RT_WINDOW) { + rc = SELinuxDoCheck(subj, obj, class, DixBlendAccess, &auditdata); + if (rc != Success) + ((WindowPtr)rec->res)->forcedBG = TRUE; + } +} + +static void +SELinuxScreen(CallbackListPtr *pcbl, pointer is_saver, pointer calldata) +{ + XaceScreenAccessRec *rec = calldata; + SELinuxSubjectRec *subj; + SELinuxObjectRec *obj; + SELinuxAuditRec auditdata = { .client = rec->client }; + Mask access_mode = rec->access_mode; + int rc; + + subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey); + obj = dixLookupPrivate(&rec->screen->devPrivates, objectKey); + + /* If this is a new object that needs labeling, do it now */ + if (access_mode & DixCreateAccess) { + /* Perform a transition to obtain the final SID */ + if (avc_compute_create(subj->sid, subj->sid, SECCLASS_X_SCREEN, + &obj->sid) < 0) { + ErrorF("SELinux: a compute_create call failed!\n"); + rec->status = BadValue; + return; + } + } + + if (is_saver) + access_mode <<= 2; + + rc = SELinuxDoCheck(subj, obj, SECCLASS_X_SCREEN, access_mode, &auditdata); + if (rc != Success) + rec->status = rc; +} + +static void +SELinuxClient(CallbackListPtr *pcbl, pointer unused, pointer calldata) +{ + XaceClientAccessRec *rec = calldata; + SELinuxSubjectRec *subj; + SELinuxObjectRec *obj; + SELinuxAuditRec auditdata = { .client = rec->client }; + int rc; + + subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey); + obj = dixLookupPrivate(&rec->target->devPrivates, objectKey); + + rc = SELinuxDoCheck(subj, obj, SECCLASS_X_CLIENT, rec->access_mode, + &auditdata); + if (rc != Success) + rec->status = rc; +} + +static void +SELinuxServer(CallbackListPtr *pcbl, pointer unused, pointer calldata) +{ + XaceServerAccessRec *rec = calldata; + SELinuxSubjectRec *subj; + SELinuxObjectRec *obj; + SELinuxAuditRec auditdata = { .client = rec->client }; + int rc; + + subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey); + obj = dixLookupPrivate(&serverClient->devPrivates, objectKey); + + rc = SELinuxDoCheck(subj, obj, SECCLASS_X_SERVER, rec->access_mode, + &auditdata); + if (rc != Success) + rec->status = rc; +} + + +/* + * DIX Callbacks + */ + +static void +SELinuxClientState(CallbackListPtr *pcbl, pointer unused, pointer calldata) +{ + NewClientInfoRec *pci = calldata; + + switch (pci->client->clientState) { + case ClientStateInitial: + SELinuxLabelClient(pci->client); + break; + + default: + break; + } +} + +static void +SELinuxResourceState(CallbackListPtr *pcbl, pointer unused, pointer calldata) +{ + ResourceStateInfoRec *rec = calldata; + SELinuxSubjectRec *subj; + SELinuxObjectRec *obj; + WindowPtr pWin; + + if (rec->type != RT_WINDOW) + return; + if (rec->state != ResourceStateAdding) + return; + + pWin = (WindowPtr)rec->value; + subj = dixLookupPrivate(&wClient(pWin)->devPrivates, subjectKey); + + if (subj->sid) { + security_context_t ctx; + int rc = avc_sid_to_context_raw(subj->sid, &ctx); + if (rc < 0) + FatalError("SELinux: Failed to get security context!\n"); + rc = dixChangeWindowProperty(serverClient, + pWin, atom_client_ctx, XA_STRING, 8, + PropModeReplace, strlen(ctx), ctx, FALSE); + if (rc != Success) + FatalError("SELinux: Failed to set label property on window!\n"); + freecon(ctx); + } else + FatalError("SELinux: Unexpected unlabeled client found\n"); + + obj = dixLookupPrivate(&pWin->devPrivates, objectKey); + + if (obj->sid) { + security_context_t ctx; + int rc = avc_sid_to_context_raw(obj->sid, &ctx); + if (rc < 0) + FatalError("SELinux: Failed to get security context!\n"); + rc = dixChangeWindowProperty(serverClient, + pWin, atom_ctx, XA_STRING, 8, + PropModeReplace, strlen(ctx), ctx, FALSE); + if (rc != Success) + FatalError("SELinux: Failed to set label property on window!\n"); + freecon(ctx); + } else + FatalError("SELinux: Unexpected unlabeled window found\n"); +} + + +static int netlink_fd; + +static void +SELinuxBlockHandler(void *data, struct timeval **tv, void *read_mask) +{ +} + +static void +SELinuxWakeupHandler(void *data, int err, void *read_mask) +{ + if (FD_ISSET(netlink_fd, (fd_set *)read_mask)) + avc_netlink_check_nb(); +} + +void +SELinuxFlaskReset(void) +{ + /* Unregister callbacks */ + DeleteCallback(&ClientStateCallback, SELinuxClientState, NULL); + DeleteCallback(&ResourceStateCallback, SELinuxResourceState, NULL); + + XaceDeleteCallback(XACE_EXT_DISPATCH, SELinuxExtension, NULL); + XaceDeleteCallback(XACE_RESOURCE_ACCESS, SELinuxResource, NULL); + XaceDeleteCallback(XACE_DEVICE_ACCESS, SELinuxDevice, NULL); + XaceDeleteCallback(XACE_PROPERTY_ACCESS, SELinuxProperty, NULL); + XaceDeleteCallback(XACE_SEND_ACCESS, SELinuxSend, NULL); + XaceDeleteCallback(XACE_RECEIVE_ACCESS, SELinuxReceive, NULL); + XaceDeleteCallback(XACE_CLIENT_ACCESS, SELinuxClient, NULL); + XaceDeleteCallback(XACE_EXT_ACCESS, SELinuxExtension, NULL); + XaceDeleteCallback(XACE_SERVER_ACCESS, SELinuxServer, NULL); + XaceDeleteCallback(XACE_SELECTION_ACCESS, SELinuxSelection, NULL); + XaceDeleteCallback(XACE_SCREEN_ACCESS, SELinuxScreen, NULL); + XaceDeleteCallback(XACE_SCREENSAVER_ACCESS, SELinuxScreen, truep); + + /* Tear down SELinux stuff */ + audit_close(audit_fd); + avc_netlink_release_fd(); + RemoveBlockAndWakeupHandlers(SELinuxBlockHandler, SELinuxWakeupHandler, + NULL); + RemoveGeneralSocket(netlink_fd); + + avc_destroy(); +} + +void +SELinuxFlaskInit(void) +{ + struct selinux_opt avc_option = { AVC_OPT_SETENFORCE, (char *)0 }; + security_context_t ctx; + int ret = TRUE; + + switch(selinuxEnforcingState) { + case SELINUX_MODE_ENFORCING: + LogMessage(X_INFO, "SELinux: Configured in enforcing mode\n"); + avc_option.value = (char *)1; + break; + case SELINUX_MODE_PERMISSIVE: + LogMessage(X_INFO, "SELinux: Configured in permissive mode\n"); + avc_option.value = (char *)0; + break; + default: + avc_option.type = AVC_OPT_UNUSED; + break; + } + + /* Set up SELinux stuff */ + selinux_set_callback(SELINUX_CB_LOG, (union selinux_callback)SELinuxLog); + selinux_set_callback(SELINUX_CB_AUDIT, (union selinux_callback)SELinuxAudit); + + if (selinux_set_mapping(map) < 0) { + if (errno == EINVAL) { + ErrorF("SELinux: Invalid object class mapping, disabling SELinux support.\n"); + return; + } + FatalError("SELinux: Failed to set up security class mapping\n"); + } + + if (avc_open(&avc_option, 1) < 0) + FatalError("SELinux: Couldn't initialize SELinux userspace AVC\n"); + + if (security_get_initial_context_raw("unlabeled", &ctx) < 0) + FatalError("SELinux: Failed to look up unlabeled context\n"); + if (avc_context_to_sid_raw(ctx, &unlabeled_sid) < 0) + FatalError("SELinux: a context_to_SID call failed!\n"); + freecon(ctx); + + /* Prepare for auditing */ + audit_fd = audit_open(); + if (audit_fd < 0) + FatalError("SELinux: Failed to open the system audit log\n"); + + /* Allocate private storage */ + if (!dixRegisterPrivateKey(subjectKey, PRIVATE_XSELINUX, sizeof(SELinuxSubjectRec)) || + !dixRegisterPrivateKey(objectKey, PRIVATE_XSELINUX, sizeof(SELinuxObjectRec)) || + !dixRegisterPrivateKey(dataKey, PRIVATE_XSELINUX, sizeof(SELinuxObjectRec))) + FatalError("SELinux: Failed to allocate private storage.\n"); + + /* Create atoms for doing window labeling */ + atom_ctx = MakeAtom("_SELINUX_CONTEXT", 16, TRUE); + if (atom_ctx == BAD_RESOURCE) + FatalError("SELinux: Failed to create atom\n"); + atom_client_ctx = MakeAtom("_SELINUX_CLIENT_CONTEXT", 23, TRUE); + if (atom_client_ctx == BAD_RESOURCE) + FatalError("SELinux: Failed to create atom\n"); + + netlink_fd = avc_netlink_acquire_fd(); + AddGeneralSocket(netlink_fd); + RegisterBlockAndWakeupHandlers(SELinuxBlockHandler, SELinuxWakeupHandler, + NULL); + + /* Register callbacks */ + ret &= AddCallback(&ClientStateCallback, SELinuxClientState, NULL); + ret &= AddCallback(&ResourceStateCallback, SELinuxResourceState, NULL); + + ret &= XaceRegisterCallback(XACE_EXT_DISPATCH, SELinuxExtension, NULL); + ret &= XaceRegisterCallback(XACE_RESOURCE_ACCESS, SELinuxResource, NULL); + ret &= XaceRegisterCallback(XACE_DEVICE_ACCESS, SELinuxDevice, NULL); + ret &= XaceRegisterCallback(XACE_PROPERTY_ACCESS, SELinuxProperty, NULL); + ret &= XaceRegisterCallback(XACE_SEND_ACCESS, SELinuxSend, NULL); + ret &= XaceRegisterCallback(XACE_RECEIVE_ACCESS, SELinuxReceive, NULL); + ret &= XaceRegisterCallback(XACE_CLIENT_ACCESS, SELinuxClient, NULL); + ret &= XaceRegisterCallback(XACE_EXT_ACCESS, SELinuxExtension, NULL); + ret &= XaceRegisterCallback(XACE_SERVER_ACCESS, SELinuxServer, NULL); + ret &= XaceRegisterCallback(XACE_SELECTION_ACCESS, SELinuxSelection, NULL); + ret &= XaceRegisterCallback(XACE_SCREEN_ACCESS, SELinuxScreen, NULL); + ret &= XaceRegisterCallback(XACE_SCREENSAVER_ACCESS, SELinuxScreen, truep); + if (!ret) + FatalError("SELinux: Failed to register one or more callbacks\n"); + + /* Label objects that were created before we could register ourself */ + SELinuxLabelInitial(); +} diff --git a/xorg-server/Xi/exevents.c b/xorg-server/Xi/exevents.c index 327873e29..c7089bb69 100644 --- a/xorg-server/Xi/exevents.c +++ b/xorg-server/Xi/exevents.c @@ -710,10 +710,13 @@ ChangeMasterDeviceClasses(DeviceIntPtr device, DeviceChangedEvent *dce) if (rc != Success) return; /* Device has disappeared */ - if (!slave->u.master) + if (IsMaster(slave)) + return; + + if (IsFloating(slave)) return; /* set floating since the event */ - if (slave->u.master->id != dce->masterid) + if (GetMaster(slave, MASTER_ATTACHED)->id != dce->masterid) return; /* not our slave anymore, don't care */ /* FIXME: we probably need to send a DCE for the new slave now */ @@ -866,7 +869,7 @@ UpdateDeviceState(DeviceIntPtr device, DeviceEvent* event) * event being delivered through the slave first */ for (sd = inputInfo.devices; sd; sd = sd->next) { - if (IsMaster(sd) || sd->u.master != device) + if (IsMaster(sd) || GetMaster(sd, MASTER_POINTER) != device) continue; if (!sd->button) continue; @@ -1006,7 +1009,7 @@ ProcessOtherEvent(InternalEvent *ev, DeviceIntPtr device) b = device->button; k = device->key; - if (IsMaster(device) || !device->u.master) + if (IsMaster(device) || IsFloating(device)) CheckMotion(event, device); switch (event->type) @@ -1047,10 +1050,8 @@ ProcessOtherEvent(InternalEvent *ev, DeviceIntPtr device) switch(event->type) { case ET_KeyPress: - if (!grab && CheckDeviceGrabs(device, event, 0)) { - device->deviceGrab.activatingKey = key; + if (!grab && CheckDeviceGrabs(device, event, 0)) return; - } break; case ET_KeyRelease: if (grab && device->deviceGrab.fromPassiveGrab && @@ -1223,7 +1224,7 @@ DeviceFocusEvent(DeviceIntPtr dev, int type, int mode, int detail, DeviceIntPtr mouse; int btlen, len, i; - mouse = (IsMaster(dev) || dev->u.master) ? GetMaster(dev, MASTER_POINTER) : dev; + mouse = IsFloating(dev) ? dev : GetMaster(dev, MASTER_POINTER); /* XI 2 event */ btlen = (mouse->button) ? bits_to_bytes(mouse->button->numButtons) : 0; @@ -1280,7 +1281,7 @@ DeviceFocusEvent(DeviceIntPtr dev, int type, int mode, int detail, DeliverEventsToWindow(dev, pWin, (xEvent *) & event, 1, DeviceFocusChangeMask, NullGrab); - if ((type == DeviceFocusIn) && + if ((event.type == DeviceFocusIn) && (wOtherInputMasks(pWin)) && (wOtherInputMasks(pWin)->inputEvents[dev->id] & DeviceStateNotifyMask)) { diff --git a/xorg-server/Xi/xichangehierarchy.c b/xorg-server/Xi/xichangehierarchy.c index 6b0288c88..a3dcab57e 100644 --- a/xorg-server/Xi/xichangehierarchy.c +++ b/xorg-server/Xi/xichangehierarchy.c @@ -1,490 +1,492 @@ -/*
- * Copyright 2007-2008 Peter Hutterer
- * Copyright 2009 Red Hat, Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Author: Peter Hutterer, University of South Australia, NICTA
- */
-
-/***********************************************************************
- *
- * Request change in the device hierarchy.
- *
- */
-
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#include <X11/X.h> /* for inputstr.h */
-#include <X11/Xproto.h> /* Request macro */
-#include "inputstr.h" /* DeviceIntPtr */
-#include "windowstr.h" /* window structure */
-#include "scrnintstr.h" /* screen structure */
-#include <X11/extensions/XI.h>
-#include <X11/extensions/XI2proto.h>
-#include <X11/extensions/geproto.h>
-#include "extnsionst.h"
-#include "exevents.h"
-#include "exglobals.h"
-#include "geext.h"
-#include "xace.h"
-#include "xiquerydevice.h" /* for GetDeviceUse */
-
-#include "xkbsrv.h"
-
-#include "xichangehierarchy.h"
-
-/**
- * Send the current state of the device hierarchy to all clients.
- */
-void XISendDeviceHierarchyEvent(int flags[MAXDEVICES])
-{
- xXIHierarchyEvent *ev;
- xXIHierarchyInfo *info;
- DeviceIntRec dummyDev;
- DeviceIntPtr dev;
- int i;
-
- if (!flags)
- return;
-
- ev = calloc(1, sizeof(xXIHierarchyEvent) +
- MAXDEVICES * sizeof(xXIHierarchyInfo));
- ev->type = GenericEvent;
- ev->extension = IReqCode;
- ev->evtype = XI_HierarchyChanged;
- ev->time = GetTimeInMillis();
- ev->flags = 0;
- ev->num_info = inputInfo.numDevices;
-
- info = (xXIHierarchyInfo*)&ev[1];
- for (dev = inputInfo.devices; dev; dev = dev->next)
- {
- info->deviceid = dev->id;
- info->enabled = dev->enabled;
- info->use = GetDeviceUse(dev, &info->attachment);
- info->flags = flags[dev->id];
- ev->flags |= info->flags;
- info++;
- }
- for (dev = inputInfo.off_devices; dev; dev = dev->next)
- {
- info->deviceid = dev->id;
- info->enabled = dev->enabled;
- info->use = GetDeviceUse(dev, &info->attachment);
- info->flags = flags[dev->id];
- ev->flags |= info->flags;
- info++;
- }
-
-
- for (i = 0; i < MAXDEVICES; i++)
- {
- if (flags[i] & (XIMasterRemoved | XISlaveRemoved))
- {
- info->deviceid = i;
- info->enabled = FALSE;
- info->flags = flags[i];
- info->use = 0;
- ev->flags |= info->flags;
- ev->num_info++;
- info++;
- }
- }
-
- ev->length = bytes_to_int32(ev->num_info * sizeof(xXIHierarchyInfo));
-
- dummyDev.id = XIAllDevices;
- SendEventToAllWindows(&dummyDev, (XI_HierarchyChangedMask >> 8), (xEvent*)ev, 1);
- free(ev);
-}
-
-
-/***********************************************************************
- *
- * This procedure allows a client to change the device hierarchy through
- * adding new master devices, removing them, etc.
- *
- */
-
-int SProcXIChangeHierarchy(ClientPtr client)
-{
- char n;
-
- REQUEST(xXIChangeHierarchyReq);
- swaps(&stuff->length, n);
- return (ProcXIChangeHierarchy(client));
-}
-
-static int
-add_master(ClientPtr client, xXIAddMasterInfo *c, int flags[MAXDEVICES])
-{
- DeviceIntPtr ptr, keybd, XTestptr, XTestkeybd;
- char* name;
- int rc;
-
- name = calloc(c->name_len + 1, sizeof(char));
- strncpy(name, (char*)&c[1], c->name_len);
-
- rc = AllocDevicePair(client, name, &ptr, &keybd,
- CorePointerProc, CoreKeyboardProc, TRUE);
- if (rc != Success)
- goto unwind;
-
- if (!c->send_core)
- ptr->coreEvents = keybd->coreEvents = FALSE;
-
- /* Allocate virtual slave devices for xtest events */
- rc = AllocXTestDevice(client, name, &XTestptr, &XTestkeybd, ptr, keybd);
- if (rc != Success)
- {
- DeleteInputDeviceRequest(ptr);
- DeleteInputDeviceRequest(keybd);
- goto unwind;
- }
-
- ActivateDevice(ptr, FALSE);
- ActivateDevice(keybd, FALSE);
- flags[ptr->id] |= XIMasterAdded;
- flags[keybd->id] |= XIMasterAdded;
-
- ActivateDevice(XTestptr, FALSE);
- ActivateDevice(XTestkeybd, FALSE);
- flags[XTestptr->id] |= XISlaveAdded;
- flags[XTestkeybd->id] |= XISlaveAdded;
-
- if (c->enable)
- {
- EnableDevice(ptr, FALSE);
- EnableDevice(keybd, FALSE);
- flags[ptr->id] |= XIDeviceEnabled;
- flags[keybd->id] |= XIDeviceEnabled;
-
- EnableDevice(XTestptr, FALSE);
- EnableDevice(XTestkeybd, FALSE);
- flags[XTestptr->id] |= XIDeviceEnabled;
- flags[XTestkeybd->id] |= XIDeviceEnabled;
- }
-
- /* Attach the XTest virtual devices to the newly
- created master device */
- AttachDevice(NULL, XTestptr, ptr);
- AttachDevice(NULL, XTestkeybd, keybd);
- flags[XTestptr->id] |= XISlaveAttached;
- flags[XTestkeybd->id] |= XISlaveAttached;
-
-unwind:
- free(name);
- return rc;
-}
-
-static int
-remove_master(ClientPtr client, xXIRemoveMasterInfo *r,
- int flags[MAXDEVICES])
-{
- DeviceIntPtr ptr, keybd, XTestptr, XTestkeybd;
- int rc = Success;
-
- if (r->return_mode != XIAttachToMaster &&
- r->return_mode != XIFloating)
- return BadValue;
-
- rc = dixLookupDevice(&ptr, r->deviceid, client, DixDestroyAccess);
- if (rc != Success)
- goto unwind;
-
- if (!IsMaster(ptr))
- {
- client->errorValue = r->deviceid;
- rc = BadDevice;
- goto unwind;
- }
-
- /* XXX: For now, don't allow removal of VCP, VCK */
- if (ptr == inputInfo.pointer || ptr == inputInfo.keyboard)
- {
- rc = BadDevice;
- goto unwind;
- }
-
-
- ptr = GetMaster(ptr, MASTER_POINTER);
- rc = dixLookupDevice(&ptr, ptr->id, client, DixDestroyAccess);
- if (rc != Success)
- goto unwind;
- keybd = GetMaster(ptr, MASTER_KEYBOARD);
- rc = dixLookupDevice(&keybd, keybd->id, client, DixDestroyAccess);
- if (rc != Success)
- goto unwind;
-
- XTestptr = GetXTestDevice(ptr);
- rc = dixLookupDevice(&XTestptr, XTestptr->id, client, DixDestroyAccess);
- if (rc != Success)
- goto unwind;
-
- XTestkeybd = GetXTestDevice(keybd);
- rc = dixLookupDevice(&XTestkeybd, XTestkeybd->id, client,
- DixDestroyAccess);
- if (rc != Success)
- goto unwind;
-
- /* Disabling sends the devices floating, reattach them if
- * desired. */
- if (r->return_mode == XIAttachToMaster)
- {
- DeviceIntPtr attached,
- newptr,
- newkeybd;
-
- rc = dixLookupDevice(&newptr, r->return_pointer, client, DixAddAccess);
- if (rc != Success)
- goto unwind;
-
- if (!IsMaster(newptr))
- {
- client->errorValue = r->return_pointer;
- rc = BadDevice;
- goto unwind;
- }
-
- rc = dixLookupDevice(&newkeybd, r->return_keyboard,
- client, DixAddAccess);
- if (rc != Success)
- goto unwind;
-
- if (!IsMaster(newkeybd))
- {
- client->errorValue = r->return_keyboard;
- rc = BadDevice;
- goto unwind;
- }
-
- for (attached = inputInfo.devices; attached; attached = attached->next)
- {
- if (!IsMaster(attached)) {
- if (attached->u.master == ptr)
- {
- AttachDevice(client, attached, newptr);
- flags[attached->id] |= XISlaveAttached;
- }
- if (attached->u.master == keybd)
- {
- AttachDevice(client, attached, newkeybd);
- flags[attached->id] |= XISlaveAttached;
- }
- }
- }
- }
-
- /* can't disable until we removed pairing */
- keybd->spriteInfo->paired = NULL;
- ptr->spriteInfo->paired = NULL;
- XTestptr->spriteInfo->paired = NULL;
- XTestkeybd->spriteInfo->paired = NULL;
-
- /* disable the remove the devices, XTest devices must be done first
- else the sprites they rely on will be destroyed */
- DisableDevice(XTestptr, FALSE);
- DisableDevice(XTestkeybd, FALSE);
- DisableDevice(keybd, FALSE);
- DisableDevice(ptr, FALSE);
- flags[XTestptr->id] |= XIDeviceDisabled | XISlaveDetached;
- flags[XTestkeybd->id] |= XIDeviceDisabled | XISlaveDetached;
- flags[keybd->id] |= XIDeviceDisabled;
- flags[ptr->id] |= XIDeviceDisabled;
-
- RemoveDevice(XTestptr, FALSE);
- RemoveDevice(XTestkeybd, FALSE);
- RemoveDevice(keybd, FALSE);
- RemoveDevice(ptr, FALSE);
- flags[XTestptr->id] |= XISlaveRemoved;
- flags[XTestkeybd->id] |= XISlaveRemoved;
- flags[keybd->id] |= XIMasterRemoved;
- flags[ptr->id] |= XIMasterRemoved;
-
-unwind:
- return rc;
-}
-
-static int
-detach_slave(ClientPtr client, xXIDetachSlaveInfo *c, int flags[MAXDEVICES])
-{
- DeviceIntPtr dev;
- int rc;
-
- rc = dixLookupDevice(&dev, c->deviceid, client, DixManageAccess);
- if (rc != Success)
- goto unwind;
-
- if (IsMaster(dev))
- {
- client->errorValue = c->deviceid;
- rc = BadDevice;
- goto unwind;
- }
-
- /* Don't allow changes to XTest Devices, these are fixed */
- if (IsXTestDevice(dev, NULL))
- {
- client->errorValue = c->deviceid;
- rc = BadDevice;
- goto unwind;
- }
-
- AttachDevice(client, dev, NULL);
- flags[dev->id] |= XISlaveDetached;
-
-unwind:
- return rc;
-}
-
-static int
-attach_slave(ClientPtr client, xXIAttachSlaveInfo *c,
- int flags[MAXDEVICES])
-{
- DeviceIntPtr dev;
- DeviceIntPtr newmaster;
- int rc;
-
- rc = dixLookupDevice(&dev, c->deviceid, client, DixManageAccess);
- if (rc != Success)
- goto unwind;
-
- if (IsMaster(dev))
- {
- client->errorValue = c->deviceid;
- rc = BadDevice;
- goto unwind;
- }
-
- /* Don't allow changes to XTest Devices, these are fixed */
- if (IsXTestDevice(dev, NULL))
- {
- client->errorValue = c->deviceid;
- rc = BadDevice;
- goto unwind;
- }
-
- rc = dixLookupDevice(&newmaster, c->new_master, client, DixAddAccess);
- if (rc != Success)
- goto unwind;
- if (!IsMaster(newmaster))
- {
- client->errorValue = c->new_master;
- rc = BadDevice;
- goto unwind;
- }
-
- if (!((IsPointerDevice(newmaster) && IsPointerDevice(dev)) ||
- (IsKeyboardDevice(newmaster) && IsKeyboardDevice(dev))))
- {
- rc = BadDevice;
- goto unwind;
- }
-
- AttachDevice(client, dev, newmaster);
- flags[dev->id] |= XISlaveAttached;
-
-unwind:
- return rc;
-}
-
-
-
-#define SWAPIF(cmd) if (client->swapped) { cmd; }
-
-int
-ProcXIChangeHierarchy(ClientPtr client)
-{
- xXIAnyHierarchyChangeInfo *any;
- int required_len = sizeof(xXIChangeHierarchyReq);
- char n;
- int rc = Success;
- int flags[MAXDEVICES] = {0};
-
- REQUEST(xXIChangeHierarchyReq);
- REQUEST_AT_LEAST_SIZE(xXIChangeHierarchyReq);
-
- if (!stuff->num_changes)
- return rc;
-
- any = (xXIAnyHierarchyChangeInfo*)&stuff[1];
- while(stuff->num_changes--)
- {
- SWAPIF(swapl(&any->type, n));
- SWAPIF(swaps(&any->length, n));
-
- required_len += any->length;
- if ((stuff->length * 4) < required_len)
- return BadLength;
-
- switch(any->type)
- {
- case XIAddMaster:
- {
- xXIAddMasterInfo* c = (xXIAddMasterInfo*)any;
- SWAPIF(swaps(&c->name_len, n));
-
- rc = add_master(client, c, flags);
- if (rc != Success)
- goto unwind;
- }
- break;
- case XIRemoveMaster:
- {
- xXIRemoveMasterInfo* r = (xXIRemoveMasterInfo*)any;
-
- rc = remove_master(client, r, flags);
- if (rc != Success)
- goto unwind;
- }
- break;
- case XIDetachSlave:
- {
- xXIDetachSlaveInfo* c = (xXIDetachSlaveInfo*)any;
-
- rc = detach_slave(client, c, flags);
- if (rc != Success)
- goto unwind;
- }
- break;
- case XIAttachSlave:
- {
- xXIAttachSlaveInfo* c = (xXIAttachSlaveInfo*)any;
-
- rc = attach_slave(client, c, flags);
- if (rc != Success)
- goto unwind;
- }
- break;
- }
-
- any = (xXIAnyHierarchyChangeInfo*)((char*)any + any->length * 4);
- }
-
-unwind:
-
- XISendDeviceHierarchyEvent(flags);
- return rc;
-}
-
+/* + * Copyright 2007-2008 Peter Hutterer + * Copyright 2009 Red Hat, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Author: Peter Hutterer, University of South Australia, NICTA + */ + +/*********************************************************************** + * + * Request change in the device hierarchy. + * + */ + + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include <X11/X.h> /* for inputstr.h */ +#include <X11/Xproto.h> /* Request macro */ +#include "inputstr.h" /* DeviceIntPtr */ +#include "windowstr.h" /* window structure */ +#include "scrnintstr.h" /* screen structure */ +#include <X11/extensions/XI.h> +#include <X11/extensions/XI2proto.h> +#include <X11/extensions/geproto.h> +#include "extnsionst.h" +#include "exevents.h" +#include "exglobals.h" +#include "geext.h" +#include "xace.h" +#include "xiquerydevice.h" /* for GetDeviceUse */ + +#include "xkbsrv.h" + +#include "xichangehierarchy.h" + +/** + * Send the current state of the device hierarchy to all clients. + */ +void XISendDeviceHierarchyEvent(int flags[MAXDEVICES]) +{ + xXIHierarchyEvent *ev; + xXIHierarchyInfo *info; + DeviceIntRec dummyDev; + DeviceIntPtr dev; + int i; + + if (!flags) + return; + + ev = calloc(1, sizeof(xXIHierarchyEvent) + + MAXDEVICES * sizeof(xXIHierarchyInfo)); + if (!ev) + return; + ev->type = GenericEvent; + ev->extension = IReqCode; + ev->evtype = XI_HierarchyChanged; + ev->time = GetTimeInMillis(); + ev->flags = 0; + ev->num_info = inputInfo.numDevices; + + info = (xXIHierarchyInfo*)&ev[1]; + for (dev = inputInfo.devices; dev; dev = dev->next) + { + info->deviceid = dev->id; + info->enabled = dev->enabled; + info->use = GetDeviceUse(dev, &info->attachment); + info->flags = flags[dev->id]; + ev->flags |= info->flags; + info++; + } + for (dev = inputInfo.off_devices; dev; dev = dev->next) + { + info->deviceid = dev->id; + info->enabled = dev->enabled; + info->use = GetDeviceUse(dev, &info->attachment); + info->flags = flags[dev->id]; + ev->flags |= info->flags; + info++; + } + + + for (i = 0; i < MAXDEVICES; i++) + { + if (flags[i] & (XIMasterRemoved | XISlaveRemoved)) + { + info->deviceid = i; + info->enabled = FALSE; + info->flags = flags[i]; + info->use = 0; + ev->flags |= info->flags; + ev->num_info++; + info++; + } + } + + ev->length = bytes_to_int32(ev->num_info * sizeof(xXIHierarchyInfo)); + + dummyDev.id = XIAllDevices; + SendEventToAllWindows(&dummyDev, (XI_HierarchyChangedMask >> 8), (xEvent*)ev, 1); + free(ev); +} + + +/*********************************************************************** + * + * This procedure allows a client to change the device hierarchy through + * adding new master devices, removing them, etc. + * + */ + +int SProcXIChangeHierarchy(ClientPtr client) +{ + char n; + + REQUEST(xXIChangeHierarchyReq); + swaps(&stuff->length, n); + return (ProcXIChangeHierarchy(client)); +} + +static int +add_master(ClientPtr client, xXIAddMasterInfo *c, int flags[MAXDEVICES]) +{ + DeviceIntPtr ptr, keybd, XTestptr, XTestkeybd; + char* name; + int rc; + + name = calloc(c->name_len + 1, sizeof(char)); + strncpy(name, (char*)&c[1], c->name_len); + + rc = AllocDevicePair(client, name, &ptr, &keybd, + CorePointerProc, CoreKeyboardProc, TRUE); + if (rc != Success) + goto unwind; + + if (!c->send_core) + ptr->coreEvents = keybd->coreEvents = FALSE; + + /* Allocate virtual slave devices for xtest events */ + rc = AllocXTestDevice(client, name, &XTestptr, &XTestkeybd, ptr, keybd); + if (rc != Success) + { + DeleteInputDeviceRequest(ptr); + DeleteInputDeviceRequest(keybd); + goto unwind; + } + + ActivateDevice(ptr, FALSE); + ActivateDevice(keybd, FALSE); + flags[ptr->id] |= XIMasterAdded; + flags[keybd->id] |= XIMasterAdded; + + ActivateDevice(XTestptr, FALSE); + ActivateDevice(XTestkeybd, FALSE); + flags[XTestptr->id] |= XISlaveAdded; + flags[XTestkeybd->id] |= XISlaveAdded; + + if (c->enable) + { + EnableDevice(ptr, FALSE); + EnableDevice(keybd, FALSE); + flags[ptr->id] |= XIDeviceEnabled; + flags[keybd->id] |= XIDeviceEnabled; + + EnableDevice(XTestptr, FALSE); + EnableDevice(XTestkeybd, FALSE); + flags[XTestptr->id] |= XIDeviceEnabled; + flags[XTestkeybd->id] |= XIDeviceEnabled; + } + + /* Attach the XTest virtual devices to the newly + created master device */ + AttachDevice(NULL, XTestptr, ptr); + AttachDevice(NULL, XTestkeybd, keybd); + flags[XTestptr->id] |= XISlaveAttached; + flags[XTestkeybd->id] |= XISlaveAttached; + +unwind: + free(name); + return rc; +} + +static int +remove_master(ClientPtr client, xXIRemoveMasterInfo *r, + int flags[MAXDEVICES]) +{ + DeviceIntPtr ptr, keybd, XTestptr, XTestkeybd; + int rc = Success; + + if (r->return_mode != XIAttachToMaster && + r->return_mode != XIFloating) + return BadValue; + + rc = dixLookupDevice(&ptr, r->deviceid, client, DixDestroyAccess); + if (rc != Success) + goto unwind; + + if (!IsMaster(ptr)) + { + client->errorValue = r->deviceid; + rc = BadDevice; + goto unwind; + } + + /* XXX: For now, don't allow removal of VCP, VCK */ + if (ptr == inputInfo.pointer || ptr == inputInfo.keyboard) + { + rc = BadDevice; + goto unwind; + } + + + ptr = GetMaster(ptr, MASTER_POINTER); + rc = dixLookupDevice(&ptr, ptr->id, client, DixDestroyAccess); + if (rc != Success) + goto unwind; + keybd = GetMaster(ptr, MASTER_KEYBOARD); + rc = dixLookupDevice(&keybd, keybd->id, client, DixDestroyAccess); + if (rc != Success) + goto unwind; + + XTestptr = GetXTestDevice(ptr); + rc = dixLookupDevice(&XTestptr, XTestptr->id, client, DixDestroyAccess); + if (rc != Success) + goto unwind; + + XTestkeybd = GetXTestDevice(keybd); + rc = dixLookupDevice(&XTestkeybd, XTestkeybd->id, client, + DixDestroyAccess); + if (rc != Success) + goto unwind; + + /* Disabling sends the devices floating, reattach them if + * desired. */ + if (r->return_mode == XIAttachToMaster) + { + DeviceIntPtr attached, + newptr, + newkeybd; + + rc = dixLookupDevice(&newptr, r->return_pointer, client, DixAddAccess); + if (rc != Success) + goto unwind; + + if (!IsMaster(newptr)) + { + client->errorValue = r->return_pointer; + rc = BadDevice; + goto unwind; + } + + rc = dixLookupDevice(&newkeybd, r->return_keyboard, + client, DixAddAccess); + if (rc != Success) + goto unwind; + + if (!IsMaster(newkeybd)) + { + client->errorValue = r->return_keyboard; + rc = BadDevice; + goto unwind; + } + + for (attached = inputInfo.devices; attached; attached = attached->next) + { + if (!IsMaster(attached)) { + if (GetMaster(attached, MASTER_ATTACHED) == ptr) + { + AttachDevice(client, attached, newptr); + flags[attached->id] |= XISlaveAttached; + } + if (GetMaster(attached, MASTER_ATTACHED) == keybd) + { + AttachDevice(client, attached, newkeybd); + flags[attached->id] |= XISlaveAttached; + } + } + } + } + + /* can't disable until we removed pairing */ + keybd->spriteInfo->paired = NULL; + ptr->spriteInfo->paired = NULL; + XTestptr->spriteInfo->paired = NULL; + XTestkeybd->spriteInfo->paired = NULL; + + /* disable the remove the devices, XTest devices must be done first + else the sprites they rely on will be destroyed */ + DisableDevice(XTestptr, FALSE); + DisableDevice(XTestkeybd, FALSE); + DisableDevice(keybd, FALSE); + DisableDevice(ptr, FALSE); + flags[XTestptr->id] |= XIDeviceDisabled | XISlaveDetached; + flags[XTestkeybd->id] |= XIDeviceDisabled | XISlaveDetached; + flags[keybd->id] |= XIDeviceDisabled; + flags[ptr->id] |= XIDeviceDisabled; + + RemoveDevice(XTestptr, FALSE); + RemoveDevice(XTestkeybd, FALSE); + RemoveDevice(keybd, FALSE); + RemoveDevice(ptr, FALSE); + flags[XTestptr->id] |= XISlaveRemoved; + flags[XTestkeybd->id] |= XISlaveRemoved; + flags[keybd->id] |= XIMasterRemoved; + flags[ptr->id] |= XIMasterRemoved; + +unwind: + return rc; +} + +static int +detach_slave(ClientPtr client, xXIDetachSlaveInfo *c, int flags[MAXDEVICES]) +{ + DeviceIntPtr dev; + int rc; + + rc = dixLookupDevice(&dev, c->deviceid, client, DixManageAccess); + if (rc != Success) + goto unwind; + + if (IsMaster(dev)) + { + client->errorValue = c->deviceid; + rc = BadDevice; + goto unwind; + } + + /* Don't allow changes to XTest Devices, these are fixed */ + if (IsXTestDevice(dev, NULL)) + { + client->errorValue = c->deviceid; + rc = BadDevice; + goto unwind; + } + + AttachDevice(client, dev, NULL); + flags[dev->id] |= XISlaveDetached; + +unwind: + return rc; +} + +static int +attach_slave(ClientPtr client, xXIAttachSlaveInfo *c, + int flags[MAXDEVICES]) +{ + DeviceIntPtr dev; + DeviceIntPtr newmaster; + int rc; + + rc = dixLookupDevice(&dev, c->deviceid, client, DixManageAccess); + if (rc != Success) + goto unwind; + + if (IsMaster(dev)) + { + client->errorValue = c->deviceid; + rc = BadDevice; + goto unwind; + } + + /* Don't allow changes to XTest Devices, these are fixed */ + if (IsXTestDevice(dev, NULL)) + { + client->errorValue = c->deviceid; + rc = BadDevice; + goto unwind; + } + + rc = dixLookupDevice(&newmaster, c->new_master, client, DixAddAccess); + if (rc != Success) + goto unwind; + if (!IsMaster(newmaster)) + { + client->errorValue = c->new_master; + rc = BadDevice; + goto unwind; + } + + if (!((IsPointerDevice(newmaster) && IsPointerDevice(dev)) || + (IsKeyboardDevice(newmaster) && IsKeyboardDevice(dev)))) + { + rc = BadDevice; + goto unwind; + } + + AttachDevice(client, dev, newmaster); + flags[dev->id] |= XISlaveAttached; + +unwind: + return rc; +} + + + +#define SWAPIF(cmd) if (client->swapped) { cmd; } + +int +ProcXIChangeHierarchy(ClientPtr client) +{ + xXIAnyHierarchyChangeInfo *any; + int required_len = sizeof(xXIChangeHierarchyReq); + char n; + int rc = Success; + int flags[MAXDEVICES] = {0}; + + REQUEST(xXIChangeHierarchyReq); + REQUEST_AT_LEAST_SIZE(xXIChangeHierarchyReq); + + if (!stuff->num_changes) + return rc; + + any = (xXIAnyHierarchyChangeInfo*)&stuff[1]; + while(stuff->num_changes--) + { + SWAPIF(swapl(&any->type, n)); + SWAPIF(swaps(&any->length, n)); + + required_len += any->length; + if ((stuff->length * 4) < required_len) + return BadLength; + + switch(any->type) + { + case XIAddMaster: + { + xXIAddMasterInfo* c = (xXIAddMasterInfo*)any; + SWAPIF(swaps(&c->name_len, n)); + + rc = add_master(client, c, flags); + if (rc != Success) + goto unwind; + } + break; + case XIRemoveMaster: + { + xXIRemoveMasterInfo* r = (xXIRemoveMasterInfo*)any; + + rc = remove_master(client, r, flags); + if (rc != Success) + goto unwind; + } + break; + case XIDetachSlave: + { + xXIDetachSlaveInfo* c = (xXIDetachSlaveInfo*)any; + + rc = detach_slave(client, c, flags); + if (rc != Success) + goto unwind; + } + break; + case XIAttachSlave: + { + xXIAttachSlaveInfo* c = (xXIAttachSlaveInfo*)any; + + rc = attach_slave(client, c, flags); + if (rc != Success) + goto unwind; + } + break; + } + + any = (xXIAnyHierarchyChangeInfo*)((char*)any + any->length * 4); + } + +unwind: + + XISendDeviceHierarchyEvent(flags); + return rc; +} + diff --git a/xorg-server/Xi/xipassivegrab.c b/xorg-server/Xi/xipassivegrab.c index 6b689f45e..8663d12a1 100644 --- a/xorg-server/Xi/xipassivegrab.c +++ b/xorg-server/Xi/xipassivegrab.c @@ -1,313 +1,307 @@ -/*
- * Copyright © 2009 Red Hat, Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Author: Peter Hutterer
- */
-
-/***********************************************************************
- *
- * Request to grab or ungrab input device.
- *
- */
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#include "inputstr.h" /* DeviceIntPtr */
-#include "windowstr.h" /* window structure */
-#include <X11/extensions/XI2.h>
-#include <X11/extensions/XI2proto.h>
-#include "swaprep.h"
-
-#include "exglobals.h" /* BadDevice */
-#include "exevents.h"
-#include "xipassivegrab.h"
-#include "dixgrabs.h"
-
-int
-SProcXIPassiveGrabDevice(ClientPtr client)
-{
- int i;
- char n;
- xXIModifierInfo *mods;
-
- REQUEST(xXIPassiveGrabDeviceReq);
-
- swaps(&stuff->length, n);
- swaps(&stuff->deviceid, n);
- swapl(&stuff->grab_window, n);
- swapl(&stuff->cursor, n);
- swapl(&stuff->time, n);
- swapl(&stuff->detail, n);
- swaps(&stuff->mask_len, n);
- swaps(&stuff->num_modifiers, n);
-
- mods = (xXIModifierInfo*)&stuff[1];
-
- for (i = 0; i < stuff->num_modifiers; i++, mods++)
- {
- swapl(&mods->base_mods, n);
- swapl(&mods->latched_mods, n);
- swapl(&mods->locked_mods, n);
- }
-
- return ProcXIPassiveGrabDevice(client);
-}
-
-int
-ProcXIPassiveGrabDevice(ClientPtr client)
-{
- DeviceIntPtr dev, mod_dev;
- xXIPassiveGrabDeviceReply rep;
- int i, ret = Success;
- uint8_t status;
- uint32_t *modifiers;
- xXIGrabModifierInfo *modifiers_failed;
- GrabMask mask;
- GrabParameters param;
- void *tmp;
- int mask_len;
-
- REQUEST(xXIPassiveGrabDeviceReq);
- REQUEST_AT_LEAST_SIZE(xXIPassiveGrabDeviceReq);
-
- if (stuff->deviceid == XIAllDevices)
- dev = inputInfo.all_devices;
- else if (stuff->deviceid == XIAllMasterDevices)
- dev = inputInfo.all_master_devices;
- else
- {
- ret = dixLookupDevice(&dev, stuff->deviceid, client, DixGrabAccess);
- if (ret != Success)
- return ret;
- }
-
- if (stuff->grab_type != XIGrabtypeButton &&
- stuff->grab_type != XIGrabtypeKeycode &&
- stuff->grab_type != XIGrabtypeEnter &&
- stuff->grab_type != XIGrabtypeFocusIn)
- {
- client->errorValue = stuff->grab_type;
- return BadValue;
- }
-
- if ((stuff->grab_type == XIGrabtypeEnter ||
- stuff->grab_type == XIGrabtypeFocusIn) && stuff->detail != 0)
- {
- client->errorValue = stuff->detail;
- return BadValue;
- }
-
- if (XICheckInvalidMaskBits(client, (unsigned char*)&stuff[1],
- stuff->mask_len * 4) != Success)
- return BadValue;
-
- mask_len = min(sizeof(mask.xi2mask[stuff->deviceid]), stuff->mask_len * 4);
- memset(mask.xi2mask, 0, sizeof(mask.xi2mask));
- memcpy(mask.xi2mask[stuff->deviceid], &stuff[1], mask_len * 4);
-
- rep.repType = X_Reply;
- rep.RepType = X_XIPassiveGrabDevice;
- rep.length = 0;
- rep.sequenceNumber = client->sequence;
- rep.num_modifiers = 0;
-
- memset(¶m, 0, sizeof(param));
- param.grabtype = GRABTYPE_XI2;
- param.ownerEvents = stuff->owner_events;
- param.this_device_mode = stuff->grab_mode;
- param.other_devices_mode = stuff->paired_device_mode;
- param.grabWindow = stuff->grab_window;
- param.cursor = stuff->cursor;
-
- if (stuff->cursor != None)
- {
- status = dixLookupResourceByType(&tmp, stuff->cursor,
- RT_CURSOR, client, DixUseAccess);
- if (status != Success)
- {
- client->errorValue = stuff->cursor;
- return status;
- }
- }
-
- status = dixLookupWindow((WindowPtr*)&tmp, stuff->grab_window, client, DixSetAttrAccess);
- if (status != Success)
- return status;
-
- status = CheckGrabValues(client, ¶m);
-
- modifiers = (uint32_t*)&stuff[1] + stuff->mask_len;
- modifiers_failed = calloc(stuff->num_modifiers, sizeof(xXIGrabModifierInfo));
- if (!modifiers_failed)
- return BadAlloc;
-
- if (!IsMaster(dev) && dev->u.master)
- mod_dev = GetMaster(dev, MASTER_KEYBOARD);
- else
- mod_dev = dev;
-
- for (i = 0; i < stuff->num_modifiers; i++, modifiers++)
- {
- param.modifiers = *modifiers;
- switch(stuff->grab_type)
- {
- case XIGrabtypeButton:
- status = GrabButton(client, dev, mod_dev, stuff->detail,
- ¶m, GRABTYPE_XI2, &mask);
- break;
- case XIGrabtypeKeycode:
- status = GrabKey(client, dev, mod_dev, stuff->detail,
- ¶m, GRABTYPE_XI2, &mask);
- break;
- case XIGrabtypeEnter:
- case XIGrabtypeFocusIn:
- status = GrabWindow(client, dev, stuff->grab_type,
- ¶m, &mask);
- break;
- }
-
- if (status != GrabSuccess)
- {
- xXIGrabModifierInfo *info = modifiers_failed + rep.num_modifiers;
-
- info->status = status;
- info->modifiers = *modifiers;
- rep.num_modifiers++;
- rep.length++;
- }
- }
-
- WriteReplyToClient(client, sizeof(rep), &rep);
- if (rep.num_modifiers)
- {
- client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write;
- WriteSwappedDataToClient(client, rep.num_modifiers * 4, (char*)modifiers_failed);
- }
- free(modifiers_failed);
- return ret;
-}
-
-void
-SRepXIPassiveGrabDevice(ClientPtr client, int size,
- xXIPassiveGrabDeviceReply * rep)
-{
- char n;
-
- swaps(&rep->sequenceNumber, n);
- swapl(&rep->length, n);
- swaps(&rep->num_modifiers, n);
-
- WriteToClient(client, size, (char *)rep);
-}
-
-int
-SProcXIPassiveUngrabDevice(ClientPtr client)
-{
- char n;
- int i;
- uint32_t *modifiers;
-
- REQUEST(xXIPassiveUngrabDeviceReq);
-
- swaps(&stuff->length, n);
- swapl(&stuff->grab_window, n);
- swaps(&stuff->deviceid, n);
- swapl(&stuff->detail, n);
- swaps(&stuff->num_modifiers, n);
-
- modifiers = (uint32_t*)&stuff[1];
-
- for (i = 0; i < stuff->num_modifiers; i++, modifiers++)
- swapl(modifiers, n);
-
- return ProcXIPassiveUngrabDevice(client);
-}
-
-int
-ProcXIPassiveUngrabDevice(ClientPtr client)
-{
- DeviceIntPtr dev, mod_dev;
- WindowPtr win;
- GrabRec tempGrab;
- uint32_t* modifiers;
- int i, rc;
-
- REQUEST(xXIPassiveUngrabDeviceReq);
- REQUEST_AT_LEAST_SIZE(xXIPassiveUngrabDeviceReq);
-
- rc = dixLookupDevice(&dev, stuff->deviceid, client, DixGrabAccess);
- if (rc != Success)
- return rc;
-
- if (stuff->grab_type != XIGrabtypeButton &&
- stuff->grab_type != XIGrabtypeKeycode &&
- stuff->grab_type != XIGrabtypeEnter &&
- stuff->grab_type != XIGrabtypeFocusIn)
- {
- client->errorValue = stuff->grab_type;
- return BadValue;
- }
-
- if ((stuff->grab_type == XIGrabtypeEnter ||
- stuff->grab_type == XIGrabtypeFocusIn) && stuff->detail != 0)
- {
- client->errorValue = stuff->detail;
- return BadValue;
- }
-
- rc = dixLookupWindow(&win, stuff->grab_window, client, DixSetAttrAccess);
- if (rc != Success)
- return rc;
-
- if (!IsMaster(dev) && dev->u.master)
- mod_dev = GetMaster(dev, MASTER_KEYBOARD);
- else
- mod_dev = dev;
-
- tempGrab.resource = client->clientAsMask;
- tempGrab.device = dev;
- tempGrab.window = win;
- switch(stuff->grab_type)
- {
- case XIGrabtypeButton: tempGrab.type = XI_ButtonPress; break;
- case XIGrabtypeKeycode: tempGrab.type = XI_KeyPress; break;
- case XIGrabtypeEnter: tempGrab.type = XI_Enter; break;
- case XIGrabtypeFocusIn: tempGrab.type = XI_FocusIn; break;
- }
- tempGrab.grabtype = GRABTYPE_XI2;
- tempGrab.modifierDevice = mod_dev;
- tempGrab.modifiersDetail.pMask = NULL;
- tempGrab.detail.exact = stuff->detail;
- tempGrab.detail.pMask = NULL;
-
- modifiers = (uint32_t*)&stuff[1];
-
- for (i = 0; i < stuff->num_modifiers; i++, modifiers++)
- {
- tempGrab.modifiersDetail.exact = *modifiers;
- DeletePassiveGrabFromList(&tempGrab);
- }
-
- return Success;
-}
+/* + * Copyright © 2009 Red Hat, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Author: Peter Hutterer + */ + +/*********************************************************************** + * + * Request to grab or ungrab input device. + * + */ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include "inputstr.h" /* DeviceIntPtr */ +#include "windowstr.h" /* window structure */ +#include <X11/extensions/XI2.h> +#include <X11/extensions/XI2proto.h> +#include "swaprep.h" + +#include "exglobals.h" /* BadDevice */ +#include "exevents.h" +#include "xipassivegrab.h" +#include "dixgrabs.h" + +int +SProcXIPassiveGrabDevice(ClientPtr client) +{ + int i; + char n; + xXIModifierInfo *mods; + + REQUEST(xXIPassiveGrabDeviceReq); + + swaps(&stuff->length, n); + swaps(&stuff->deviceid, n); + swapl(&stuff->grab_window, n); + swapl(&stuff->cursor, n); + swapl(&stuff->time, n); + swapl(&stuff->detail, n); + swaps(&stuff->mask_len, n); + swaps(&stuff->num_modifiers, n); + + mods = (xXIModifierInfo*)&stuff[1]; + + for (i = 0; i < stuff->num_modifiers; i++, mods++) + { + swapl(&mods->base_mods, n); + swapl(&mods->latched_mods, n); + swapl(&mods->locked_mods, n); + } + + return ProcXIPassiveGrabDevice(client); +} + +int +ProcXIPassiveGrabDevice(ClientPtr client) +{ + DeviceIntPtr dev, mod_dev; + xXIPassiveGrabDeviceReply rep; + int i, ret = Success; + uint8_t status; + uint32_t *modifiers; + xXIGrabModifierInfo *modifiers_failed; + GrabMask mask; + GrabParameters param; + void *tmp; + int mask_len; + + REQUEST(xXIPassiveGrabDeviceReq); + REQUEST_AT_LEAST_SIZE(xXIPassiveGrabDeviceReq); + + if (stuff->deviceid == XIAllDevices) + dev = inputInfo.all_devices; + else if (stuff->deviceid == XIAllMasterDevices) + dev = inputInfo.all_master_devices; + else + { + ret = dixLookupDevice(&dev, stuff->deviceid, client, DixGrabAccess); + if (ret != Success) + return ret; + } + + if (stuff->grab_type != XIGrabtypeButton && + stuff->grab_type != XIGrabtypeKeycode && + stuff->grab_type != XIGrabtypeEnter && + stuff->grab_type != XIGrabtypeFocusIn) + { + client->errorValue = stuff->grab_type; + return BadValue; + } + + if ((stuff->grab_type == XIGrabtypeEnter || + stuff->grab_type == XIGrabtypeFocusIn) && stuff->detail != 0) + { + client->errorValue = stuff->detail; + return BadValue; + } + + if (XICheckInvalidMaskBits(client, (unsigned char*)&stuff[1], + stuff->mask_len * 4) != Success) + return BadValue; + + mask_len = min(sizeof(mask.xi2mask[stuff->deviceid]), stuff->mask_len * 4); + memset(mask.xi2mask, 0, sizeof(mask.xi2mask)); + memcpy(mask.xi2mask[stuff->deviceid], &stuff[1], mask_len * 4); + + rep.repType = X_Reply; + rep.RepType = X_XIPassiveGrabDevice; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.num_modifiers = 0; + + memset(¶m, 0, sizeof(param)); + param.grabtype = GRABTYPE_XI2; + param.ownerEvents = stuff->owner_events; + param.this_device_mode = stuff->grab_mode; + param.other_devices_mode = stuff->paired_device_mode; + param.grabWindow = stuff->grab_window; + param.cursor = stuff->cursor; + + if (stuff->cursor != None) + { + status = dixLookupResourceByType(&tmp, stuff->cursor, + RT_CURSOR, client, DixUseAccess); + if (status != Success) + { + client->errorValue = stuff->cursor; + return status; + } + } + + status = dixLookupWindow((WindowPtr*)&tmp, stuff->grab_window, client, DixSetAttrAccess); + if (status != Success) + return status; + + status = CheckGrabValues(client, ¶m); + + modifiers = (uint32_t*)&stuff[1] + stuff->mask_len; + modifiers_failed = calloc(stuff->num_modifiers, sizeof(xXIGrabModifierInfo)); + if (!modifiers_failed) + return BadAlloc; + + mod_dev = (IsFloating(dev)) ? dev : GetMaster(dev, MASTER_KEYBOARD); + + for (i = 0; i < stuff->num_modifiers; i++, modifiers++) + { + param.modifiers = *modifiers; + switch(stuff->grab_type) + { + case XIGrabtypeButton: + status = GrabButton(client, dev, mod_dev, stuff->detail, + ¶m, GRABTYPE_XI2, &mask); + break; + case XIGrabtypeKeycode: + status = GrabKey(client, dev, mod_dev, stuff->detail, + ¶m, GRABTYPE_XI2, &mask); + break; + case XIGrabtypeEnter: + case XIGrabtypeFocusIn: + status = GrabWindow(client, dev, stuff->grab_type, + ¶m, &mask); + break; + } + + if (status != GrabSuccess) + { + xXIGrabModifierInfo *info = modifiers_failed + rep.num_modifiers; + + info->status = status; + info->modifiers = *modifiers; + rep.num_modifiers++; + rep.length++; + } + } + + WriteReplyToClient(client, sizeof(rep), &rep); + if (rep.num_modifiers) + { + client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write; + WriteSwappedDataToClient(client, rep.num_modifiers * 4, (char*)modifiers_failed); + } + free(modifiers_failed); + return ret; +} + +void +SRepXIPassiveGrabDevice(ClientPtr client, int size, + xXIPassiveGrabDeviceReply * rep) +{ + char n; + + swaps(&rep->sequenceNumber, n); + swapl(&rep->length, n); + swaps(&rep->num_modifiers, n); + + WriteToClient(client, size, (char *)rep); +} + +int +SProcXIPassiveUngrabDevice(ClientPtr client) +{ + char n; + int i; + uint32_t *modifiers; + + REQUEST(xXIPassiveUngrabDeviceReq); + + swaps(&stuff->length, n); + swapl(&stuff->grab_window, n); + swaps(&stuff->deviceid, n); + swapl(&stuff->detail, n); + swaps(&stuff->num_modifiers, n); + + modifiers = (uint32_t*)&stuff[1]; + + for (i = 0; i < stuff->num_modifiers; i++, modifiers++) + swapl(modifiers, n); + + return ProcXIPassiveUngrabDevice(client); +} + +int +ProcXIPassiveUngrabDevice(ClientPtr client) +{ + DeviceIntPtr dev, mod_dev; + WindowPtr win; + GrabRec tempGrab; + uint32_t* modifiers; + int i, rc; + + REQUEST(xXIPassiveUngrabDeviceReq); + REQUEST_AT_LEAST_SIZE(xXIPassiveUngrabDeviceReq); + + rc = dixLookupDevice(&dev, stuff->deviceid, client, DixGrabAccess); + if (rc != Success) + return rc; + + if (stuff->grab_type != XIGrabtypeButton && + stuff->grab_type != XIGrabtypeKeycode && + stuff->grab_type != XIGrabtypeEnter && + stuff->grab_type != XIGrabtypeFocusIn) + { + client->errorValue = stuff->grab_type; + return BadValue; + } + + if ((stuff->grab_type == XIGrabtypeEnter || + stuff->grab_type == XIGrabtypeFocusIn) && stuff->detail != 0) + { + client->errorValue = stuff->detail; + return BadValue; + } + + rc = dixLookupWindow(&win, stuff->grab_window, client, DixSetAttrAccess); + if (rc != Success) + return rc; + + mod_dev = (IsFloating(dev)) ? dev : GetMaster(dev, MASTER_KEYBOARD); + + tempGrab.resource = client->clientAsMask; + tempGrab.device = dev; + tempGrab.window = win; + switch(stuff->grab_type) + { + case XIGrabtypeButton: tempGrab.type = XI_ButtonPress; break; + case XIGrabtypeKeycode: tempGrab.type = XI_KeyPress; break; + case XIGrabtypeEnter: tempGrab.type = XI_Enter; break; + case XIGrabtypeFocusIn: tempGrab.type = XI_FocusIn; break; + } + tempGrab.grabtype = GRABTYPE_XI2; + tempGrab.modifierDevice = mod_dev; + tempGrab.modifiersDetail.pMask = NULL; + tempGrab.detail.exact = stuff->detail; + tempGrab.detail.pMask = NULL; + + modifiers = (uint32_t*)&stuff[1]; + + for (i = 0; i < stuff->num_modifiers; i++, modifiers++) + { + tempGrab.modifiersDetail.exact = *modifiers; + DeletePassiveGrabFromList(&tempGrab); + } + + return Success; +} diff --git a/xorg-server/Xi/xiquerydevice.c b/xorg-server/Xi/xiquerydevice.c index 4e1cae406..8b5421130 100644 --- a/xorg-server/Xi/xiquerydevice.c +++ b/xorg-server/Xi/xiquerydevice.c @@ -1,503 +1,503 @@ -/*
- * Copyright © 2009 Red Hat, Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors: Peter Hutterer
- *
- */
-
-/**
- * @file Protocol handling for the XIQueryDevice request/reply.
- */
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#include "inputstr.h"
-#include <X11/X.h>
-#include <X11/Xatom.h>
-#include <X11/extensions/XI2proto.h>
-#include "xkbstr.h"
-#include "xkbsrv.h"
-#include "xserver-properties.h"
-#include "exevents.h"
-#include "xace.h"
-
-#include "xiquerydevice.h"
-
-static Bool ShouldSkipDevice(ClientPtr client, int deviceid, DeviceIntPtr d);
-static int
-ListDeviceInfo(ClientPtr client, DeviceIntPtr dev, xXIDeviceInfo* info);
-static int SizeDeviceInfo(DeviceIntPtr dev);
-static void SwapDeviceInfo(DeviceIntPtr dev, xXIDeviceInfo* info);
-int
-SProcXIQueryDevice(ClientPtr client)
-{
- char n;
-
- REQUEST(xXIQueryDeviceReq);
-
- swaps(&stuff->length, n);
- swaps(&stuff->deviceid, n);
-
- return ProcXIQueryDevice(client);
-}
-
-int
-ProcXIQueryDevice(ClientPtr client)
-{
- xXIQueryDeviceReply rep;
- DeviceIntPtr dev = NULL;
- int rc = Success;
- int i = 0, len = 0;
- char *info, *ptr;
- Bool *skip = NULL;
-
- REQUEST(xXIQueryDeviceReq);
- REQUEST_SIZE_MATCH(xXIQueryDeviceReq);
-
- if (stuff->deviceid != XIAllDevices && stuff->deviceid != XIAllMasterDevices)
- {
- rc = dixLookupDevice(&dev, stuff->deviceid, client, DixGetAttrAccess);
- if (rc != Success)
- {
- client->errorValue = stuff->deviceid;
- return rc;
- }
- len += SizeDeviceInfo(dev);
- }
- else
- {
- skip = calloc(sizeof(Bool), inputInfo.numDevices);
- if (!skip)
- return BadAlloc;
-
- for (dev = inputInfo.devices; dev; dev = dev->next, i++)
- {
- skip[i] = ShouldSkipDevice(client, stuff->deviceid, dev);
- if (!skip[i])
- len += SizeDeviceInfo(dev);
- }
-
- for (dev = inputInfo.off_devices; dev; dev = dev->next, i++)
- {
- skip[i] = ShouldSkipDevice(client, stuff->deviceid, dev);
- if (!skip[i])
- len += SizeDeviceInfo(dev);
- }
- }
-
- info = calloc(1, len);
- if (!info)
- return BadAlloc;
-
- memset(&rep, 0, sizeof(xXIQueryDeviceReply));
- rep.repType = X_Reply;
- rep.RepType = X_XIQueryDevice;
- rep.sequenceNumber = client->sequence;
- rep.length = len/4;
- rep.num_devices = 0;
-
- ptr = info;
- if (dev)
- {
- len = ListDeviceInfo(client, dev, (xXIDeviceInfo*)info);
- if (client->swapped)
- SwapDeviceInfo(dev, (xXIDeviceInfo*)info);
- info += len;
- rep.num_devices = 1;
- } else
- {
- i = 0;
- for (dev = inputInfo.devices; dev; dev = dev->next, i++)
- {
- if (!skip[i])
- {
- len = ListDeviceInfo(client, dev, (xXIDeviceInfo*)info);
- if (client->swapped)
- SwapDeviceInfo(dev, (xXIDeviceInfo*)info);
- info += len;
- rep.num_devices++;
- }
- }
-
- for (dev = inputInfo.off_devices; dev; dev = dev->next, i++)
- {
- if (!skip[i])
- {
- len = ListDeviceInfo(client, dev, (xXIDeviceInfo*)info);
- if (client->swapped)
- SwapDeviceInfo(dev, (xXIDeviceInfo*)info);
- info += len;
- rep.num_devices++;
- }
- }
- }
-
- WriteReplyToClient(client, sizeof(xXIQueryDeviceReply), &rep);
- WriteToClient(client, rep.length * 4, ptr);
- free(ptr);
- free(skip);
- return rc;
-}
-
-void
-SRepXIQueryDevice(ClientPtr client, int size, xXIQueryDeviceReply *rep)
-{
- char n;
-
- swaps(&rep->sequenceNumber, n);
- swapl(&rep->length, n);
- swaps(&rep->num_devices, n);
-
- /* Device info is already swapped, see ProcXIQueryDevice */
-
- WriteToClient(client, size, (char *)rep);
-}
-
-
-/**
- * @return Whether the device should be included in the returned list.
- */
-static Bool
-ShouldSkipDevice(ClientPtr client, int deviceid, DeviceIntPtr dev)
-{
- /* if all devices are not being queried, only master devices are */
- if (deviceid == XIAllDevices || IsMaster(dev))
- {
- int rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixGetAttrAccess);
- if (rc == Success)
- return FALSE;
- }
- return TRUE;
-}
-
-/**
- * @return The number of bytes needed to store this device's xXIDeviceInfo
- * (and its classes).
- */
-static int
-SizeDeviceInfo(DeviceIntPtr dev)
-{
- int len = sizeof(xXIDeviceInfo);
-
- /* 4-padded name */
- len += pad_to_int32(strlen(dev->name));
-
- return len + SizeDeviceClasses(dev);
-
-}
-
-/*
- * @return The number of bytes needed to store this device's classes.
- */
-int
-SizeDeviceClasses(DeviceIntPtr dev)
-{
- int len = 0;
-
- if (dev->button)
- {
- len += sizeof(xXIButtonInfo);
- len += dev->button->numButtons * sizeof(Atom);
- len += pad_to_int32(bits_to_bytes(dev->button->numButtons));
- }
-
- if (dev->key)
- {
- XkbDescPtr xkb = dev->key->xkbInfo->desc;
- len += sizeof(xXIKeyInfo);
- len += (xkb->max_key_code - xkb->min_key_code + 1) * sizeof(uint32_t);
- }
-
- if (dev->valuator)
- len += sizeof(xXIValuatorInfo) * dev->valuator->numAxes;
-
- return len;
-}
-
-
-/**
- * Write button information into info.
- * @return Number of bytes written into info.
- */
-int
-ListButtonInfo(DeviceIntPtr dev, xXIButtonInfo* info, Bool reportState)
-{
- unsigned char *bits;
- int mask_len;
- int i;
-
- if (!dev || !dev->button)
- return 0;
-
- mask_len = bytes_to_int32(bits_to_bytes(dev->button->numButtons));
-
- info->type = ButtonClass;
- info->num_buttons = dev->button->numButtons;
- info->length = bytes_to_int32(sizeof(xXIButtonInfo)) +
- info->num_buttons + mask_len;
- info->sourceid = dev->button->sourceid;
-
- bits = (unsigned char*)&info[1];
- memset(bits, 0, mask_len * 4);
-
- if (reportState)
- for (i = 0; i < dev->button->numButtons; i++)
- if (BitIsOn(dev->button->down, i))
- SetBit(bits, i);
-
- bits += mask_len * 4;
- memcpy(bits, dev->button->labels, dev->button->numButtons * sizeof(Atom));
-
- return info->length * 4;
-}
-
-static void
-SwapButtonInfo(DeviceIntPtr dev, xXIButtonInfo* info)
-{
- char n;
- Atom *btn;
- int i;
- swaps(&info->type, n);
- swaps(&info->length, n);
- swaps(&info->sourceid, n);
-
- for (i = 0, btn = (Atom*)&info[1]; i < info->num_buttons; i++, btn++)
- swaps(btn, n);
-
- swaps(&info->num_buttons, n);
-}
-
-/**
- * Write key information into info.
- * @return Number of bytes written into info.
- */
-int
-ListKeyInfo(DeviceIntPtr dev, xXIKeyInfo* info)
-{
- int i;
- XkbDescPtr xkb = dev->key->xkbInfo->desc;
- uint32_t *kc;
-
- info->type = KeyClass;
- info->num_keycodes = xkb->max_key_code - xkb->min_key_code + 1;
- info->length = sizeof(xXIKeyInfo)/4 + info->num_keycodes;
- info->sourceid = dev->key->sourceid;
-
- kc = (uint32_t*)&info[1];
- for (i = xkb->min_key_code; i <= xkb->max_key_code; i++, kc++)
- *kc = i;
-
- return info->length * 4;
-}
-
-static void
-SwapKeyInfo(DeviceIntPtr dev, xXIKeyInfo* info)
-{
- char n;
- uint32_t *key;
- int i;
- swaps(&info->type, n);
- swaps(&info->length, n);
- swaps(&info->sourceid, n);
-
- for (i = 0, key = (uint32_t*)&info[1]; i < info->num_keycodes; i++, key++)
- swapl(key, n);
-
- swaps(&info->num_keycodes, n);
-}
-
-/**
- * List axis information for the given axis.
- *
- * @return The number of bytes written into info.
- */
-int
-ListValuatorInfo(DeviceIntPtr dev, xXIValuatorInfo* info, int axisnumber,
- Bool reportState)
-{
- ValuatorClassPtr v = dev->valuator;
-
- info->type = ValuatorClass;
- info->length = sizeof(xXIValuatorInfo)/4;
- info->label = v->axes[axisnumber].label;
- info->min.integral = v->axes[axisnumber].min_value;
- info->min.frac = 0;
- info->max.integral = v->axes[axisnumber].max_value;
- info->max.frac = 0;
- info->value.integral = (int)v->axisVal[axisnumber];
- info->value.frac = (int)(v->axisVal[axisnumber] * (1 << 16) * (1 << 16));
- info->resolution = v->axes[axisnumber].resolution;
- info->number = axisnumber;
- info->mode = valuator_get_mode(dev, axisnumber);
- info->sourceid = v->sourceid;
-
- if (!reportState)
- info->value = info->min;
-
- return info->length * 4;
-}
-
-static void
-SwapValuatorInfo(DeviceIntPtr dev, xXIValuatorInfo* info)
-{
- char n;
- swaps(&info->type, n);
- swaps(&info->length, n);
- swapl(&info->label, n);
- swapl(&info->min.integral, n);
- swapl(&info->min.frac, n);
- swapl(&info->max.integral, n);
- swapl(&info->max.frac, n);
- swaps(&info->number, n);
- swaps(&info->sourceid, n);
-}
-
-int GetDeviceUse(DeviceIntPtr dev, uint16_t *attachment)
-{
- DeviceIntPtr master = dev->u.master;
- int use;
-
- if (IsMaster(dev))
- {
- DeviceIntPtr paired = GetPairedDevice(dev);
- use = IsPointerDevice(dev) ? XIMasterPointer : XIMasterKeyboard;
- *attachment = (paired ? paired->id : 0);
- } else if (master)
- {
- use = IsPointerDevice(master) ? XISlavePointer : XISlaveKeyboard;
- *attachment = master->id;
- } else
- use = XIFloatingSlave;
-
- return use;
-}
-
-/**
- * Write the info for device dev into the buffer pointed to by info.
- *
- * @return The number of bytes used.
- */
-static int
-ListDeviceInfo(ClientPtr client, DeviceIntPtr dev, xXIDeviceInfo* info)
-{
- char *any = (char*)&info[1];
- int len = 0, total_len = 0;
-
- info->deviceid = dev->id;
- info->use = GetDeviceUse(dev, &info->attachment);
- info->num_classes = 0;
- info->name_len = strlen(dev->name);
- info->enabled = dev->enabled;
- total_len = sizeof(xXIDeviceInfo);
-
- len = pad_to_int32(info->name_len);
- memset(any, 0, len);
- strncpy(any, dev->name, info->name_len);
- any += len;
- total_len += len;
-
- total_len += ListDeviceClasses(client, dev, any, &info->num_classes);
- return total_len;
-}
-
-/**
- * Write the class info of the device into the memory pointed to by any, set
- * nclasses to the number of classes in total and return the number of bytes
- * written.
- */
-int
-ListDeviceClasses(ClientPtr client, DeviceIntPtr dev,
- char *any, uint16_t *nclasses)
-{
- int total_len = 0;
- int len;
- int i;
- int rc;
-
- /* Check if the current device state should be suppressed */
- rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixReadAccess);
-
- if (dev->button)
- {
- (*nclasses)++;
- len = ListButtonInfo(dev, (xXIButtonInfo*)any, rc == Success);
- any += len;
- total_len += len;
- }
-
- if (dev->key)
- {
- (*nclasses)++;
- len = ListKeyInfo(dev, (xXIKeyInfo*)any);
- any += len;
- total_len += len;
- }
-
- for (i = 0; dev->valuator && i < dev->valuator->numAxes; i++)
- {
- (*nclasses)++;
- len = ListValuatorInfo(dev, (xXIValuatorInfo*)any, i, rc == Success);
- any += len;
- total_len += len;
- }
-
- return total_len;
-}
-
-static void
-SwapDeviceInfo(DeviceIntPtr dev, xXIDeviceInfo* info)
-{
- char n;
- char *any = (char*)&info[1];
- int i;
-
- /* Skip over name */
- any += pad_to_int32(info->name_len);
-
- for (i = 0; i < info->num_classes; i++)
- {
- int len = ((xXIAnyInfo*)any)->length;
- switch(((xXIAnyInfo*)any)->type)
- {
- case XIButtonClass:
- SwapButtonInfo(dev, (xXIButtonInfo*)any);
- break;
- case XIKeyClass:
- SwapKeyInfo(dev, (xXIKeyInfo*)any);
- break;
- case XIValuatorClass:
- SwapValuatorInfo(dev, (xXIValuatorInfo*)any);
- break;
- }
-
- any += len * 4;
- }
-
- swaps(&info->deviceid, n);
- swaps(&info->use, n);
- swaps(&info->attachment, n);
- swaps(&info->num_classes, n);
- swaps(&info->name_len, n);
-
-}
+/* + * Copyright © 2009 Red Hat, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: Peter Hutterer + * + */ + +/** + * @file Protocol handling for the XIQueryDevice request/reply. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include "inputstr.h" +#include <X11/X.h> +#include <X11/Xatom.h> +#include <X11/extensions/XI2proto.h> +#include "xkbstr.h" +#include "xkbsrv.h" +#include "xserver-properties.h" +#include "exevents.h" +#include "xace.h" + +#include "xiquerydevice.h" + +static Bool ShouldSkipDevice(ClientPtr client, int deviceid, DeviceIntPtr d); +static int +ListDeviceInfo(ClientPtr client, DeviceIntPtr dev, xXIDeviceInfo* info); +static int SizeDeviceInfo(DeviceIntPtr dev); +static void SwapDeviceInfo(DeviceIntPtr dev, xXIDeviceInfo* info); +int +SProcXIQueryDevice(ClientPtr client) +{ + char n; + + REQUEST(xXIQueryDeviceReq); + + swaps(&stuff->length, n); + swaps(&stuff->deviceid, n); + + return ProcXIQueryDevice(client); +} + +int +ProcXIQueryDevice(ClientPtr client) +{ + xXIQueryDeviceReply rep; + DeviceIntPtr dev = NULL; + int rc = Success; + int i = 0, len = 0; + char *info, *ptr; + Bool *skip = NULL; + + REQUEST(xXIQueryDeviceReq); + REQUEST_SIZE_MATCH(xXIQueryDeviceReq); + + if (stuff->deviceid != XIAllDevices && stuff->deviceid != XIAllMasterDevices) + { + rc = dixLookupDevice(&dev, stuff->deviceid, client, DixGetAttrAccess); + if (rc != Success) + { + client->errorValue = stuff->deviceid; + return rc; + } + len += SizeDeviceInfo(dev); + } + else + { + skip = calloc(sizeof(Bool), inputInfo.numDevices); + if (!skip) + return BadAlloc; + + for (dev = inputInfo.devices; dev; dev = dev->next, i++) + { + skip[i] = ShouldSkipDevice(client, stuff->deviceid, dev); + if (!skip[i]) + len += SizeDeviceInfo(dev); + } + + for (dev = inputInfo.off_devices; dev; dev = dev->next, i++) + { + skip[i] = ShouldSkipDevice(client, stuff->deviceid, dev); + if (!skip[i]) + len += SizeDeviceInfo(dev); + } + } + + info = calloc(1, len); + if (!info) + return BadAlloc; + + memset(&rep, 0, sizeof(xXIQueryDeviceReply)); + rep.repType = X_Reply; + rep.RepType = X_XIQueryDevice; + rep.sequenceNumber = client->sequence; + rep.length = len/4; + rep.num_devices = 0; + + ptr = info; + if (dev) + { + len = ListDeviceInfo(client, dev, (xXIDeviceInfo*)info); + if (client->swapped) + SwapDeviceInfo(dev, (xXIDeviceInfo*)info); + info += len; + rep.num_devices = 1; + } else + { + i = 0; + for (dev = inputInfo.devices; dev; dev = dev->next, i++) + { + if (!skip[i]) + { + len = ListDeviceInfo(client, dev, (xXIDeviceInfo*)info); + if (client->swapped) + SwapDeviceInfo(dev, (xXIDeviceInfo*)info); + info += len; + rep.num_devices++; + } + } + + for (dev = inputInfo.off_devices; dev; dev = dev->next, i++) + { + if (!skip[i]) + { + len = ListDeviceInfo(client, dev, (xXIDeviceInfo*)info); + if (client->swapped) + SwapDeviceInfo(dev, (xXIDeviceInfo*)info); + info += len; + rep.num_devices++; + } + } + } + + WriteReplyToClient(client, sizeof(xXIQueryDeviceReply), &rep); + WriteToClient(client, rep.length * 4, ptr); + free(ptr); + free(skip); + return rc; +} + +void +SRepXIQueryDevice(ClientPtr client, int size, xXIQueryDeviceReply *rep) +{ + char n; + + swaps(&rep->sequenceNumber, n); + swapl(&rep->length, n); + swaps(&rep->num_devices, n); + + /* Device info is already swapped, see ProcXIQueryDevice */ + + WriteToClient(client, size, (char *)rep); +} + + +/** + * @return Whether the device should be included in the returned list. + */ +static Bool +ShouldSkipDevice(ClientPtr client, int deviceid, DeviceIntPtr dev) +{ + /* if all devices are not being queried, only master devices are */ + if (deviceid == XIAllDevices || IsMaster(dev)) + { + int rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixGetAttrAccess); + if (rc == Success) + return FALSE; + } + return TRUE; +} + +/** + * @return The number of bytes needed to store this device's xXIDeviceInfo + * (and its classes). + */ +static int +SizeDeviceInfo(DeviceIntPtr dev) +{ + int len = sizeof(xXIDeviceInfo); + + /* 4-padded name */ + len += pad_to_int32(strlen(dev->name)); + + return len + SizeDeviceClasses(dev); + +} + +/* + * @return The number of bytes needed to store this device's classes. + */ +int +SizeDeviceClasses(DeviceIntPtr dev) +{ + int len = 0; + + if (dev->button) + { + len += sizeof(xXIButtonInfo); + len += dev->button->numButtons * sizeof(Atom); + len += pad_to_int32(bits_to_bytes(dev->button->numButtons)); + } + + if (dev->key) + { + XkbDescPtr xkb = dev->key->xkbInfo->desc; + len += sizeof(xXIKeyInfo); + len += (xkb->max_key_code - xkb->min_key_code + 1) * sizeof(uint32_t); + } + + if (dev->valuator) + len += sizeof(xXIValuatorInfo) * dev->valuator->numAxes; + + return len; +} + + +/** + * Write button information into info. + * @return Number of bytes written into info. + */ +int +ListButtonInfo(DeviceIntPtr dev, xXIButtonInfo* info, Bool reportState) +{ + unsigned char *bits; + int mask_len; + int i; + + if (!dev || !dev->button) + return 0; + + mask_len = bytes_to_int32(bits_to_bytes(dev->button->numButtons)); + + info->type = ButtonClass; + info->num_buttons = dev->button->numButtons; + info->length = bytes_to_int32(sizeof(xXIButtonInfo)) + + info->num_buttons + mask_len; + info->sourceid = dev->button->sourceid; + + bits = (unsigned char*)&info[1]; + memset(bits, 0, mask_len * 4); + + if (reportState) + for (i = 0; i < dev->button->numButtons; i++) + if (BitIsOn(dev->button->down, i)) + SetBit(bits, i); + + bits += mask_len * 4; + memcpy(bits, dev->button->labels, dev->button->numButtons * sizeof(Atom)); + + return info->length * 4; +} + +static void +SwapButtonInfo(DeviceIntPtr dev, xXIButtonInfo* info) +{ + char n; + Atom *btn; + int i; + swaps(&info->type, n); + swaps(&info->length, n); + swaps(&info->sourceid, n); + + for (i = 0, btn = (Atom*)&info[1]; i < info->num_buttons; i++, btn++) + swaps(btn, n); + + swaps(&info->num_buttons, n); +} + +/** + * Write key information into info. + * @return Number of bytes written into info. + */ +int +ListKeyInfo(DeviceIntPtr dev, xXIKeyInfo* info) +{ + int i; + XkbDescPtr xkb = dev->key->xkbInfo->desc; + uint32_t *kc; + + info->type = KeyClass; + info->num_keycodes = xkb->max_key_code - xkb->min_key_code + 1; + info->length = sizeof(xXIKeyInfo)/4 + info->num_keycodes; + info->sourceid = dev->key->sourceid; + + kc = (uint32_t*)&info[1]; + for (i = xkb->min_key_code; i <= xkb->max_key_code; i++, kc++) + *kc = i; + + return info->length * 4; +} + +static void +SwapKeyInfo(DeviceIntPtr dev, xXIKeyInfo* info) +{ + char n; + uint32_t *key; + int i; + swaps(&info->type, n); + swaps(&info->length, n); + swaps(&info->sourceid, n); + + for (i = 0, key = (uint32_t*)&info[1]; i < info->num_keycodes; i++, key++) + swapl(key, n); + + swaps(&info->num_keycodes, n); +} + +/** + * List axis information for the given axis. + * + * @return The number of bytes written into info. + */ +int +ListValuatorInfo(DeviceIntPtr dev, xXIValuatorInfo* info, int axisnumber, + Bool reportState) +{ + ValuatorClassPtr v = dev->valuator; + + info->type = ValuatorClass; + info->length = sizeof(xXIValuatorInfo)/4; + info->label = v->axes[axisnumber].label; + info->min.integral = v->axes[axisnumber].min_value; + info->min.frac = 0; + info->max.integral = v->axes[axisnumber].max_value; + info->max.frac = 0; + info->value.integral = (int)v->axisVal[axisnumber]; + info->value.frac = (int)(v->axisVal[axisnumber] * (1 << 16) * (1 << 16)); + info->resolution = v->axes[axisnumber].resolution; + info->number = axisnumber; + info->mode = valuator_get_mode(dev, axisnumber); + info->sourceid = v->sourceid; + + if (!reportState) + info->value = info->min; + + return info->length * 4; +} + +static void +SwapValuatorInfo(DeviceIntPtr dev, xXIValuatorInfo* info) +{ + char n; + swaps(&info->type, n); + swaps(&info->length, n); + swapl(&info->label, n); + swapl(&info->min.integral, n); + swapl(&info->min.frac, n); + swapl(&info->max.integral, n); + swapl(&info->max.frac, n); + swaps(&info->number, n); + swaps(&info->sourceid, n); +} + +int GetDeviceUse(DeviceIntPtr dev, uint16_t *attachment) +{ + DeviceIntPtr master = GetMaster(dev, MASTER_ATTACHED); + int use; + + if (IsMaster(dev)) + { + DeviceIntPtr paired = GetPairedDevice(dev); + use = IsPointerDevice(dev) ? XIMasterPointer : XIMasterKeyboard; + *attachment = (paired ? paired->id : 0); + } else if (!IsFloating(dev)) + { + use = IsPointerDevice(master) ? XISlavePointer : XISlaveKeyboard; + *attachment = master->id; + } else + use = XIFloatingSlave; + + return use; +} + +/** + * Write the info for device dev into the buffer pointed to by info. + * + * @return The number of bytes used. + */ +static int +ListDeviceInfo(ClientPtr client, DeviceIntPtr dev, xXIDeviceInfo* info) +{ + char *any = (char*)&info[1]; + int len = 0, total_len = 0; + + info->deviceid = dev->id; + info->use = GetDeviceUse(dev, &info->attachment); + info->num_classes = 0; + info->name_len = strlen(dev->name); + info->enabled = dev->enabled; + total_len = sizeof(xXIDeviceInfo); + + len = pad_to_int32(info->name_len); + memset(any, 0, len); + strncpy(any, dev->name, info->name_len); + any += len; + total_len += len; + + total_len += ListDeviceClasses(client, dev, any, &info->num_classes); + return total_len; +} + +/** + * Write the class info of the device into the memory pointed to by any, set + * nclasses to the number of classes in total and return the number of bytes + * written. + */ +int +ListDeviceClasses(ClientPtr client, DeviceIntPtr dev, + char *any, uint16_t *nclasses) +{ + int total_len = 0; + int len; + int i; + int rc; + + /* Check if the current device state should be suppressed */ + rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixReadAccess); + + if (dev->button) + { + (*nclasses)++; + len = ListButtonInfo(dev, (xXIButtonInfo*)any, rc == Success); + any += len; + total_len += len; + } + + if (dev->key) + { + (*nclasses)++; + len = ListKeyInfo(dev, (xXIKeyInfo*)any); + any += len; + total_len += len; + } + + for (i = 0; dev->valuator && i < dev->valuator->numAxes; i++) + { + (*nclasses)++; + len = ListValuatorInfo(dev, (xXIValuatorInfo*)any, i, rc == Success); + any += len; + total_len += len; + } + + return total_len; +} + +static void +SwapDeviceInfo(DeviceIntPtr dev, xXIDeviceInfo* info) +{ + char n; + char *any = (char*)&info[1]; + int i; + + /* Skip over name */ + any += pad_to_int32(info->name_len); + + for (i = 0; i < info->num_classes; i++) + { + int len = ((xXIAnyInfo*)any)->length; + switch(((xXIAnyInfo*)any)->type) + { + case XIButtonClass: + SwapButtonInfo(dev, (xXIButtonInfo*)any); + break; + case XIKeyClass: + SwapKeyInfo(dev, (xXIKeyInfo*)any); + break; + case XIValuatorClass: + SwapValuatorInfo(dev, (xXIValuatorInfo*)any); + break; + } + + any += len * 4; + } + + swaps(&info->deviceid, n); + swaps(&info->use, n); + swaps(&info->attachment, n); + swaps(&info->num_classes, n); + swaps(&info->name_len, n); + +} diff --git a/xorg-server/Xi/xiquerypointer.c b/xorg-server/Xi/xiquerypointer.c index 2dc057d67..51317994b 100644 --- a/xorg-server/Xi/xiquerypointer.c +++ b/xorg-server/Xi/xiquerypointer.c @@ -1,229 +1,229 @@ -/*
- * Copyright 2007-2008 Peter Hutterer
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Author: Peter Hutterer, University of South Australia, NICTA
- */
-
-/***********************************************************************
- *
- * Request to query the pointer location of an extension input device.
- *
- */
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#include <X11/X.h> /* for inputstr.h */
-#include <X11/Xproto.h> /* Request macro */
-#include "inputstr.h" /* DeviceIntPtr */
-#include "windowstr.h" /* window structure */
-#include <X11/extensions/XI.h>
-#include <X11/extensions/XI2proto.h>
-#include "extnsionst.h"
-#include "exevents.h"
-#include "exglobals.h"
-#include "eventconvert.h"
-#include "scrnintstr.h"
-#include "xkbsrv.h"
-
-#ifdef PANORAMIX
-#include "panoramiXsrv.h"
-#endif
-
-#include "xiquerypointer.h"
-
-/***********************************************************************
- *
- * This procedure allows a client to query the pointer of a device.
- *
- */
-
-int
-SProcXIQueryPointer(ClientPtr client)
-{
- char n;
-
- REQUEST(xXIQueryPointerReq);
- swaps(&stuff->length, n);
- swaps(&stuff->deviceid, n);
- swapl(&stuff->win, n);
- return (ProcXIQueryPointer(client));
-}
-
-int
-ProcXIQueryPointer(ClientPtr client)
-{
- int rc;
- xXIQueryPointerReply rep;
- DeviceIntPtr pDev, kbd;
- WindowPtr pWin, t;
- SpritePtr pSprite;
- XkbStatePtr state;
- char *buttons = NULL;
- int buttons_size = 0; /* size of buttons array */
-
- REQUEST(xXIQueryPointerReq);
- REQUEST_SIZE_MATCH(xXIQueryPointerReq);
-
- rc = dixLookupDevice(&pDev, stuff->deviceid, client, DixReadAccess);
- if (rc != Success)
- {
- client->errorValue = stuff->deviceid;
- return rc;
- }
-
- if (pDev->valuator == NULL || IsKeyboardDevice(pDev) ||
- (!IsMaster(pDev) && pDev->u.master)) /* no attached devices */
- {
- client->errorValue = stuff->deviceid;
- return BadDevice;
- }
-
- rc = dixLookupWindow(&pWin, stuff->win, client, DixGetAttrAccess);
- if (rc != Success)
- {
- SendErrorToClient(client, IReqCode, X_XIQueryPointer,
- stuff->win, rc);
- return Success;
- }
-
- if (pDev->valuator->motionHintWindow)
- MaybeStopHint(pDev, client);
-
- if (IsMaster(pDev))
- kbd = GetPairedDevice(pDev);
- else
- kbd = (pDev->key) ? pDev : NULL;
-
- pSprite = pDev->spriteInfo->sprite;
-
- memset(&rep, 0, sizeof(rep));
- rep.repType = X_Reply;
- rep.RepType = X_XIQueryPointer;
- rep.length = 6;
- rep.sequenceNumber = client->sequence;
- rep.root = (GetCurrentRootWindow(pDev))->drawable.id;
- rep.root_x = FP1616(pSprite->hot.x, 0);
- rep.root_y = FP1616(pSprite->hot.y, 0);
- rep.child = None;
-
- if (kbd)
- {
- state = &kbd->key->xkbInfo->state;
- rep.mods.base_mods = state->base_mods;
- rep.mods.latched_mods = state->latched_mods;
- rep.mods.locked_mods = state->locked_mods;
-
- rep.group.base_group = state->base_group;
- rep.group.latched_group = state->latched_group;
- rep.group.locked_group = state->locked_group;
- }
-
- if (pDev->button)
- {
- int i, down;
- rep.buttons_len = bytes_to_int32(bits_to_bytes(pDev->button->numButtons));
- rep.length += rep.buttons_len;
- buttons_size = rep.buttons_len * 4;
- buttons = calloc(1, buttons_size);
- if (!buttons)
- return BadAlloc;
-
- down = pDev->button->buttonsDown;
-
- for (i = 0; i < pDev->button->numButtons && down; i++)
- {
- if (BitIsOn(pDev->button->down, i))
- {
- SetBit(buttons, i);
- down--;
- }
- }
- } else
- rep.buttons_len = 0;
-
- if (pSprite->hot.pScreen == pWin->drawable.pScreen)
- {
- rep.same_screen = xTrue;
- rep.win_x = FP1616(pSprite->hot.x - pWin->drawable.x, 0);
- rep.win_y = FP1616(pSprite->hot.y - pWin->drawable.y, 0);
- for (t = pSprite->win; t; t = t->parent)
- if (t->parent == pWin)
- {
- rep.child = t->drawable.id;
- break;
- }
- } else
- {
- rep.same_screen = xFalse;
- rep.win_x = 0;
- rep.win_y = 0;
- }
-
-#ifdef PANORAMIX
- if(!noPanoramiXExtension) {
- rep.root_x += FP1616(screenInfo.screens[0]->x, 0);
- rep.root_y += FP1616(screenInfo.screens[0]->y, 0);
- if (stuff->win == rep.root)
- {
- rep.win_x += FP1616(screenInfo.screens[0]->x, 0);
- rep.win_y += FP1616(screenInfo.screens[0]->y, 0);
- }
- }
-#endif
-
- WriteReplyToClient(client, sizeof(xXIQueryPointerReply), &rep);
- if (buttons)
- WriteToClient(client, buttons_size, buttons);
-
- free(buttons);
-
- return Success;
-}
-
-/***********************************************************************
- *
- * This procedure writes the reply for the XIQueryPointer function,
- * if the client and server have a different byte ordering.
- *
- */
-
-void
-SRepXIQueryPointer(ClientPtr client, int size,
- xXIQueryPointerReply * rep)
-{
- char n;
-
- swaps(&rep->sequenceNumber, n);
- swapl(&rep->length, n);
- swapl(&rep->root, n);
- swapl(&rep->child, n);
- swapl(&rep->root_x, n);
- swapl(&rep->root_y, n);
- swapl(&rep->win_x, n);
- swapl(&rep->win_y, n);
- swaps(&rep->buttons_len, n);
-
- WriteToClient(client, size, (char *)rep);
-}
-
+/* + * Copyright 2007-2008 Peter Hutterer + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Author: Peter Hutterer, University of South Australia, NICTA + */ + +/*********************************************************************** + * + * Request to query the pointer location of an extension input device. + * + */ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include <X11/X.h> /* for inputstr.h */ +#include <X11/Xproto.h> /* Request macro */ +#include "inputstr.h" /* DeviceIntPtr */ +#include "windowstr.h" /* window structure */ +#include <X11/extensions/XI.h> +#include <X11/extensions/XI2proto.h> +#include "extnsionst.h" +#include "exevents.h" +#include "exglobals.h" +#include "eventconvert.h" +#include "scrnintstr.h" +#include "xkbsrv.h" + +#ifdef PANORAMIX +#include "panoramiXsrv.h" +#endif + +#include "xiquerypointer.h" + +/*********************************************************************** + * + * This procedure allows a client to query the pointer of a device. + * + */ + +int +SProcXIQueryPointer(ClientPtr client) +{ + char n; + + REQUEST(xXIQueryPointerReq); + swaps(&stuff->length, n); + swaps(&stuff->deviceid, n); + swapl(&stuff->win, n); + return (ProcXIQueryPointer(client)); +} + +int +ProcXIQueryPointer(ClientPtr client) +{ + int rc; + xXIQueryPointerReply rep; + DeviceIntPtr pDev, kbd; + WindowPtr pWin, t; + SpritePtr pSprite; + XkbStatePtr state; + char *buttons = NULL; + int buttons_size = 0; /* size of buttons array */ + + REQUEST(xXIQueryPointerReq); + REQUEST_SIZE_MATCH(xXIQueryPointerReq); + + rc = dixLookupDevice(&pDev, stuff->deviceid, client, DixReadAccess); + if (rc != Success) + { + client->errorValue = stuff->deviceid; + return rc; + } + + if (pDev->valuator == NULL || IsKeyboardDevice(pDev) || + (!IsMaster(pDev) && !IsFloating(pDev))) /* no attached devices */ + { + client->errorValue = stuff->deviceid; + return BadDevice; + } + + rc = dixLookupWindow(&pWin, stuff->win, client, DixGetAttrAccess); + if (rc != Success) + { + SendErrorToClient(client, IReqCode, X_XIQueryPointer, + stuff->win, rc); + return Success; + } + + if (pDev->valuator->motionHintWindow) + MaybeStopHint(pDev, client); + + if (IsMaster(pDev)) + kbd = GetPairedDevice(pDev); + else + kbd = (pDev->key) ? pDev : NULL; + + pSprite = pDev->spriteInfo->sprite; + + memset(&rep, 0, sizeof(rep)); + rep.repType = X_Reply; + rep.RepType = X_XIQueryPointer; + rep.length = 6; + rep.sequenceNumber = client->sequence; + rep.root = (GetCurrentRootWindow(pDev))->drawable.id; + rep.root_x = FP1616(pSprite->hot.x, 0); + rep.root_y = FP1616(pSprite->hot.y, 0); + rep.child = None; + + if (kbd) + { + state = &kbd->key->xkbInfo->state; + rep.mods.base_mods = state->base_mods; + rep.mods.latched_mods = state->latched_mods; + rep.mods.locked_mods = state->locked_mods; + + rep.group.base_group = state->base_group; + rep.group.latched_group = state->latched_group; + rep.group.locked_group = state->locked_group; + } + + if (pDev->button) + { + int i, down; + rep.buttons_len = bytes_to_int32(bits_to_bytes(pDev->button->numButtons)); + rep.length += rep.buttons_len; + buttons_size = rep.buttons_len * 4; + buttons = calloc(1, buttons_size); + if (!buttons) + return BadAlloc; + + down = pDev->button->buttonsDown; + + for (i = 0; i < pDev->button->numButtons && down; i++) + { + if (BitIsOn(pDev->button->down, i)) + { + SetBit(buttons, i); + down--; + } + } + } else + rep.buttons_len = 0; + + if (pSprite->hot.pScreen == pWin->drawable.pScreen) + { + rep.same_screen = xTrue; + rep.win_x = FP1616(pSprite->hot.x - pWin->drawable.x, 0); + rep.win_y = FP1616(pSprite->hot.y - pWin->drawable.y, 0); + for (t = pSprite->win; t; t = t->parent) + if (t->parent == pWin) + { + rep.child = t->drawable.id; + break; + } + } else + { + rep.same_screen = xFalse; + rep.win_x = 0; + rep.win_y = 0; + } + +#ifdef PANORAMIX + if(!noPanoramiXExtension) { + rep.root_x += FP1616(screenInfo.screens[0]->x, 0); + rep.root_y += FP1616(screenInfo.screens[0]->y, 0); + if (stuff->win == rep.root) + { + rep.win_x += FP1616(screenInfo.screens[0]->x, 0); + rep.win_y += FP1616(screenInfo.screens[0]->y, 0); + } + } +#endif + + WriteReplyToClient(client, sizeof(xXIQueryPointerReply), &rep); + if (buttons) + WriteToClient(client, buttons_size, buttons); + + free(buttons); + + return Success; +} + +/*********************************************************************** + * + * This procedure writes the reply for the XIQueryPointer function, + * if the client and server have a different byte ordering. + * + */ + +void +SRepXIQueryPointer(ClientPtr client, int size, + xXIQueryPointerReply * rep) +{ + char n; + + swaps(&rep->sequenceNumber, n); + swapl(&rep->length, n); + swapl(&rep->root, n); + swapl(&rep->child, n); + swapl(&rep->root_x, n); + swapl(&rep->root_y, n); + swapl(&rep->win_x, n); + swapl(&rep->win_y, n); + swaps(&rep->buttons_len, n); + + WriteToClient(client, size, (char *)rep); +} + diff --git a/xorg-server/Xi/xiwarppointer.c b/xorg-server/Xi/xiwarppointer.c index c01b115f3..a463ab94d 100644 --- a/xorg-server/Xi/xiwarppointer.c +++ b/xorg-server/Xi/xiwarppointer.c @@ -97,7 +97,7 @@ ProcXIWarpPointer(ClientPtr client) return rc; } - if ((!IsMaster(pDev) && pDev->u.master) || + if ((!IsMaster(pDev) && !IsFloating(pDev)) || (IsMaster(pDev) && !IsPointerDevice(pDev))) { client->errorValue = stuff->deviceid; diff --git a/xorg-server/configure.ac b/xorg-server/configure.ac index 85d5c980e..681f9d9c5 100644 --- a/xorg-server/configure.ac +++ b/xorg-server/configure.ac @@ -26,8 +26,8 @@ dnl dnl Process this file with autoconf to create configure. AC_PREREQ(2.57) -AC_INIT([xorg-server], 1.10.0, [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg], xorg-server) -RELEASE_DATE="2011-2-25" +AC_INIT([xorg-server], 1.10.99.1, [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg], xorg-server) +RELEASE_DATE="unreleased" AC_CONFIG_SRCDIR([Makefile.am]) AM_INIT_AUTOMAKE([foreign dist-bzip2]) AM_MAINTAINER_MODE @@ -312,19 +312,6 @@ AC_CHECK_HEADER([execinfo.h],[ ])] ) -dnl ARM needs additional compiler flags for proper backtraces if GCC is -dnl used. Compile a dummy program with the -mapcs-frame option. If it -dnl succeeds, we know that we are building for ARM with GCC. -old_CFLAGS="$CFLAGS" -CFLAGS="-mapcs-frame" -AC_COMPILE_IFELSE( - AC_LANG_PROGRAM([[ ]]), - ARM_BACKTRACE_CFLAGS="$CFLAGS", - ARM_BACKTRACE_CFLAGS="" -) -CFLAGS="$old_CFLAGS" -AC_SUBST(ARM_BACKTRACE_CFLAGS) - dnl --------------------------------------------------------------------------- dnl Bus options and CPU capabilities. Replaces logic in dnl hw/xfree86/os-support/bus/Makefile.am, among others. @@ -626,7 +613,6 @@ AC_ARG_ENABLE(xf86vidmode, AS_HELP_STRING([--disable-xf86vidmode], [Build XF8 AC_ARG_ENABLE(xace, AS_HELP_STRING([--disable-xace], [Build X-ACE extension (default: enabled)]), [XACE=$enableval], [XACE=yes]) AC_ARG_ENABLE(xselinux, AS_HELP_STRING([--enable-xselinux], [Build SELinux extension (default: disabled)]), [XSELINUX=$enableval], [XSELINUX=no]) AC_ARG_ENABLE(xcsecurity, AS_HELP_STRING([--enable-xcsecurity], [Build Security extension (default: disabled)]), [XCSECURITY=$enableval], [XCSECURITY=no]) -AC_ARG_ENABLE(xcalibrate, AS_HELP_STRING([--enable-xcalibrate], [Build XCalibrate extension (default: disabled)]), [XCALIBRATE=$enableval], [XCALIBRATE=no]) AC_ARG_ENABLE(tslib, AS_HELP_STRING([--enable-tslib], [Build kdrive tslib touchscreen support (default: disabled)]), [TSLIB=$enableval], [TSLIB=no]) AC_ARG_ENABLE(dbe, AS_HELP_STRING([--disable-dbe], [Build DBE extension (default: enabled)]), [DBE=$enableval], [DBE=yes]) AC_ARG_ENABLE(xf86bigfont, AS_HELP_STRING([--enable-xf86bigfont], [Build XF86 Big Font extension (default: disabled)]), [XF86BIGFONT=$enableval], [XF86BIGFONT=no]) @@ -641,6 +627,7 @@ AC_ARG_ENABLE(vbe, AS_HELP_STRING([--enable-vbe], [Build Xorg with VB AC_ARG_ENABLE(int10-module, AS_HELP_STRING([--enable-int10-module], [Build Xorg with int10 module (default: enabled)]), [INT10MODULE=$enableval], [INT10MODULE=yes]) AC_ARG_ENABLE(windowswm, AS_HELP_STRING([--enable-windowswm], [Build XWin with WindowsWM extension (default: no)]), [WINDOWSWM=$enableval], [WINDOWSWM=no]) AC_ARG_ENABLE(libdrm, AS_HELP_STRING([--enable-libdrm], [Build Xorg with libdrm support (default: enabled)]), [DRM=$enableval],[DRM=yes]) +AC_ARG_ENABLE(clientids, AS_HELP_STRING([--disable-clientids], [Build Xorg with client ID tracking (default: enabled)]), [CLIENTIDS=$enableval], [CLIENTIDS=yes]) dnl DDXes. AC_ARG_ENABLE(xorg, AS_HELP_STRING([--enable-xorg], [Build Xorg server (default: auto)]), [XORG=$enableval], [XORG=auto]) @@ -779,7 +766,6 @@ DRIPROTO="xf86driproto >= 2.1.0" DRI2PROTO="dri2proto >= 2.3" XINERAMAPROTO="xineramaproto" BIGFONTPROTO="xf86bigfontproto >= 1.2.0" -XCALIBRATEPROTO="xcalibrateproto" DGAPROTO="xf86dgaproto >= 2.0.99.1" GLPROTO="glproto >= 1.4.10" DMXPROTO="dmxproto >= 2.2.99.1" @@ -807,7 +793,7 @@ LIBGLIB="glib-2.0 >= 2.16" LIBUDEV="libudev >= 143" LIBSELINUX="libselinux >= 2.0.86" LIBDBUS="dbus-1 >= 1.0" -LIBPIXMAN="pixman-1 >= 0.15.20" +LIBPIXMAN="pixman-1 >= 0.21.6" dnl Pixman is always required, but we separate it out so we can link dnl specific modules against it @@ -994,6 +980,18 @@ if test "x$RES" = xyes; then REQUIRED_MODULES="$REQUIRED_MODULES $RESOURCEPROTO" fi +# The XRes extension may support client ID tracking only if it has +# been specifically enabled. Client ID tracking is implicitly not +# supported if XRes extension is disabled. +AC_MSG_CHECKING([whether to track client ids]) +if test "x$RES" = xyes && test "x$CLIENTIDS" = xyes; then + AC_DEFINE(CLIENTIDS, 1, [Support client ID tracking]) +else + CLIENTIDS=no +fi +AC_MSG_RESULT([$CLIENTIDS]) +AM_CONDITIONAL(CLIENTIDS, [test "x$CLIENTIDS" = xyes]) + if test "x$GLX" = xyes; then PKG_CHECK_MODULES([XLIB], [x11]) PKG_CHECK_MODULES([GL], $GLPROTO $LIBGL) @@ -1120,14 +1118,6 @@ if test "x$DPMSExtension" = xyes; then AC_DEFINE(DPMSExtension, 1, [Support DPMS extension]) fi -if test "x$XCALIBRATE" = xyes && test "$KDRIVE" = yes; then - AC_DEFINE(XCALIBRATE, 1, [Build XCalibrate extension]) - REQUIRED_MODULES="$REQUIRED_MODULES $XCALIBRATEPROTO" -else - XCALIBRATE=no -fi -AM_CONDITIONAL(XCALIBRATE, [test "x$XCALIBRATE" = xyes]) - AC_DEFINE(RENDER, 1, [Support RENDER extension]) RENDER_LIB='$(top_builddir)/render/librender.la' RENDER_INC='-I$(top_srcdir)/render' @@ -1525,7 +1515,7 @@ if test "x$XNEST" = xyes; then if test "x$have_xnest" = xno; then AC_MSG_ERROR([Xnest build explicitly requested, but required modules not found.]) fi - XNEST_LIBS="$FB_LIB $FIXES_LIB $MI_LIB $XEXT_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $DIX_LIB $MAIN_LIB $OS_LIB" + XNEST_LIBS="$FB_LIB $FIXES_LIB $MI_LIB $XEXT_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $MAIN_LIB $DIX_LIB $OS_LIB" XNEST_SYS_LIBS="$XNESTMODULES_LIBS $GLX_SYS_LIBS" AC_SUBST([XNEST_LIBS]) AC_SUBST([XNEST_SYS_LIBS]) @@ -1923,7 +1913,7 @@ if test "x$XQUARTZ" = xyes; then AC_CHECK_LIB([Xplugin],[xp_init],[:]) - CFLAGS="${CFLAGS} -DROOTLESS_SAFEALPHA -DNO_ALLOCA" + CFLAGS="${CFLAGS} -DROOTLESS_WORKAROUND -DROOTLESS_SAFEALPHA -DNO_ALLOCA" PKG_CHECK_MODULES(XPBPROXY, $APPLEWMPROTO $LIBAPPLEWM xfixes x11) diff --git a/xorg-server/dix/devices.c b/xorg-server/dix/devices.c index 89294aacb..e57c27b00 100644 --- a/xorg-server/dix/devices.c +++ b/xorg-server/dix/devices.c @@ -446,7 +446,7 @@ DisableDevice(DeviceIntPtr dev, BOOL sendevent) { for (other = inputInfo.devices; other; other = other->next) { - if (other->u.master == dev) + if (!IsMaster(other) && GetMaster(other, MASTER_ATTACHED) == dev) { AttachDevice(NULL, other, NULL); flags[other->id] |= XISlaveDetached; @@ -457,8 +457,8 @@ DisableDevice(DeviceIntPtr dev, BOOL sendevent) { for (other = inputInfo.devices; other; other = other->next) { - if (IsMaster(other) && other->u.lastSlave == dev) - other->u.lastSlave = NULL; + if (IsMaster(other) && other->lastSlave == dev) + other->lastSlave = NULL; } } @@ -987,8 +987,8 @@ CloseDownDevices(void) */ for (dev = inputInfo.devices; dev; dev = dev->next) { - if (!IsMaster(dev) && dev->u.master) - dev->u.master = NULL; + if (!IsMaster(dev) && !IsFloating(dev)) + dev->master = NULL; } CloseDeviceList(&inputInfo.devices); @@ -1281,10 +1281,11 @@ InitValuatorClassDeviceStruct(DeviceIntPtr dev, int numAxes, Atom *labels, /* global list of acceleration schemes */ ValuatorAccelerationRec pointerAccelerationScheme[] = { - {PtrAccelNoOp, NULL, NULL, NULL}, - {PtrAccelPredictable, acceleratePointerPredictable, NULL, AccelerationDefaultCleanup}, - {PtrAccelLightweight, acceleratePointerLightweight, NULL, NULL}, - {-1, NULL, NULL, NULL} /* terminator */ + {PtrAccelNoOp, NULL, NULL, NULL, NULL}, + {PtrAccelPredictable, acceleratePointerPredictable, NULL, + InitPredictableAccelerationScheme, AccelerationDefaultCleanup}, + {PtrAccelLightweight, acceleratePointerLightweight, NULL, NULL, NULL}, + {-1, NULL, NULL, NULL, NULL} /* terminator */ }; /** @@ -1296,59 +1297,37 @@ InitPointerAccelerationScheme(DeviceIntPtr dev, int scheme) { int x, i = -1; - void* data = NULL; ValuatorClassPtr val; val = dev->valuator; - if(!val) - return FALSE; + if (!val) + return FALSE; - if(IsMaster(dev) && scheme != PtrAccelNoOp) + if (IsMaster(dev) && scheme != PtrAccelNoOp) return FALSE; - for(x = 0; pointerAccelerationScheme[x].number >= 0; x++) { + for (x = 0; pointerAccelerationScheme[x].number >= 0; x++) { if(pointerAccelerationScheme[x].number == scheme){ i = x; break; } } - if(-1 == i) + if (-1 == i) return FALSE; if (val->accelScheme.AccelCleanupProc) val->accelScheme.AccelCleanupProc(dev); - /* init scheme-specific data */ - switch(scheme){ - case PtrAccelPredictable: - { - DeviceVelocityPtr s; - s = malloc(sizeof(DeviceVelocityRec)); - if(!s) - return FALSE; - InitVelocityData(s); - data = s; - break; + if (pointerAccelerationScheme[i].AccelInitProc) { + if (!pointerAccelerationScheme[i].AccelInitProc(dev, + &pointerAccelerationScheme[i])) { + return FALSE; } - default: - break; + } else { + val->accelScheme = pointerAccelerationScheme[i]; } - - val->accelScheme = pointerAccelerationScheme[i]; - val->accelScheme.accelData = data; - - /* post-init scheme */ - switch(scheme){ - case PtrAccelPredictable: - InitializePredictableAccelerationProperties(dev); - break; - - default: - break; - } - return TRUE; } @@ -1666,7 +1645,7 @@ ProcChangeKeyboardMapping(ClientPtr client) stuff->keyCodes, NULL, client); for (tmp = inputInfo.devices; tmp; tmp = tmp->next) { - if (IsMaster(tmp) || tmp->u.master != pDev) + if (IsMaster(tmp) || GetMaster(tmp, MASTER_KEYBOARD) != pDev) continue; if (!tmp->key) continue; @@ -2329,7 +2308,7 @@ RecalculateMasterButtons(DeviceIntPtr slave) for (dev = inputInfo.devices; dev; dev = dev->next) { if (IsMaster(dev) || - dev->u.master != master || + GetMaster(dev, MASTER_ATTACHED) != master || !dev->button) continue; @@ -2378,6 +2357,46 @@ RecalculateMasterButtons(DeviceIntPtr slave) } /** + * Generate release events for all keys/button currently down on this + * device. + */ +static void +ReleaseButtonsAndKeys(DeviceIntPtr dev) +{ + EventListPtr eventlist = InitEventList(GetMaximumEventsNum()); + ButtonClassPtr b = dev->button; + KeyClassPtr k = dev->key; + int i, j, nevents; + + if (!eventlist) /* no release events for you */ + return; + + /* Release all buttons */ + for (i = 0; b && i < b->numButtons; i++) + { + if (BitIsOn(b->down, i)) + { + nevents = GetPointerEvents(eventlist, dev, ButtonRelease, i, 0, NULL); + for (j = 0; j < nevents; j++) + mieqProcessDeviceEvent(dev, (InternalEvent*)(eventlist+j)->event, NULL); + } + } + + /* Release all keys */ + for (i = 0; k && i < MAP_LENGTH; i++) + { + if (BitIsOn(k->down, i)) + { + nevents = GetKeyboardEvents(eventlist, dev, KeyRelease, i); + for (j = 0; j < nevents; j++) + mieqProcessDeviceEvent(dev, (InternalEvent*)(eventlist+j)->event, NULL); + } + } + + FreeEventList(eventlist, GetMaximumEventsNum()); +} + +/** * Attach device 'dev' to device 'master'. * Client is set to the client that issued the request, or NULL if it comes * from some internal automatic pairing. @@ -2399,19 +2418,21 @@ AttachDevice(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr master) return BadDevice; /* set from floating to floating? */ - if (!dev->u.master && !master && dev->enabled) + if (IsFloating(dev) && !master && dev->enabled) return Success; /* free the existing sprite. */ - if (!dev->u.master && dev->spriteInfo->paired == dev) + if (IsFloating(dev) && dev->spriteInfo->paired == dev) { screen = miPointerGetScreen(dev); screen->DeviceCursorCleanup(dev, screen); free(dev->spriteInfo->sprite); } - oldmaster = dev->u.master; - dev->u.master = master; + ReleaseButtonsAndKeys(dev); + + oldmaster = GetMaster(dev, MASTER_ATTACHED); + dev->master = master; /* If device is set to floating, we need to create a sprite for it, * otherwise things go bad. However, we don't want to render the cursor, @@ -2461,8 +2482,8 @@ AttachDevice(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr master) DeviceIntPtr GetPairedDevice(DeviceIntPtr dev) { - if (!IsMaster(dev) && dev->u.master) - dev = dev->u.master; + if (!IsMaster(dev) && !IsFloating(dev)) + dev = GetMaster(dev, MASTER_ATTACHED); return dev->spriteInfo->paired; } @@ -2475,7 +2496,10 @@ GetPairedDevice(DeviceIntPtr dev) * returned master is either the device itself or the paired master device. * If dev is a floating slave device, NULL is returned. * - * @type ::MASTER_KEYBOARD or ::MASTER_POINTER + * @type ::MASTER_KEYBOARD or ::MASTER_POINTER or ::MASTER_ATTACHED + * @return The requested master device. In the case of MASTER_ATTACHED, this + * is the directly attached master to this device, regardless of the type. + * Otherwise, it is either the master keyboard or pointer for this device. */ DeviceIntPtr GetMaster(DeviceIntPtr dev, int which) @@ -2485,9 +2509,9 @@ GetMaster(DeviceIntPtr dev, int which) if (IsMaster(dev)) master = dev; else - master = dev->u.master; + master = dev->master; - if (master) + if (master && which != MASTER_ATTACHED) { if (which == MASTER_KEYBOARD) { @@ -2540,7 +2564,7 @@ AllocDevicePair (ClientPtr client, char* name, pointer->coreEvents = TRUE; pointer->spriteInfo->spriteOwner = TRUE; - pointer->u.lastSlave = NULL; + pointer->lastSlave = NULL; pointer->last.slave = NULL; pointer->type = (master) ? MASTER_POINTER : SLAVE; @@ -2566,7 +2590,7 @@ AllocDevicePair (ClientPtr client, char* name, keyboard->coreEvents = TRUE; keyboard->spriteInfo->spriteOwner = FALSE; - keyboard->u.lastSlave = NULL; + keyboard->lastSlave = NULL; keyboard->last.slave = NULL; keyboard->type = (master) ? MASTER_KEYBOARD : SLAVE; diff --git a/xorg-server/dix/dispatch.c b/xorg-server/dix/dispatch.c index 2474c2f3b..601b14a71 100644 --- a/xorg-server/dix/dispatch.c +++ b/xorg-server/dix/dispatch.c @@ -1,3901 +1,3911 @@ -/************************************************************
-
-Copyright 1987, 1989, 1998 The Open Group
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation.
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
-AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of The Open Group shall not be
-used in advertising or otherwise to promote the sale, use or other dealings
-in this Software without prior written authorization from The Open Group.
-
-
-Copyright 1987, 1989 by Digital Equipment Corporation, Maynard, Massachusetts.
-
- All Rights Reserved
-
-Permission 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 that
-both that copyright notice and this permission notice appear in
-supporting documentation, and that the name of Digital not be
-used in advertising or publicity pertaining to distribution of the
-software without specific, written prior permission.
-
-DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
-ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
-DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
-ANY 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 THIS
-SOFTWARE.
-
-********************************************************/
-
-/* The panoramix components contained the following notice */
-/*****************************************************************
-
-Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software.
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING,
-BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY,
-WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
-IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of Digital Equipment Corporation
-shall not be used in advertising or otherwise to promote the sale, use or other
-dealings in this Software without prior written authorization from Digital
-Equipment Corporation.
-
-******************************************************************/
-
-/* XSERVER_DTRACE additions:
- * Copyright (c) 2005-2006, Oracle and/or its affiliates. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#include <version-config.h>
-#endif
-
-#ifdef PANORAMIX_DEBUG
-#include <stdio.h>
-int ProcInitialConnection();
-#endif
-
-#include "windowstr.h"
-#include <X11/fonts/fontstruct.h>
-#include "dixfontstr.h"
-#include "gcstruct.h"
-#include "selection.h"
-#include "colormapst.h"
-#include "cursorstr.h"
-#include "scrnintstr.h"
-#include "opaque.h"
-#include "input.h"
-#include "servermd.h"
-#include "extnsionst.h"
-#include "dixfont.h"
-#include "dispatch.h"
-#include "swaprep.h"
-#include "swapreq.h"
-#include "privates.h"
-#include "xace.h"
-#include "inputstr.h"
-#include "xkbsrv.h"
-#include "site.h"
-
-#ifdef XSERVER_DTRACE
-#include "registry.h"
-#include <sys/types.h>
-typedef const char *string;
-#include "Xserver-dtrace.h"
-#endif
-
-#define mskcnt ((MAXCLIENTS + 31) / 32)
-#define BITMASK(i) (1U << ((i) & 31))
-#define MASKIDX(i) ((i) >> 5)
-#define MASKWORD(buf, i) buf[MASKIDX(i)]
-#define BITSET(buf, i) MASKWORD(buf, i) |= BITMASK(i)
-#define BITCLEAR(buf, i) MASKWORD(buf, i) &= ~BITMASK(i)
-#define GETBIT(buf, i) (MASKWORD(buf, i) & BITMASK(i))
-
-xConnSetupPrefix connSetupPrefix;
-
-PaddingInfo PixmapWidthPaddingInfo[33];
-
-static ClientPtr grabClient;
-#define GrabNone 0
-#define GrabActive 1
-#define GrabKickout 2
-static int grabState = GrabNone;
-static long grabWaiters[mskcnt];
-CallbackListPtr ServerGrabCallback = NULL;
-HWEventQueuePtr checkForInput[2];
-int connBlockScreenStart;
-
-static void KillAllClients(void);
-
-static int nextFreeClientID; /* always MIN free client ID */
-
-static int nClients; /* number of authorized clients */
-
-CallbackListPtr ClientStateCallback;
-
-/* dispatchException & isItTimeToYield must be declared volatile since they
- * are modified by signal handlers - otherwise optimizer may assume it doesn't
- * need to actually check value in memory when used and may miss changes from
- * signal handlers.
- */
-volatile char dispatchException = 0;
-volatile char isItTimeToYield;
-
-#define SAME_SCREENS(a, b) (\
- (a.pScreen == b.pScreen))
-
-void
-SetInputCheck(HWEventQueuePtr c0, HWEventQueuePtr c1)
-{
- checkForInput[0] = c0;
- checkForInput[1] = c1;
-}
-
-void
-UpdateCurrentTime(void)
-{
- TimeStamp systime;
-
- /* To avoid time running backwards, we must call GetTimeInMillis before
- * calling ProcessInputEvents.
- */
- systime.months = currentTime.months;
- systime.milliseconds = GetTimeInMillis();
- if (systime.milliseconds < currentTime.milliseconds)
- systime.months++;
- if (*checkForInput[0] != *checkForInput[1])
- ProcessInputEvents();
- if (CompareTimeStamps(systime, currentTime) == LATER)
- currentTime = systime;
-}
-
-/* Like UpdateCurrentTime, but can't call ProcessInputEvents */
-void
-UpdateCurrentTimeIf(void)
-{
- TimeStamp systime;
-
- systime.months = currentTime.months;
- systime.milliseconds = GetTimeInMillis();
- if (systime.milliseconds < currentTime.milliseconds)
- systime.months++;
- if (*checkForInput[0] == *checkForInput[1])
- currentTime = systime;
-}
-
-
-#undef SMART_DEBUG
-
-#define SMART_SCHEDULE_DEFAULT_INTERVAL 20 /* ms */
-#define SMART_SCHEDULE_MAX_SLICE 200 /* ms */
-
-Bool SmartScheduleDisable = FALSE;
-long SmartScheduleSlice = SMART_SCHEDULE_DEFAULT_INTERVAL;
-long SmartScheduleInterval = SMART_SCHEDULE_DEFAULT_INTERVAL;
-long SmartScheduleMaxSlice = SMART_SCHEDULE_MAX_SLICE;
-long SmartScheduleTime;
-int SmartScheduleLatencyLimited = 0;
-static ClientPtr SmartLastClient;
-static int SmartLastIndex[SMART_MAX_PRIORITY-SMART_MIN_PRIORITY+1];
-
-#ifdef SMART_DEBUG
-long SmartLastPrint;
-#endif
-
-void Dispatch(void);
-
-static int
-SmartScheduleClient (int *clientReady, int nready)
-{
- ClientPtr pClient;
- int i;
- int client;
- int bestPrio, best = 0;
- int bestRobin, robin;
- long now = SmartScheduleTime;
- long idle;
-
- bestPrio = -0x7fffffff;
- bestRobin = 0;
- idle = 2 * SmartScheduleSlice;
- for (i = 0; i < nready; i++)
- {
- client = clientReady[i];
- pClient = clients[client];
- /* Praise clients which are idle */
- if ((now - pClient->smart_check_tick) >= idle)
- {
- if (pClient->smart_priority < 0)
- pClient->smart_priority++;
- }
- pClient->smart_check_tick = now;
-
- /* check priority to select best client */
- robin = (pClient->index - SmartLastIndex[pClient->smart_priority-SMART_MIN_PRIORITY]) & 0xff;
- if (pClient->smart_priority > bestPrio ||
- (pClient->smart_priority == bestPrio && robin > bestRobin))
- {
- bestPrio = pClient->smart_priority;
- bestRobin = robin;
- best = client;
- }
-#ifdef SMART_DEBUG
- if ((now - SmartLastPrint) >= 5000)
- fprintf (stderr, " %2d: %3d", client, pClient->smart_priority);
-#endif
- }
-#ifdef SMART_DEBUG
- if ((now - SmartLastPrint) >= 5000)
- {
- fprintf (stderr, " use %2d\n", best);
- SmartLastPrint = now;
- }
-#endif
- pClient = clients[best];
- SmartLastIndex[bestPrio-SMART_MIN_PRIORITY] = pClient->index;
- /*
- * Set current client pointer
- */
- if (SmartLastClient != pClient)
- {
- pClient->smart_start_tick = now;
- SmartLastClient = pClient;
- }
- /*
- * Adjust slice
- */
- if (nready == 1 && SmartScheduleLatencyLimited == 0)
- {
- /*
- * If it's been a long time since another client
- * has run, bump the slice up to get maximal
- * performance from a single client
- */
- if ((now - pClient->smart_start_tick) > 1000 &&
- SmartScheduleSlice < SmartScheduleMaxSlice)
- {
- SmartScheduleSlice += SmartScheduleInterval;
- }
- }
- else
- {
- SmartScheduleSlice = SmartScheduleInterval;
- }
- return best;
-}
-
-void
-EnableLimitedSchedulingLatency(void)
-{
- ++SmartScheduleLatencyLimited;
- SmartScheduleSlice = SmartScheduleInterval;
-}
-
-void
-DisableLimitedSchedulingLatency(void)
-{
- --SmartScheduleLatencyLimited;
-
- /* protect against bugs */
- if (SmartScheduleLatencyLimited < 0)
- SmartScheduleLatencyLimited = 0;
-}
-
-#define MAJOROP ((xReq *)client->requestBuffer)->reqType
-
-void
-Dispatch(void)
-{
- int *clientReady; /* array of request ready clients */
- int result;
- ClientPtr client;
- int nready;
- HWEventQueuePtr* icheck = checkForInput;
- long start_tick;
-
- nextFreeClientID = 1;
- nClients = 0;
-
- clientReady = malloc(sizeof(int) * MaxClients);
- if (!clientReady)
- return;
-
- SmartScheduleSlice = SmartScheduleInterval;
- while (!dispatchException)
- {
- if (*icheck[0] != *icheck[1])
- {
- ProcessInputEvents();
- FlushIfCriticalOutputPending();
- }
-
- nready = WaitForSomething(clientReady);
-
- if (nready && !SmartScheduleDisable)
- {
- clientReady[0] = SmartScheduleClient (clientReady, nready);
- nready = 1;
- }
- /*****************
- * Handle events in round robin fashion, doing input between
- * each round
- *****************/
-
- while (!dispatchException && (--nready >= 0))
- {
- client = clients[clientReady[nready]];
- if (! client)
- {
- /* KillClient can cause this to happen */
- continue;
- }
- /* GrabServer activation can cause this to be true */
- if (grabState == GrabKickout)
- {
- grabState = GrabActive;
- break;
- }
- isItTimeToYield = FALSE;
-
- start_tick = SmartScheduleTime;
- while (!isItTimeToYield)
- {
- if (*icheck[0] != *icheck[1])
- ProcessInputEvents();
-
- FlushIfCriticalOutputPending();
- if (!SmartScheduleDisable &&
- (SmartScheduleTime - start_tick) >= SmartScheduleSlice)
- {
- /* Penalize clients which consume ticks */
- if (client->smart_priority > SMART_MIN_PRIORITY)
- client->smart_priority--;
- break;
- }
- /* now, finally, deal with client requests */
-
- result = ReadRequestFromClient(client);
- if (result <= 0)
- {
- if (result < 0)
- CloseDownClient(client);
- break;
- }
-
- client->sequence++;
-#ifdef XSERVER_DTRACE
- XSERVER_REQUEST_START(LookupMajorName(MAJOROP), MAJOROP,
- ((xReq *)client->requestBuffer)->length,
- client->index, client->requestBuffer);
-#endif
- if (result > (maxBigRequestSize << 2))
- result = BadLength;
- else {
- result = XaceHookDispatch(client, MAJOROP);
- if (result == Success)
- result = (* client->requestVector[MAJOROP])(client);
- XaceHookAuditEnd(client, result);
- }
-#ifdef XSERVER_DTRACE
- XSERVER_REQUEST_DONE(LookupMajorName(MAJOROP), MAJOROP,
- client->sequence, client->index, result);
-#endif
-
- if (client->noClientException != Success)
- {
- CloseDownClient(client);
- break;
- }
- else if (result != Success)
- {
- SendErrorToClient(client, MAJOROP,
- MinorOpcodeOfRequest(client),
- client->errorValue, result);
- break;
- }
- }
- FlushAllOutput();
- client = clients[clientReady[nready]];
- if (client)
- client->smart_stop_tick = SmartScheduleTime;
- }
- dispatchException &= ~DE_PRIORITYCHANGE;
- }
-#if defined(DDXBEFORERESET)
- ddxBeforeReset ();
-#endif
- KillAllClients();
- free(clientReady);
- dispatchException &= ~DE_RESET;
- SmartScheduleLatencyLimited = 0;
-}
-
-#undef MAJOROP
-
-static int VendorRelease = VENDOR_RELEASE;
-static char *VendorString = VENDOR_NAME;
-
-static const int padlength[4] = {0, 3, 2, 1};
-
-void
-SetVendorRelease(int release)
-{
- VendorRelease = release;
-}
-
-void
-SetVendorString(char *string)
-{
- VendorString = string;
-}
-
-Bool
-CreateConnectionBlock(void)
-{
- xConnSetup setup;
- xWindowRoot root;
- xDepth depth;
- xVisualType visual;
- xPixmapFormat format;
- unsigned long vid;
- int i, j, k,
- lenofblock,
- sizesofar = 0;
- char *pBuf;
-
-
- memset(&setup, 0, sizeof(xConnSetup));
- /* Leave off the ridBase and ridMask, these must be sent with
- connection */
-
- setup.release = VendorRelease;
- /*
- * per-server image and bitmap parameters are defined in Xmd.h
- */
- setup.imageByteOrder = screenInfo.imageByteOrder;
-
- setup.bitmapScanlineUnit = screenInfo.bitmapScanlineUnit;
- setup.bitmapScanlinePad = screenInfo.bitmapScanlinePad;
-
- setup.bitmapBitOrder = screenInfo.bitmapBitOrder;
- setup.motionBufferSize = NumMotionEvents();
- setup.numRoots = screenInfo.numScreens;
- setup.nbytesVendor = strlen(VendorString);
- setup.numFormats = screenInfo.numPixmapFormats;
- setup.maxRequestSize = MAX_REQUEST_SIZE;
- QueryMinMaxKeyCodes(&setup.minKeyCode, &setup.maxKeyCode);
-
- lenofblock = sizeof(xConnSetup) +
- pad_to_int32(setup.nbytesVendor) +
- (setup.numFormats * sizeof(xPixmapFormat)) +
- (setup.numRoots * sizeof(xWindowRoot));
- ConnectionInfo = malloc(lenofblock);
- if (!ConnectionInfo)
- return FALSE;
-
- memmove(ConnectionInfo, (char *)&setup, sizeof(xConnSetup));
- sizesofar = sizeof(xConnSetup);
- pBuf = ConnectionInfo + sizeof(xConnSetup);
-
- memmove(pBuf, VendorString, (int)setup.nbytesVendor);
- sizesofar += setup.nbytesVendor;
- pBuf += setup.nbytesVendor;
- i = padlength[setup.nbytesVendor & 3];
- sizesofar += i;
- while (--i >= 0)
- *pBuf++ = 0;
-
- memset(&format, 0, sizeof(xPixmapFormat));
- for (i=0; i<screenInfo.numPixmapFormats; i++)
- {
- format.depth = screenInfo.formats[i].depth;
- format.bitsPerPixel = screenInfo.formats[i].bitsPerPixel;
- format.scanLinePad = screenInfo.formats[i].scanlinePad;
- memmove(pBuf, (char *)&format, sizeof(xPixmapFormat));
- pBuf += sizeof(xPixmapFormat);
- sizesofar += sizeof(xPixmapFormat);
- }
-
- connBlockScreenStart = sizesofar;
- memset(&depth, 0, sizeof(xDepth));
- memset(&visual, 0, sizeof(xVisualType));
- for (i=0; i<screenInfo.numScreens; i++)
- {
- ScreenPtr pScreen;
- DepthPtr pDepth;
- VisualPtr pVisual;
-
- pScreen = screenInfo.screens[i];
- root.windowId = pScreen->root->drawable.id;
- root.defaultColormap = pScreen->defColormap;
- root.whitePixel = pScreen->whitePixel;
- root.blackPixel = pScreen->blackPixel;
- root.currentInputMask = 0; /* filled in when sent */
- root.pixWidth = pScreen->width;
- root.pixHeight = pScreen->height;
- root.mmWidth = pScreen->mmWidth;
- root.mmHeight = pScreen->mmHeight;
- root.minInstalledMaps = pScreen->minInstalledCmaps;
- root.maxInstalledMaps = pScreen->maxInstalledCmaps;
- root.rootVisualID = pScreen->rootVisual;
- root.backingStore = pScreen->backingStoreSupport;
- root.saveUnders = FALSE;
- root.rootDepth = pScreen->rootDepth;
- root.nDepths = pScreen->numDepths;
- memmove(pBuf, (char *)&root, sizeof(xWindowRoot));
- sizesofar += sizeof(xWindowRoot);
- pBuf += sizeof(xWindowRoot);
-
- pDepth = pScreen->allowedDepths;
- for(j = 0; j < pScreen->numDepths; j++, pDepth++)
- {
- lenofblock += sizeof(xDepth) +
- (pDepth->numVids * sizeof(xVisualType));
- pBuf = (char *)realloc(ConnectionInfo, lenofblock);
- if (!pBuf)
- {
- free(ConnectionInfo);
- return FALSE;
- }
- ConnectionInfo = pBuf;
- pBuf += sizesofar;
- depth.depth = pDepth->depth;
- depth.nVisuals = pDepth->numVids;
- memmove(pBuf, (char *)&depth, sizeof(xDepth));
- pBuf += sizeof(xDepth);
- sizesofar += sizeof(xDepth);
- for(k = 0; k < pDepth->numVids; k++)
- {
- vid = pDepth->vids[k];
- for (pVisual = pScreen->visuals;
- pVisual->vid != vid;
- pVisual++)
- ;
- visual.visualID = vid;
- visual.class = pVisual->class;
- visual.bitsPerRGB = pVisual->bitsPerRGBValue;
- visual.colormapEntries = pVisual->ColormapEntries;
- visual.redMask = pVisual->redMask;
- visual.greenMask = pVisual->greenMask;
- visual.blueMask = pVisual->blueMask;
- memmove(pBuf, (char *)&visual, sizeof(xVisualType));
- pBuf += sizeof(xVisualType);
- sizesofar += sizeof(xVisualType);
- }
- }
- }
- connSetupPrefix.success = xTrue;
- connSetupPrefix.length = lenofblock/4;
- connSetupPrefix.majorVersion = X_PROTOCOL;
- connSetupPrefix.minorVersion = X_PROTOCOL_REVISION;
- return TRUE;
-}
-
-
-int
-ProcBadRequest(ClientPtr client)
-{
- return BadRequest;
-}
-
-int
-ProcCreateWindow(ClientPtr client)
-{
- WindowPtr pParent, pWin;
- REQUEST(xCreateWindowReq);
- int len, rc;
-
- REQUEST_AT_LEAST_SIZE(xCreateWindowReq);
-
- LEGAL_NEW_RESOURCE(stuff->wid, client);
- rc = dixLookupWindow(&pParent, stuff->parent, client, DixAddAccess);
- if (rc != Success)
- return rc;
- len = client->req_len - bytes_to_int32(sizeof(xCreateWindowReq));
- if (Ones(stuff->mask) != len)
- return BadLength;
- if (!stuff->width || !stuff->height)
- {
- client->errorValue = 0;
- return BadValue;
- }
- pWin = CreateWindow(stuff->wid, pParent, stuff->x,
- stuff->y, stuff->width, stuff->height,
- stuff->borderWidth, stuff->class,
- stuff->mask, (XID *) &stuff[1],
- (int)stuff->depth,
- client, stuff->visual, &rc);
- if (pWin)
- {
- Mask mask = pWin->eventMask;
-
- pWin->eventMask = 0; /* subterfuge in case AddResource fails */
- if (!AddResource(stuff->wid, RT_WINDOW, (pointer)pWin))
- return BadAlloc;
- pWin->eventMask = mask;
- }
- return rc;
-}
-
-int
-ProcChangeWindowAttributes(ClientPtr client)
-{
- WindowPtr pWin;
- REQUEST(xChangeWindowAttributesReq);
- int len, rc;
- Mask access_mode = 0;
-
- REQUEST_AT_LEAST_SIZE(xChangeWindowAttributesReq);
- access_mode |= (stuff->valueMask & CWEventMask) ? DixReceiveAccess : 0;
- access_mode |= (stuff->valueMask & ~CWEventMask) ? DixSetAttrAccess : 0;
- rc = dixLookupWindow(&pWin, stuff->window, client, access_mode);
- if (rc != Success)
- return rc;
- len = client->req_len - bytes_to_int32(sizeof(xChangeWindowAttributesReq));
- if (len != Ones(stuff->valueMask))
- return BadLength;
- return ChangeWindowAttributes(pWin,
- stuff->valueMask,
- (XID *) &stuff[1],
- client);
-}
-
-int
-ProcGetWindowAttributes(ClientPtr client)
-{
- WindowPtr pWin;
- REQUEST(xResourceReq);
- xGetWindowAttributesReply wa;
- int rc;
-
- REQUEST_SIZE_MATCH(xResourceReq);
- rc = dixLookupWindow(&pWin, stuff->id, client, DixGetAttrAccess);
- if (rc != Success)
- return rc;
- memset(&wa, 0, sizeof(xGetWindowAttributesReply));
- GetWindowAttributes(pWin, client, &wa);
- WriteReplyToClient(client, sizeof(xGetWindowAttributesReply), &wa);
- return Success;
-}
-
-int
-ProcDestroyWindow(ClientPtr client)
-{
- WindowPtr pWin;
- REQUEST(xResourceReq);
- int rc;
-
- REQUEST_SIZE_MATCH(xResourceReq);
- rc = dixLookupWindow(&pWin, stuff->id, client, DixDestroyAccess);
- if (rc != Success)
- return rc;
- if (pWin->parent) {
- rc = dixLookupWindow(&pWin, pWin->parent->drawable.id, client,
- DixRemoveAccess);
- if (rc != Success)
- return rc;
- FreeResource(stuff->id, RT_NONE);
- }
- return Success;
-}
-
-int
-ProcDestroySubwindows(ClientPtr client)
-{
- WindowPtr pWin;
- REQUEST(xResourceReq);
- int rc;
-
- REQUEST_SIZE_MATCH(xResourceReq);
- rc = dixLookupWindow(&pWin, stuff->id, client, DixRemoveAccess);
- if (rc != Success)
- return rc;
- DestroySubwindows(pWin, client);
- return Success;
-}
-
-int
-ProcChangeSaveSet(ClientPtr client)
-{
- WindowPtr pWin;
- REQUEST(xChangeSaveSetReq);
- int rc;
-
- REQUEST_SIZE_MATCH(xChangeSaveSetReq);
- rc = dixLookupWindow(&pWin, stuff->window, client, DixManageAccess);
- if (rc != Success)
- return rc;
- if (client->clientAsMask == (CLIENT_BITS(pWin->drawable.id)))
- return BadMatch;
- if ((stuff->mode == SetModeInsert) || (stuff->mode == SetModeDelete))
- return AlterSaveSetForClient(client, pWin, stuff->mode, FALSE, TRUE);
- client->errorValue = stuff->mode;
- return BadValue;
-}
-
-int
-ProcReparentWindow(ClientPtr client)
-{
- WindowPtr pWin, pParent;
- REQUEST(xReparentWindowReq);
- int rc;
-
- REQUEST_SIZE_MATCH(xReparentWindowReq);
- rc = dixLookupWindow(&pWin, stuff->window, client, DixManageAccess);
- if (rc != Success)
- return rc;
- rc = dixLookupWindow(&pParent, stuff->parent, client, DixAddAccess);
- if (rc != Success)
- return rc;
- if (!SAME_SCREENS(pWin->drawable, pParent->drawable))
- return BadMatch;
- if ((pWin->backgroundState == ParentRelative) &&
- (pParent->drawable.depth != pWin->drawable.depth))
- return BadMatch;
- if ((pWin->drawable.class != InputOnly) &&
- (pParent->drawable.class == InputOnly))
- return BadMatch;
- return ReparentWindow(pWin, pParent,
- (short)stuff->x, (short)stuff->y, client);
-}
-
-int
-ProcMapWindow(ClientPtr client)
-{
- WindowPtr pWin;
- REQUEST(xResourceReq);
- int rc;
-
- REQUEST_SIZE_MATCH(xResourceReq);
- rc = dixLookupWindow(&pWin, stuff->id, client, DixShowAccess);
- if (rc != Success)
- return rc;
- MapWindow(pWin, client);
- /* update cache to say it is mapped */
- return Success;
-}
-
-int
-ProcMapSubwindows(ClientPtr client)
-{
- WindowPtr pWin;
- REQUEST(xResourceReq);
- int rc;
-
- REQUEST_SIZE_MATCH(xResourceReq);
- rc = dixLookupWindow(&pWin, stuff->id, client, DixListAccess);
- if (rc != Success)
- return rc;
- MapSubwindows(pWin, client);
- /* update cache to say it is mapped */
- return Success;
-}
-
-int
-ProcUnmapWindow(ClientPtr client)
-{
- WindowPtr pWin;
- REQUEST(xResourceReq);
- int rc;
-
- REQUEST_SIZE_MATCH(xResourceReq);
- rc = dixLookupWindow(&pWin, stuff->id, client, DixHideAccess);
- if (rc != Success)
- return rc;
- UnmapWindow(pWin, FALSE);
- /* update cache to say it is mapped */
- return Success;
-}
-
-int
-ProcUnmapSubwindows(ClientPtr client)
-{
- WindowPtr pWin;
- REQUEST(xResourceReq);
- int rc;
-
- REQUEST_SIZE_MATCH(xResourceReq);
- rc = dixLookupWindow(&pWin, stuff->id, client, DixListAccess);
- if (rc != Success)
- return rc;
- UnmapSubwindows(pWin);
- return Success;
-}
-
-int
-ProcConfigureWindow(ClientPtr client)
-{
- WindowPtr pWin;
- REQUEST(xConfigureWindowReq);
- int len, rc;
-
- REQUEST_AT_LEAST_SIZE(xConfigureWindowReq);
- rc = dixLookupWindow(&pWin, stuff->window, client,
- DixManageAccess|DixSetAttrAccess);
- if (rc != Success)
- return rc;
- len = client->req_len - bytes_to_int32(sizeof(xConfigureWindowReq));
- if (Ones((Mask)stuff->mask) != len)
- return BadLength;
- return ConfigureWindow(pWin, (Mask)stuff->mask, (XID *) &stuff[1], client);
-}
-
-int
-ProcCirculateWindow(ClientPtr client)
-{
- WindowPtr pWin;
- REQUEST(xCirculateWindowReq);
- int rc;
-
- REQUEST_SIZE_MATCH(xCirculateWindowReq);
- if ((stuff->direction != RaiseLowest) &&
- (stuff->direction != LowerHighest))
- {
- client->errorValue = stuff->direction;
- return BadValue;
- }
- rc = dixLookupWindow(&pWin, stuff->window, client, DixManageAccess);
- if (rc != Success)
- return rc;
- CirculateWindow(pWin, (int)stuff->direction, client);
- return Success;
-}
-
-static int
-GetGeometry(ClientPtr client, xGetGeometryReply *rep)
-{
- DrawablePtr pDraw;
- int rc;
- REQUEST(xResourceReq);
- REQUEST_SIZE_MATCH(xResourceReq);
-
- rc = dixLookupDrawable(&pDraw, stuff->id, client, M_ANY, DixGetAttrAccess);
- if (rc != Success)
- return rc;
-
- rep->type = X_Reply;
- rep->length = 0;
- rep->sequenceNumber = client->sequence;
- rep->root = pDraw->pScreen->root->drawable.id;
- rep->depth = pDraw->depth;
- rep->width = pDraw->width;
- rep->height = pDraw->height;
-
- if (WindowDrawable(pDraw->type))
- {
- WindowPtr pWin = (WindowPtr)pDraw;
- rep->x = pWin->origin.x - wBorderWidth (pWin);
- rep->y = pWin->origin.y - wBorderWidth (pWin);
- rep->borderWidth = pWin->borderWidth;
- }
- else /* DRAWABLE_PIXMAP */
- {
- rep->x = rep->y = rep->borderWidth = 0;
- }
-
- return Success;
-}
-
-
-int
-ProcGetGeometry(ClientPtr client)
-{
- xGetGeometryReply rep;
- int status;
-
- memset(&rep, 0, sizeof(xGetGeometryReply));
- if ((status = GetGeometry(client, &rep)) != Success)
- return status;
-
- WriteReplyToClient(client, sizeof(xGetGeometryReply), &rep);
- return Success;
-}
-
-
-int
-ProcQueryTree(ClientPtr client)
-{
- xQueryTreeReply reply;
- int rc, numChildren = 0;
- WindowPtr pChild, pWin, pHead;
- Window *childIDs = (Window *)NULL;
- REQUEST(xResourceReq);
-
- REQUEST_SIZE_MATCH(xResourceReq);
- rc = dixLookupWindow(&pWin, stuff->id, client, DixListAccess);
- if (rc != Success)
- return rc;
- memset(&reply, 0, sizeof(xQueryTreeReply));
- reply.type = X_Reply;
- reply.root = pWin->drawable.pScreen->root->drawable.id;
- reply.sequenceNumber = client->sequence;
- if (pWin->parent)
- reply.parent = pWin->parent->drawable.id;
- else
- reply.parent = (Window)None;
- pHead = RealChildHead(pWin);
- for (pChild = pWin->lastChild; pChild != pHead; pChild = pChild->prevSib)
- numChildren++;
- if (numChildren)
- {
- int curChild = 0;
-
- childIDs = malloc(numChildren * sizeof(Window));
- if (!childIDs)
- return BadAlloc;
- for (pChild = pWin->lastChild; pChild != pHead; pChild = pChild->prevSib)
- childIDs[curChild++] = pChild->drawable.id;
- }
-
- reply.nChildren = numChildren;
- reply.length = bytes_to_int32(numChildren * sizeof(Window));
-
- WriteReplyToClient(client, sizeof(xQueryTreeReply), &reply);
- if (numChildren)
- {
- client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write;
- WriteSwappedDataToClient(client, numChildren * sizeof(Window), childIDs);
- free(childIDs);
- }
-
- return Success;
-}
-
-int
-ProcInternAtom(ClientPtr client)
-{
- Atom atom;
- char *tchar;
- REQUEST(xInternAtomReq);
-
- REQUEST_FIXED_SIZE(xInternAtomReq, stuff->nbytes);
- if ((stuff->onlyIfExists != xTrue) && (stuff->onlyIfExists != xFalse))
- {
- client->errorValue = stuff->onlyIfExists;
- return BadValue;
- }
- tchar = (char *) &stuff[1];
- atom = MakeAtom(tchar, stuff->nbytes, !stuff->onlyIfExists);
- if (atom != BAD_RESOURCE)
- {
- xInternAtomReply reply;
- memset(&reply, 0, sizeof(xInternAtomReply));
- reply.type = X_Reply;
- reply.length = 0;
- reply.sequenceNumber = client->sequence;
- reply.atom = atom;
- WriteReplyToClient(client, sizeof(xInternAtomReply), &reply);
- return Success;
- }
- else
- return BadAlloc;
-}
-
-int
-ProcGetAtomName(ClientPtr client)
-{
- const char *str;
- xGetAtomNameReply reply;
- int len;
- REQUEST(xResourceReq);
-
- REQUEST_SIZE_MATCH(xResourceReq);
- if ( (str = NameForAtom(stuff->id)) )
- {
- len = strlen(str);
- memset(&reply, 0, sizeof(xGetAtomNameReply));
- reply.type = X_Reply;
- reply.length = bytes_to_int32(len);
- reply.sequenceNumber = client->sequence;
- reply.nameLength = len;
- WriteReplyToClient(client, sizeof(xGetAtomNameReply), &reply);
- (void)WriteToClient(client, len, str);
- return Success;
- }
- else
- {
- client->errorValue = stuff->id;
- return BadAtom;
- }
-}
-
-int
-ProcGrabServer(ClientPtr client)
-{
- int rc;
- REQUEST_SIZE_MATCH(xReq);
- if (grabState != GrabNone && client != grabClient)
- {
- ResetCurrentRequest(client);
- client->sequence--;
- BITSET(grabWaiters, client->index);
- IgnoreClient(client);
- return Success;
- }
- rc = OnlyListenToOneClient(client);
- if (rc != Success)
- return rc;
- grabState = GrabKickout;
- grabClient = client;
-
- if (ServerGrabCallback)
- {
- ServerGrabInfoRec grabinfo;
- grabinfo.client = client;
- grabinfo.grabstate = SERVER_GRABBED;
- CallCallbacks(&ServerGrabCallback, (pointer)&grabinfo);
- }
-
- return Success;
-}
-
-static void
-UngrabServer(ClientPtr client)
-{
- int i;
-
- grabState = GrabNone;
- ListenToAllClients();
- for (i = mskcnt; --i >= 0 && !grabWaiters[i]; )
- ;
- if (i >= 0)
- {
- i <<= 5;
- while (!GETBIT(grabWaiters, i))
- i++;
- BITCLEAR(grabWaiters, i);
- AttendClient(clients[i]);
- }
-
- if (ServerGrabCallback)
- {
- ServerGrabInfoRec grabinfo;
- grabinfo.client = client;
- grabinfo.grabstate = SERVER_UNGRABBED;
- CallCallbacks(&ServerGrabCallback, (pointer)&grabinfo);
- }
-}
-
-int
-ProcUngrabServer(ClientPtr client)
-{
- REQUEST_SIZE_MATCH(xReq);
- UngrabServer(client);
- return Success;
-}
-
-int
-ProcTranslateCoords(ClientPtr client)
-{
- REQUEST(xTranslateCoordsReq);
-
- WindowPtr pWin, pDst;
- xTranslateCoordsReply rep;
- int rc;
-
- REQUEST_SIZE_MATCH(xTranslateCoordsReq);
- rc = dixLookupWindow(&pWin, stuff->srcWid, client, DixGetAttrAccess);
- if (rc != Success)
- return rc;
- rc = dixLookupWindow(&pDst, stuff->dstWid, client, DixGetAttrAccess);
- if (rc != Success)
- return rc;
- memset(&rep, 0, sizeof(xTranslateCoordsReply));
- rep.type = X_Reply;
- rep.length = 0;
- rep.sequenceNumber = client->sequence;
- if (!SAME_SCREENS(pWin->drawable, pDst->drawable))
- {
- rep.sameScreen = xFalse;
- rep.child = None;
- rep.dstX = rep.dstY = 0;
- }
- else
- {
- INT16 x, y;
- rep.sameScreen = xTrue;
- rep.child = None;
- /* computing absolute coordinates -- adjust to destination later */
- x = pWin->drawable.x + stuff->srcX;
- y = pWin->drawable.y + stuff->srcY;
- pWin = pDst->firstChild;
- while (pWin)
- {
- BoxRec box;
- if ((pWin->mapped) &&
- (x >= pWin->drawable.x - wBorderWidth (pWin)) &&
- (x < pWin->drawable.x + (int)pWin->drawable.width +
- wBorderWidth (pWin)) &&
- (y >= pWin->drawable.y - wBorderWidth (pWin)) &&
- (y < pWin->drawable.y + (int)pWin->drawable.height +
- wBorderWidth (pWin))
- /* When a window is shaped, a further check
- * is made to see if the point is inside
- * borderSize
- */
- && (!wBoundingShape(pWin) ||
- RegionContainsPoint(&pWin->borderSize, x, y, &box))
-
- && (!wInputShape(pWin) ||
- RegionContainsPoint(wInputShape(pWin),
- x - pWin->drawable.x,
- y - pWin->drawable.y, &box))
- )
- {
- rep.child = pWin->drawable.id;
- pWin = (WindowPtr) NULL;
- }
- else
- pWin = pWin->nextSib;
- }
- /* adjust to destination coordinates */
- rep.dstX = x - pDst->drawable.x;
- rep.dstY = y - pDst->drawable.y;
- }
- WriteReplyToClient(client, sizeof(xTranslateCoordsReply), &rep);
- return Success;
-}
-
-int
-ProcOpenFont(ClientPtr client)
-{
- int err;
- REQUEST(xOpenFontReq);
-
- REQUEST_FIXED_SIZE(xOpenFontReq, stuff->nbytes);
- client->errorValue = stuff->fid;
- LEGAL_NEW_RESOURCE(stuff->fid, client);
- err = OpenFont(client, stuff->fid, (Mask) 0,
- stuff->nbytes, (char *)&stuff[1]);
- if (err == Success)
- {
- return Success;
- }
- else
- return err;
-}
-
-int
-ProcCloseFont(ClientPtr client)
-{
- FontPtr pFont;
- int rc;
- REQUEST(xResourceReq);
-
- REQUEST_SIZE_MATCH(xResourceReq);
- rc = dixLookupResourceByType((pointer *)&pFont, stuff->id, RT_FONT,
- client, DixDestroyAccess);
- if (rc == Success)
- {
- FreeResource(stuff->id, RT_NONE);
- return Success;
- }
- else
- {
- client->errorValue = stuff->id;
- return rc;
- }
-}
-
-int
-ProcQueryFont(ClientPtr client)
-{
- xQueryFontReply *reply;
- FontPtr pFont;
- int rc;
- REQUEST(xResourceReq);
- REQUEST_SIZE_MATCH(xResourceReq);
-
- rc = dixLookupFontable(&pFont, stuff->id, client, DixGetAttrAccess);
- if (rc != Success)
- return rc;
-
- {
- xCharInfo *pmax = FONTINKMAX(pFont);
- xCharInfo *pmin = FONTINKMIN(pFont);
- int nprotoxcistructs;
- int rlength;
-
- nprotoxcistructs = (
- pmax->rightSideBearing == pmin->rightSideBearing &&
- pmax->leftSideBearing == pmin->leftSideBearing &&
- pmax->descent == pmin->descent &&
- pmax->ascent == pmin->ascent &&
- pmax->characterWidth == pmin->characterWidth) ?
- 0 : N2dChars(pFont);
-
- rlength = sizeof(xQueryFontReply) +
- FONTINFONPROPS(FONTCHARSET(pFont)) * sizeof(xFontProp) +
- nprotoxcistructs * sizeof(xCharInfo);
- reply = calloc(1, rlength);
- if(!reply)
- {
- return BadAlloc;
- }
-
- reply->type = X_Reply;
- reply->length = bytes_to_int32(rlength - sizeof(xGenericReply));
- reply->sequenceNumber = client->sequence;
- QueryFont( pFont, reply, nprotoxcistructs);
-
- WriteReplyToClient(client, rlength, reply);
- free(reply);
- return Success;
- }
-}
-
-int
-ProcQueryTextExtents(ClientPtr client)
-{
- xQueryTextExtentsReply reply;
- FontPtr pFont;
- ExtentInfoRec info;
- unsigned long length;
- int rc;
- REQUEST(xQueryTextExtentsReq);
- REQUEST_AT_LEAST_SIZE(xQueryTextExtentsReq);
-
- rc = dixLookupFontable(&pFont, stuff->fid, client, DixGetAttrAccess);
- if (rc != Success)
- return rc;
-
- length = client->req_len - bytes_to_int32(sizeof(xQueryTextExtentsReq));
- length = length << 1;
- if (stuff->oddLength)
- {
- if (length == 0)
- return BadLength;
- length--;
- }
- if (!QueryTextExtents(pFont, length, (unsigned char *)&stuff[1], &info))
- return BadAlloc;
- reply.type = X_Reply;
- reply.length = 0;
- reply.sequenceNumber = client->sequence;
- reply.drawDirection = info.drawDirection;
- reply.fontAscent = info.fontAscent;
- reply.fontDescent = info.fontDescent;
- reply.overallAscent = info.overallAscent;
- reply.overallDescent = info.overallDescent;
- reply.overallWidth = info.overallWidth;
- reply.overallLeft = info.overallLeft;
- reply.overallRight = info.overallRight;
- WriteReplyToClient(client, sizeof(xQueryTextExtentsReply), &reply);
- return Success;
-}
-
-int
-ProcListFonts(ClientPtr client)
-{
- REQUEST(xListFontsReq);
-
- REQUEST_FIXED_SIZE(xListFontsReq, stuff->nbytes);
-
- return ListFonts(client, (unsigned char *) &stuff[1], stuff->nbytes,
- stuff->maxNames);
-}
-
-int
-ProcListFontsWithInfo(ClientPtr client)
-{
- REQUEST(xListFontsWithInfoReq);
-
- REQUEST_FIXED_SIZE(xListFontsWithInfoReq, stuff->nbytes);
-
- return StartListFontsWithInfo(client, stuff->nbytes,
- (unsigned char *) &stuff[1], stuff->maxNames);
-}
-
-/**
- *
- * \param value must conform to DeleteType
- */
-int
-dixDestroyPixmap(pointer value, XID pid)
-{
- PixmapPtr pPixmap = (PixmapPtr)value;
- return (*pPixmap->drawable.pScreen->DestroyPixmap)(pPixmap);
-}
-
-int
-ProcCreatePixmap(ClientPtr client)
-{
- PixmapPtr pMap;
- DrawablePtr pDraw;
- REQUEST(xCreatePixmapReq);
- DepthPtr pDepth;
- int i, rc;
-
- REQUEST_SIZE_MATCH(xCreatePixmapReq);
- client->errorValue = stuff->pid;
- LEGAL_NEW_RESOURCE(stuff->pid, client);
-
- rc = dixLookupDrawable(&pDraw, stuff->drawable, client, M_ANY,
- DixGetAttrAccess);
- if (rc != Success)
- return rc;
-
- if (!stuff->width || !stuff->height)
- {
- client->errorValue = 0;
- return BadValue;
- }
- if (stuff->width > 32767 || stuff->height > 32767)
- {
- /* It is allowed to try and allocate a pixmap which is larger than
- * 32767 in either dimension. However, all of the framebuffer code
- * is buggy and does not reliably draw to such big pixmaps, basically
- * because the Region data structure operates with signed shorts
- * for the rectangles in it.
- *
- * Furthermore, several places in the X server computes the
- * size in bytes of the pixmap and tries to store it in an
- * integer. This integer can overflow and cause the allocated size
- * to be much smaller.
- *
- * So, such big pixmaps are rejected here with a BadAlloc
- */
- return BadAlloc;
- }
- if (stuff->depth != 1)
- {
- pDepth = pDraw->pScreen->allowedDepths;
- for (i=0; i<pDraw->pScreen->numDepths; i++, pDepth++)
- if (pDepth->depth == stuff->depth)
- goto CreatePmap;
- client->errorValue = stuff->depth;
- return BadValue;
- }
-CreatePmap:
- pMap = (PixmapPtr)(*pDraw->pScreen->CreatePixmap)
- (pDraw->pScreen, stuff->width,
- stuff->height, stuff->depth, 0);
- if (pMap)
- {
- pMap->drawable.serialNumber = NEXT_SERIAL_NUMBER;
- pMap->drawable.id = stuff->pid;
- /* security creation/labeling check */
- rc = XaceHook(XACE_RESOURCE_ACCESS, client, stuff->pid, RT_PIXMAP,
- pMap, RT_NONE, NULL, DixCreateAccess);
- if (rc != Success) {
- (*pDraw->pScreen->DestroyPixmap)(pMap);
- return rc;
- }
- if (AddResource(stuff->pid, RT_PIXMAP, (pointer)pMap))
- return Success;
- (*pDraw->pScreen->DestroyPixmap)(pMap);
- }
- return BadAlloc;
-}
-
-int
-ProcFreePixmap(ClientPtr client)
-{
- PixmapPtr pMap;
- int rc;
- REQUEST(xResourceReq);
- REQUEST_SIZE_MATCH(xResourceReq);
-
- rc = dixLookupResourceByType((pointer *)&pMap, stuff->id, RT_PIXMAP, client,
- DixDestroyAccess);
- if (rc == Success)
- {
- FreeResource(stuff->id, RT_NONE);
- return Success;
- }
- else
- {
- client->errorValue = stuff->id;
- return rc;
- }
-}
-
-int
-ProcCreateGC(ClientPtr client)
-{
- int error, rc;
- GC *pGC;
- DrawablePtr pDraw;
- unsigned len;
- REQUEST(xCreateGCReq);
-
- REQUEST_AT_LEAST_SIZE(xCreateGCReq);
- client->errorValue = stuff->gc;
- LEGAL_NEW_RESOURCE(stuff->gc, client);
- rc = dixLookupDrawable(&pDraw, stuff->drawable, client, 0,
- DixGetAttrAccess);
- if (rc != Success)
- return rc;
-
- len = client->req_len - bytes_to_int32(sizeof(xCreateGCReq));
- if (len != Ones(stuff->mask))
- return BadLength;
- pGC = (GC *)CreateGC(pDraw, stuff->mask, (XID *) &stuff[1], &error,
- stuff->gc, client);
- if (error != Success)
- return error;
- if (!AddResource(stuff->gc, RT_GC, (pointer)pGC))
- return BadAlloc;
- return Success;
-}
-
-int
-ProcChangeGC(ClientPtr client)
-{
- GC *pGC;
- int result;
- unsigned len;
- REQUEST(xChangeGCReq);
- REQUEST_AT_LEAST_SIZE(xChangeGCReq);
-
- result = dixLookupGC(&pGC, stuff->gc, client, DixSetAttrAccess);
- if (result != Success)
- return result;
-
- len = client->req_len - bytes_to_int32(sizeof(xChangeGCReq));
- if (len != Ones(stuff->mask))
- return BadLength;
-
- return ChangeGCXIDs(client, pGC, stuff->mask, (CARD32 *) &stuff[1]);
-}
-
-int
-ProcCopyGC(ClientPtr client)
-{
- GC *dstGC;
- GC *pGC;
- int result;
- REQUEST(xCopyGCReq);
- REQUEST_SIZE_MATCH(xCopyGCReq);
-
- result = dixLookupGC(&pGC, stuff->srcGC, client, DixGetAttrAccess);
- if (result != Success)
- return result;
- result = dixLookupGC(&dstGC, stuff->dstGC, client, DixSetAttrAccess);
- if (result != Success)
- return result;
- if ((dstGC->pScreen != pGC->pScreen) || (dstGC->depth != pGC->depth))
- return BadMatch;
- if (stuff->mask & ~GCAllBits)
- {
- client->errorValue = stuff->mask;
- return BadValue;
- }
- return CopyGC(pGC, dstGC, stuff->mask);
-}
-
-int
-ProcSetDashes(ClientPtr client)
-{
- GC *pGC;
- int result;
- REQUEST(xSetDashesReq);
-
- REQUEST_FIXED_SIZE(xSetDashesReq, stuff->nDashes);
- if (stuff->nDashes == 0)
- {
- client->errorValue = 0;
- return BadValue;
- }
-
- result = dixLookupGC(&pGC,stuff->gc, client, DixSetAttrAccess);
- if (result != Success)
- return result;
-
- /* If there's an error, either there's no sensible errorValue,
- * or there was a dash segment of 0. */
- client->errorValue = 0;
- return SetDashes(pGC, stuff->dashOffset, stuff->nDashes,
- (unsigned char *)&stuff[1]);
-}
-
-int
-ProcSetClipRectangles(ClientPtr client)
-{
- int nr, result;
- GC *pGC;
- REQUEST(xSetClipRectanglesReq);
-
- REQUEST_AT_LEAST_SIZE(xSetClipRectanglesReq);
- if ((stuff->ordering != Unsorted) && (stuff->ordering != YSorted) &&
- (stuff->ordering != YXSorted) && (stuff->ordering != YXBanded))
- {
- client->errorValue = stuff->ordering;
- return BadValue;
- }
- result = dixLookupGC(&pGC,stuff->gc, client, DixSetAttrAccess);
- if (result != Success)
- return result;
-
- nr = (client->req_len << 2) - sizeof(xSetClipRectanglesReq);
- if (nr & 4)
- return BadLength;
- nr >>= 3;
- return SetClipRects(pGC, stuff->xOrigin, stuff->yOrigin,
- nr, (xRectangle *)&stuff[1], (int)stuff->ordering);
-}
-
-int
-ProcFreeGC(ClientPtr client)
-{
- GC *pGC;
- int rc;
- REQUEST(xResourceReq);
- REQUEST_SIZE_MATCH(xResourceReq);
-
- rc = dixLookupGC(&pGC, stuff->id, client, DixDestroyAccess);
- if (rc != Success)
- return rc;
-
- FreeResource(stuff->id, RT_NONE);
- return Success;
-}
-
-int
-ProcClearToBackground(ClientPtr client)
-{
- REQUEST(xClearAreaReq);
- WindowPtr pWin;
- int rc;
-
- REQUEST_SIZE_MATCH(xClearAreaReq);
- rc = dixLookupWindow(&pWin, stuff->window, client, DixWriteAccess);
- if (rc != Success)
- return rc;
- if (pWin->drawable.class == InputOnly)
- {
- client->errorValue = stuff->window;
- return BadMatch;
- }
- if ((stuff->exposures != xTrue) && (stuff->exposures != xFalse))
- {
- client->errorValue = stuff->exposures;
- return BadValue;
- }
- (*pWin->drawable.pScreen->ClearToBackground)(pWin, stuff->x, stuff->y,
- stuff->width, stuff->height,
- (Bool)stuff->exposures);
- return Success;
-}
-
-int
-ProcCopyArea(ClientPtr client)
-{
- DrawablePtr pDst;
- DrawablePtr pSrc;
- GC *pGC;
- REQUEST(xCopyAreaReq);
- RegionPtr pRgn;
- int rc;
-
- REQUEST_SIZE_MATCH(xCopyAreaReq);
-
- VALIDATE_DRAWABLE_AND_GC(stuff->dstDrawable, pDst, DixWriteAccess);
- if (stuff->dstDrawable != stuff->srcDrawable)
- {
- rc = dixLookupDrawable(&pSrc, stuff->srcDrawable, client, 0,
- DixReadAccess);
- if (rc != Success)
- return rc;
- if ((pDst->pScreen != pSrc->pScreen) || (pDst->depth != pSrc->depth))
- {
- client->errorValue = stuff->dstDrawable;
- return BadMatch;
- }
- }
- else
- pSrc = pDst;
-
- pRgn = (*pGC->ops->CopyArea)(pSrc, pDst, pGC, stuff->srcX, stuff->srcY,
- stuff->width, stuff->height,
- stuff->dstX, stuff->dstY);
- if (pGC->graphicsExposures)
- {
- (*pDst->pScreen->SendGraphicsExpose)
- (client, pRgn, stuff->dstDrawable, X_CopyArea, 0);
- if (pRgn)
- RegionDestroy(pRgn);
- }
-
- return Success;
-}
-
-int
-ProcCopyPlane(ClientPtr client)
-{
- DrawablePtr psrcDraw, pdstDraw;
- GC *pGC;
- REQUEST(xCopyPlaneReq);
- RegionPtr pRgn;
- int rc;
-
- REQUEST_SIZE_MATCH(xCopyPlaneReq);
-
- VALIDATE_DRAWABLE_AND_GC(stuff->dstDrawable, pdstDraw, DixWriteAccess);
- if (stuff->dstDrawable != stuff->srcDrawable)
- {
- rc = dixLookupDrawable(&psrcDraw, stuff->srcDrawable, client, 0,
- DixReadAccess);
- if (rc != Success)
- return rc;
-
- if (pdstDraw->pScreen != psrcDraw->pScreen)
- {
- client->errorValue = stuff->dstDrawable;
- return BadMatch;
- }
- }
- else
- psrcDraw = pdstDraw;
-
- /* Check to see if stuff->bitPlane has exactly ONE good bit set */
- if(stuff->bitPlane == 0 || (stuff->bitPlane & (stuff->bitPlane - 1)) ||
- (stuff->bitPlane > (1L << (psrcDraw->depth - 1))))
- {
- client->errorValue = stuff->bitPlane;
- return BadValue;
- }
-
- pRgn = (*pGC->ops->CopyPlane)(psrcDraw, pdstDraw, pGC, stuff->srcX, stuff->srcY,
- stuff->width, stuff->height,
- stuff->dstX, stuff->dstY, stuff->bitPlane);
- if (pGC->graphicsExposures)
- {
- (*pdstDraw->pScreen->SendGraphicsExpose)
- (client, pRgn, stuff->dstDrawable, X_CopyPlane, 0);
- if (pRgn)
- RegionDestroy(pRgn);
- }
- return Success;
-}
-
-int
-ProcPolyPoint(ClientPtr client)
-{
- int npoint;
- GC *pGC;
- DrawablePtr pDraw;
- REQUEST(xPolyPointReq);
-
- REQUEST_AT_LEAST_SIZE(xPolyPointReq);
- if ((stuff->coordMode != CoordModeOrigin) &&
- (stuff->coordMode != CoordModePrevious))
- {
- client->errorValue = stuff->coordMode;
- return BadValue;
- }
- VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
- npoint = bytes_to_int32((client->req_len << 2) - sizeof(xPolyPointReq));
- if (npoint)
- (*pGC->ops->PolyPoint)(pDraw, pGC, stuff->coordMode, npoint,
- (xPoint *) &stuff[1]);
- return Success;
-}
-
-int
-ProcPolyLine(ClientPtr client)
-{
- int npoint;
- GC *pGC;
- DrawablePtr pDraw;
- REQUEST(xPolyLineReq);
-
- REQUEST_AT_LEAST_SIZE(xPolyLineReq);
- if ((stuff->coordMode != CoordModeOrigin) &&
- (stuff->coordMode != CoordModePrevious))
- {
- client->errorValue = stuff->coordMode;
- return BadValue;
- }
- VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
- npoint = bytes_to_int32((client->req_len << 2) - sizeof(xPolyLineReq));
- if (npoint > 1)
- (*pGC->ops->Polylines)(pDraw, pGC, stuff->coordMode, npoint,
- (DDXPointPtr) &stuff[1]);
- return Success;
-}
-
-int
-ProcPolySegment(ClientPtr client)
-{
- int nsegs;
- GC *pGC;
- DrawablePtr pDraw;
- REQUEST(xPolySegmentReq);
-
- REQUEST_AT_LEAST_SIZE(xPolySegmentReq);
- VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
- nsegs = (client->req_len << 2) - sizeof(xPolySegmentReq);
- if (nsegs & 4)
- return BadLength;
- nsegs >>= 3;
- if (nsegs)
- (*pGC->ops->PolySegment)(pDraw, pGC, nsegs, (xSegment *) &stuff[1]);
- return Success;
-}
-
-int
-ProcPolyRectangle (ClientPtr client)
-{
- int nrects;
- GC *pGC;
- DrawablePtr pDraw;
- REQUEST(xPolyRectangleReq);
-
- REQUEST_AT_LEAST_SIZE(xPolyRectangleReq);
- VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
- nrects = (client->req_len << 2) - sizeof(xPolyRectangleReq);
- if (nrects & 4)
- return BadLength;
- nrects >>= 3;
- if (nrects)
- (*pGC->ops->PolyRectangle)(pDraw, pGC,
- nrects, (xRectangle *) &stuff[1]);
- return Success;
-}
-
-int
-ProcPolyArc(ClientPtr client)
-{
- int narcs;
- GC *pGC;
- DrawablePtr pDraw;
- REQUEST(xPolyArcReq);
-
- REQUEST_AT_LEAST_SIZE(xPolyArcReq);
- VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
- narcs = (client->req_len << 2) - sizeof(xPolyArcReq);
- if (narcs % sizeof(xArc))
- return BadLength;
- narcs /= sizeof(xArc);
- if (narcs)
- (*pGC->ops->PolyArc)(pDraw, pGC, narcs, (xArc *) &stuff[1]);
- return Success;
-}
-
-int
-ProcFillPoly(ClientPtr client)
-{
- int things;
- GC *pGC;
- DrawablePtr pDraw;
- REQUEST(xFillPolyReq);
-
- REQUEST_AT_LEAST_SIZE(xFillPolyReq);
- if ((stuff->shape != Complex) && (stuff->shape != Nonconvex) &&
- (stuff->shape != Convex))
- {
- client->errorValue = stuff->shape;
- return BadValue;
- }
- if ((stuff->coordMode != CoordModeOrigin) &&
- (stuff->coordMode != CoordModePrevious))
- {
- client->errorValue = stuff->coordMode;
- return BadValue;
- }
-
- VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
- things = bytes_to_int32((client->req_len << 2) - sizeof(xFillPolyReq));
- if (things)
- (*pGC->ops->FillPolygon) (pDraw, pGC, stuff->shape,
- stuff->coordMode, things,
- (DDXPointPtr) &stuff[1]);
- return Success;
-}
-
-int
-ProcPolyFillRectangle(ClientPtr client)
-{
- int things;
- GC *pGC;
- DrawablePtr pDraw;
- REQUEST(xPolyFillRectangleReq);
-
- REQUEST_AT_LEAST_SIZE(xPolyFillRectangleReq);
- VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
- things = (client->req_len << 2) - sizeof(xPolyFillRectangleReq);
- if (things & 4)
- return BadLength;
- things >>= 3;
-
- if (things)
- (*pGC->ops->PolyFillRect) (pDraw, pGC, things,
- (xRectangle *) &stuff[1]);
- return Success;
-}
-
-int
-ProcPolyFillArc(ClientPtr client)
-{
- int narcs;
- GC *pGC;
- DrawablePtr pDraw;
- REQUEST(xPolyFillArcReq);
-
- REQUEST_AT_LEAST_SIZE(xPolyFillArcReq);
- VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
- narcs = (client->req_len << 2) - sizeof(xPolyFillArcReq);
- if (narcs % sizeof(xArc))
- return BadLength;
- narcs /= sizeof(xArc);
- if (narcs)
- (*pGC->ops->PolyFillArc) (pDraw, pGC, narcs, (xArc *) &stuff[1]);
- return Success;
-}
-
-#ifdef MATCH_CLIENT_ENDIAN
-
-int
-ServerOrder (void)
-{
- int whichbyte = 1;
-
- if (*((char *) &whichbyte))
- return LSBFirst;
- return MSBFirst;
-}
-
-#define ClientOrder(client) ((client)->swapped ? !ServerOrder() : ServerOrder())
-
-void
-ReformatImage (char *base, int nbytes, int bpp, int order)
-{
- switch (bpp) {
- case 1: /* yuck */
- if (BITMAP_BIT_ORDER != order)
- BitOrderInvert ((unsigned char *) base, nbytes);
-#if IMAGE_BYTE_ORDER != BITMAP_BIT_ORDER && BITMAP_SCANLINE_UNIT != 8
- ReformatImage (base, nbytes, BITMAP_SCANLINE_UNIT, order);
-#endif
- break;
- case 4:
- break; /* yuck */
- case 8:
- break;
- case 16:
- if (IMAGE_BYTE_ORDER != order)
- TwoByteSwap ((unsigned char *) base, nbytes);
- break;
- case 32:
- if (IMAGE_BYTE_ORDER != order)
- FourByteSwap ((unsigned char *) base, nbytes);
- break;
- }
-}
-#else
-#define ReformatImage(b,n,bpp,o)
-#endif
-
-/* 64-bit server notes: the protocol restricts padding of images to
- * 8-, 16-, or 32-bits. We would like to have 64-bits for the server
- * to use internally. Removes need for internal alignment checking.
- * All of the PutImage functions could be changed individually, but
- * as currently written, they call other routines which require things
- * to be 64-bit padded on scanlines, so we changed things here.
- * If an image would be padded differently for 64- versus 32-, then
- * copy each scanline to a 64-bit padded scanline.
- * Also, we need to make sure that the image is aligned on a 64-bit
- * boundary, even if the scanlines are padded to our satisfaction.
- */
-int
-ProcPutImage(ClientPtr client)
-{
- GC *pGC;
- DrawablePtr pDraw;
- long length; /* length of scanline server padded */
- long lengthProto; /* length of scanline protocol padded */
- char *tmpImage;
- REQUEST(xPutImageReq);
-
- REQUEST_AT_LEAST_SIZE(xPutImageReq);
- VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
- if (stuff->format == XYBitmap)
- {
- if ((stuff->depth != 1) ||
- (stuff->leftPad >= (unsigned int)screenInfo.bitmapScanlinePad))
- return BadMatch;
- length = BitmapBytePad(stuff->width + stuff->leftPad);
- }
- else if (stuff->format == XYPixmap)
- {
- if ((pDraw->depth != stuff->depth) ||
- (stuff->leftPad >= (unsigned int)screenInfo.bitmapScanlinePad))
- return BadMatch;
- length = BitmapBytePad(stuff->width + stuff->leftPad);
- length *= stuff->depth;
- }
- else if (stuff->format == ZPixmap)
- {
- if ((pDraw->depth != stuff->depth) || (stuff->leftPad != 0))
- return BadMatch;
- length = PixmapBytePad(stuff->width, stuff->depth);
- }
- else
- {
- client->errorValue = stuff->format;
- return BadValue;
- }
-
- tmpImage = (char *)&stuff[1];
- lengthProto = length;
-
- if ((bytes_to_int32(lengthProto * stuff->height) +
- bytes_to_int32(sizeof(xPutImageReq))) != client->req_len)
- return BadLength;
-
- ReformatImage (tmpImage, lengthProto * stuff->height,
- stuff->format == ZPixmap ? BitsPerPixel (stuff->depth) : 1,
- ClientOrder(client));
-
- (*pGC->ops->PutImage) (pDraw, pGC, stuff->depth, stuff->dstX, stuff->dstY,
- stuff->width, stuff->height,
- stuff->leftPad, stuff->format, tmpImage);
-
- return Success;
-}
-
-static int
-DoGetImage(ClientPtr client, int format, Drawable drawable,
- int x, int y, int width, int height,
- Mask planemask, xGetImageReply **im_return)
-{
- DrawablePtr pDraw, pBoundingDraw;
- int nlines, linesPerBuf, rc;
- int linesDone;
- /* coordinates relative to the bounding drawable */
- int relx, rely;
- long widthBytesLine, length;
- Mask plane = 0;
- char *pBuf;
- xGetImageReply xgi;
- RegionPtr pVisibleRegion = NULL;
-
- if ((format != XYPixmap) && (format != ZPixmap))
- {
- client->errorValue = format;
- return BadValue;
- }
- rc = dixLookupDrawable(&pDraw, drawable, client, 0, DixReadAccess);
- if (rc != Success)
- return rc;
-
- memset(&xgi, 0, sizeof(xGetImageReply));
-
- relx = x;
- rely = y;
-
- if(pDraw->type == DRAWABLE_WINDOW)
- {
- WindowPtr pWin = (WindowPtr)pDraw;
-
- /* "If the drawable is a window, the window must be viewable ... or a
- * BadMatch error results" */
- if (!pWin->viewable)
- return BadMatch;
-
- relx += pDraw->x;
- rely += pDraw->y;
-
- if (pDraw->pScreen->GetWindowPixmap) {
- PixmapPtr pPix = (*pDraw->pScreen->GetWindowPixmap) (pWin);
-
- pBoundingDraw = &pPix->drawable;
-#ifdef COMPOSITE
- relx -= pPix->screen_x;
- rely -= pPix->screen_y;
-#endif
- }
- else
- {
- pBoundingDraw = (DrawablePtr)pDraw->pScreen->root;
- }
-
- xgi.visual = wVisual (pWin);
- }
- else
- {
- pBoundingDraw = pDraw;
- xgi.visual = None;
- }
-
- /* "If the drawable is a pixmap, the given rectangle must be wholly
- * contained within the pixmap, or a BadMatch error results. If the
- * drawable is a window [...] it must be the case that if there were no
- * inferiors or overlapping windows, the specified rectangle of the window
- * would be fully visible on the screen and wholly contained within the
- * outside edges of the window, or a BadMatch error results."
- *
- * We relax the window case slightly to mean that the rectangle must exist
- * within the bounds of the window's backing pixmap. In particular, this
- * means that a GetImage request may succeed or fail with BadMatch depending
- * on whether any of its ancestor windows are redirected. */
- if(relx < 0 || relx + width > (int)pBoundingDraw->width ||
- rely < 0 || rely + height > (int)pBoundingDraw->height)
- return BadMatch;
-
- xgi.type = X_Reply;
- xgi.sequenceNumber = client->sequence;
- xgi.depth = pDraw->depth;
- if(format == ZPixmap)
- {
- widthBytesLine = PixmapBytePad(width, pDraw->depth);
- length = widthBytesLine * height;
-
- }
- else
- {
- widthBytesLine = BitmapBytePad(width);
- plane = ((Mask)1) << (pDraw->depth - 1);
- /* only planes asked for */
- length = widthBytesLine * height *
- Ones(planemask & (plane | (plane - 1)));
-
- }
-
- xgi.length = length;
-
- if (im_return) {
- pBuf = calloc(1, sz_xGetImageReply + length);
- if (!pBuf)
- return BadAlloc;
- if (widthBytesLine == 0)
- linesPerBuf = 0;
- else
- linesPerBuf = height;
- *im_return = (xGetImageReply *)pBuf;
- *(xGetImageReply *)pBuf = xgi;
- pBuf += sz_xGetImageReply;
- } else {
- xgi.length = bytes_to_int32(xgi.length);
- if (widthBytesLine == 0 || height == 0)
- linesPerBuf = 0;
- else if (widthBytesLine >= IMAGE_BUFSIZE)
- linesPerBuf = 1;
- else
- {
- linesPerBuf = IMAGE_BUFSIZE / widthBytesLine;
- if (linesPerBuf > height)
- linesPerBuf = height;
- }
- length = linesPerBuf * widthBytesLine;
- if (linesPerBuf < height)
- {
- /* we have to make sure intermediate buffers don't need padding */
- while ((linesPerBuf > 1) &&
- (length & ((1L << LOG2_BYTES_PER_SCANLINE_PAD)-1)))
- {
- linesPerBuf--;
- length -= widthBytesLine;
- }
- while (length & ((1L << LOG2_BYTES_PER_SCANLINE_PAD)-1))
- {
- linesPerBuf++;
- length += widthBytesLine;
- }
- }
- if(!(pBuf = calloc(1, length)))
- return BadAlloc;
- WriteReplyToClient(client, sizeof (xGetImageReply), &xgi);
- }
-
- if (pDraw->type == DRAWABLE_WINDOW)
- {
- pVisibleRegion = NotClippedByChildren((WindowPtr)pDraw);
- if (pVisibleRegion)
- {
- RegionTranslate(pVisibleRegion, -pDraw->x, -pDraw->y);
- }
- }
-
- if (linesPerBuf == 0)
- {
- /* nothing to do */
- }
- else if (format == ZPixmap)
- {
- linesDone = 0;
- while (height - linesDone > 0)
- {
- nlines = min(linesPerBuf, height - linesDone);
- (*pDraw->pScreen->GetImage) (pDraw,
- x,
- y + linesDone,
- width,
- nlines,
- format,
- planemask,
- (pointer) pBuf);
- if (pVisibleRegion)
- XaceCensorImage(client, pVisibleRegion, widthBytesLine,
- pDraw, x, y + linesDone, width,
- nlines, format, pBuf);
-
- /* Note that this is NOT a call to WriteSwappedDataToClient,
- as we do NOT byte swap */
- if (!im_return)
- {
- ReformatImage (pBuf, (int)(nlines * widthBytesLine),
- BitsPerPixel (pDraw->depth),
- ClientOrder(client));
-
-/* Don't split me, gcc pukes when you do */
- (void)WriteToClient(client,
- (int)(nlines * widthBytesLine),
- pBuf);
- }
- linesDone += nlines;
- }
- }
- else /* XYPixmap */
- {
- for (; plane; plane >>= 1)
- {
- if (planemask & plane)
- {
- linesDone = 0;
- while (height - linesDone > 0)
- {
- nlines = min(linesPerBuf, height - linesDone);
- (*pDraw->pScreen->GetImage) (pDraw,
- x,
- y + linesDone,
- width,
- nlines,
- format,
- plane,
- (pointer)pBuf);
- if (pVisibleRegion)
- XaceCensorImage(client, pVisibleRegion,
- widthBytesLine,
- pDraw, x, y + linesDone, width,
- nlines, format, pBuf);
-
- /* Note: NOT a call to WriteSwappedDataToClient,
- as we do NOT byte swap */
- if (im_return) {
- pBuf += nlines * widthBytesLine;
- } else {
- ReformatImage (pBuf,
- (int)(nlines * widthBytesLine),
- 1,
- ClientOrder (client));
-
-/* Don't split me, gcc pukes when you do */
- (void)WriteToClient(client,
- (int)(nlines * widthBytesLine),
- pBuf);
- }
- linesDone += nlines;
- }
- }
- }
- }
- if (pVisibleRegion)
- RegionDestroy(pVisibleRegion);
- if (!im_return)
- free(pBuf);
- return Success;
-}
-
-int
-ProcGetImage(ClientPtr client)
-{
- REQUEST(xGetImageReq);
-
- REQUEST_SIZE_MATCH(xGetImageReq);
-
- return DoGetImage(client, stuff->format, stuff->drawable,
- stuff->x, stuff->y,
- (int)stuff->width, (int)stuff->height,
- stuff->planeMask, (xGetImageReply **)NULL);
-}
-
-int
-ProcPolyText(ClientPtr client)
-{
- int err;
- REQUEST(xPolyTextReq);
- DrawablePtr pDraw;
- GC *pGC;
-
- REQUEST_AT_LEAST_SIZE(xPolyTextReq);
- VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
-
- err = PolyText(client,
- pDraw,
- pGC,
- (unsigned char *)&stuff[1],
- ((unsigned char *) stuff) + (client->req_len << 2),
- stuff->x,
- stuff->y,
- stuff->reqType,
- stuff->drawable);
-
- if (err == Success)
- {
- return Success;
- }
- else
- return err;
-}
-
-int
-ProcImageText8(ClientPtr client)
-{
- int err;
- DrawablePtr pDraw;
- GC *pGC;
-
- REQUEST(xImageTextReq);
-
- REQUEST_FIXED_SIZE(xImageTextReq, stuff->nChars);
- VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
-
- err = ImageText(client,
- pDraw,
- pGC,
- stuff->nChars,
- (unsigned char *)&stuff[1],
- stuff->x,
- stuff->y,
- stuff->reqType,
- stuff->drawable);
-
- if (err == Success)
- {
- return Success;
- }
- else
- return err;
-}
-
-int
-ProcImageText16(ClientPtr client)
-{
- int err;
- DrawablePtr pDraw;
- GC *pGC;
-
- REQUEST(xImageTextReq);
-
- REQUEST_FIXED_SIZE(xImageTextReq, stuff->nChars << 1);
- VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
-
- err = ImageText(client,
- pDraw,
- pGC,
- stuff->nChars,
- (unsigned char *)&stuff[1],
- stuff->x,
- stuff->y,
- stuff->reqType,
- stuff->drawable);
-
- if (err == Success)
- {
- return Success;
- }
- else
- return err;
-}
-
-
-int
-ProcCreateColormap(ClientPtr client)
-{
- VisualPtr pVisual;
- ColormapPtr pmap;
- Colormap mid;
- WindowPtr pWin;
- ScreenPtr pScreen;
- REQUEST(xCreateColormapReq);
- int i, result;
-
- REQUEST_SIZE_MATCH(xCreateColormapReq);
-
- if ((stuff->alloc != AllocNone) && (stuff->alloc != AllocAll))
- {
- client->errorValue = stuff->alloc;
- return BadValue;
- }
- mid = stuff->mid;
- LEGAL_NEW_RESOURCE(mid, client);
- result = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
- if (result != Success)
- return result;
-
- pScreen = pWin->drawable.pScreen;
- for (i = 0, pVisual = pScreen->visuals;
- i < pScreen->numVisuals;
- i++, pVisual++)
- {
- if (pVisual->vid != stuff->visual)
- continue;
- return CreateColormap(mid, pScreen, pVisual, &pmap,
- (int)stuff->alloc, client->index);
- }
- client->errorValue = stuff->visual;
- return BadMatch;
-}
-
-int
-ProcFreeColormap(ClientPtr client)
-{
- ColormapPtr pmap;
- int rc;
- REQUEST(xResourceReq);
-
- REQUEST_SIZE_MATCH(xResourceReq);
- rc = dixLookupResourceByType((pointer *)&pmap, stuff->id, RT_COLORMAP, client,
- DixDestroyAccess);
- if (rc == Success)
- {
- /* Freeing a default colormap is a no-op */
- if (!(pmap->flags & IsDefault))
- FreeResource(stuff->id, RT_NONE);
- return Success;
- }
- else
- {
- client->errorValue = stuff->id;
- return rc;
- }
-}
-
-
-int
-ProcCopyColormapAndFree(ClientPtr client)
-{
- Colormap mid;
- ColormapPtr pSrcMap;
- REQUEST(xCopyColormapAndFreeReq);
- int rc;
-
- REQUEST_SIZE_MATCH(xCopyColormapAndFreeReq);
- mid = stuff->mid;
- LEGAL_NEW_RESOURCE(mid, client);
- rc = dixLookupResourceByType((pointer *)&pSrcMap, stuff->srcCmap, RT_COLORMAP,
- client, DixReadAccess|DixRemoveAccess);
- if (rc == Success)
- return CopyColormapAndFree(mid, pSrcMap, client->index);
- client->errorValue = stuff->srcCmap;
- return rc;
-}
-
-int
-ProcInstallColormap(ClientPtr client)
-{
- ColormapPtr pcmp;
- int rc;
- REQUEST(xResourceReq);
- REQUEST_SIZE_MATCH(xResourceReq);
-
- rc = dixLookupResourceByType((pointer *)&pcmp, stuff->id, RT_COLORMAP, client,
- DixInstallAccess);
- if (rc != Success)
- goto out;
-
- rc = XaceHook(XACE_SCREEN_ACCESS, client, pcmp->pScreen, DixSetAttrAccess);
- if (rc != Success) {
- if (rc == BadValue)
- rc = BadColor;
- goto out;
- }
-
- (*(pcmp->pScreen->InstallColormap)) (pcmp);
- return Success;
-
-out:
- client->errorValue = stuff->id;
- return rc;
-}
-
-int
-ProcUninstallColormap(ClientPtr client)
-{
- ColormapPtr pcmp;
- int rc;
- REQUEST(xResourceReq);
- REQUEST_SIZE_MATCH(xResourceReq);
-
- rc = dixLookupResourceByType((pointer *)&pcmp, stuff->id, RT_COLORMAP, client,
- DixUninstallAccess);
- if (rc != Success)
- goto out;
-
- rc = XaceHook(XACE_SCREEN_ACCESS, client, pcmp->pScreen, DixSetAttrAccess);
- if (rc != Success) {
- if (rc == BadValue)
- rc = BadColor;
- goto out;
- }
-
- if(pcmp->mid != pcmp->pScreen->defColormap)
- (*(pcmp->pScreen->UninstallColormap)) (pcmp);
- return Success;
-
-out:
- client->errorValue = stuff->id;
- return rc;
-}
-
-int
-ProcListInstalledColormaps(ClientPtr client)
-{
- xListInstalledColormapsReply *preply;
- int nummaps, rc;
- WindowPtr pWin;
- REQUEST(xResourceReq);
- REQUEST_SIZE_MATCH(xResourceReq);
-
- rc = dixLookupWindow(&pWin, stuff->id, client, DixGetAttrAccess);
- if (rc != Success)
- return rc;
-
- rc = XaceHook(XACE_SCREEN_ACCESS, client, pWin->drawable.pScreen,
- DixGetAttrAccess);
- if (rc != Success)
- return rc;
-
- preply = malloc(sizeof(xListInstalledColormapsReply) +
- pWin->drawable.pScreen->maxInstalledCmaps *
- sizeof(Colormap));
- if(!preply)
- return BadAlloc;
-
- preply->type = X_Reply;
- preply->sequenceNumber = client->sequence;
- nummaps = (*pWin->drawable.pScreen->ListInstalledColormaps)
- (pWin->drawable.pScreen, (Colormap *)&preply[1]);
- preply->nColormaps = nummaps;
- preply->length = nummaps;
- WriteReplyToClient(client, sizeof (xListInstalledColormapsReply), preply);
- client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write;
- WriteSwappedDataToClient(client, nummaps * sizeof(Colormap), &preply[1]);
- free(preply);
- return Success;
-}
-
-int
-ProcAllocColor (ClientPtr client)
-{
- ColormapPtr pmap;
- int rc;
- xAllocColorReply acr;
- REQUEST(xAllocColorReq);
-
- REQUEST_SIZE_MATCH(xAllocColorReq);
- rc = dixLookupResourceByType((pointer *)&pmap, stuff->cmap, RT_COLORMAP, client,
- DixAddAccess);
- if (rc == Success)
- {
- acr.type = X_Reply;
- acr.length = 0;
- acr.sequenceNumber = client->sequence;
- acr.red = stuff->red;
- acr.green = stuff->green;
- acr.blue = stuff->blue;
- acr.pixel = 0;
- if( (rc = AllocColor(pmap, &acr.red, &acr.green, &acr.blue,
- &acr.pixel, client->index)) )
- return rc;
-#ifdef PANORAMIX
- if (noPanoramiXExtension || !pmap->pScreen->myNum)
-#endif
- WriteReplyToClient(client, sizeof(xAllocColorReply), &acr);
- return Success;
-
- }
- else
- {
- client->errorValue = stuff->cmap;
- return rc;
- }
-}
-
-int
-ProcAllocNamedColor (ClientPtr client)
-{
- ColormapPtr pcmp;
- int rc;
- REQUEST(xAllocNamedColorReq);
-
- REQUEST_FIXED_SIZE(xAllocNamedColorReq, stuff->nbytes);
- rc = dixLookupResourceByType((pointer *)&pcmp, stuff->cmap, RT_COLORMAP, client,
- DixAddAccess);
- if (rc == Success)
- {
- xAllocNamedColorReply ancr;
-
- ancr.type = X_Reply;
- ancr.length = 0;
- ancr.sequenceNumber = client->sequence;
-
- if(OsLookupColor(pcmp->pScreen->myNum, (char *)&stuff[1], stuff->nbytes,
- &ancr.exactRed, &ancr.exactGreen, &ancr.exactBlue))
- {
- ancr.screenRed = ancr.exactRed;
- ancr.screenGreen = ancr.exactGreen;
- ancr.screenBlue = ancr.exactBlue;
- ancr.pixel = 0;
- if( (rc = AllocColor(pcmp,
- &ancr.screenRed, &ancr.screenGreen, &ancr.screenBlue,
- &ancr.pixel, client->index)) )
- return rc;
-#ifdef PANORAMIX
- if (noPanoramiXExtension || !pcmp->pScreen->myNum)
-#endif
- WriteReplyToClient(client, sizeof (xAllocNamedColorReply), &ancr);
- return Success;
- }
- else
- return BadName;
-
- }
- else
- {
- client->errorValue = stuff->cmap;
- return rc;
- }
-}
-
-int
-ProcAllocColorCells (ClientPtr client)
-{
- ColormapPtr pcmp;
- int rc;
- REQUEST(xAllocColorCellsReq);
-
- REQUEST_SIZE_MATCH(xAllocColorCellsReq);
- rc = dixLookupResourceByType((pointer *)&pcmp, stuff->cmap, RT_COLORMAP, client,
- DixAddAccess);
- if (rc == Success)
- {
- xAllocColorCellsReply accr;
- int npixels, nmasks;
- long length;
- Pixel *ppixels, *pmasks;
-
- npixels = stuff->colors;
- if (!npixels)
- {
- client->errorValue = npixels;
- return BadValue;
- }
- if (stuff->contiguous != xTrue && stuff->contiguous != xFalse)
- {
- client->errorValue = stuff->contiguous;
- return BadValue;
- }
- nmasks = stuff->planes;
- length = ((long)npixels + (long)nmasks) * sizeof(Pixel);
- ppixels = malloc(length);
- if(!ppixels)
- return BadAlloc;
- pmasks = ppixels + npixels;
-
- if( (rc = AllocColorCells(client->index, pcmp, npixels, nmasks,
- (Bool)stuff->contiguous, ppixels, pmasks)) )
- {
- free(ppixels);
- return rc;
- }
-#ifdef PANORAMIX
- if (noPanoramiXExtension || !pcmp->pScreen->myNum)
-#endif
- {
- accr.type = X_Reply;
- accr.length = bytes_to_int32(length);
- accr.sequenceNumber = client->sequence;
- accr.nPixels = npixels;
- accr.nMasks = nmasks;
- WriteReplyToClient(client, sizeof (xAllocColorCellsReply), &accr);
- client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write;
- WriteSwappedDataToClient(client, length, ppixels);
- }
- free(ppixels);
- return Success;
- }
- else
- {
- client->errorValue = stuff->cmap;
- return rc;
- }
-}
-
-int
-ProcAllocColorPlanes(ClientPtr client)
-{
- ColormapPtr pcmp;
- int rc;
- REQUEST(xAllocColorPlanesReq);
-
- REQUEST_SIZE_MATCH(xAllocColorPlanesReq);
- rc = dixLookupResourceByType((pointer *)&pcmp, stuff->cmap, RT_COLORMAP, client,
- DixAddAccess);
- if (rc == Success)
- {
- xAllocColorPlanesReply acpr;
- int npixels;
- long length;
- Pixel *ppixels;
-
- npixels = stuff->colors;
- if (!npixels)
- {
- client->errorValue = npixels;
- return BadValue;
- }
- if (stuff->contiguous != xTrue && stuff->contiguous != xFalse)
- {
- client->errorValue = stuff->contiguous;
- return BadValue;
- }
- acpr.type = X_Reply;
- acpr.sequenceNumber = client->sequence;
- acpr.nPixels = npixels;
- length = (long)npixels * sizeof(Pixel);
- ppixels = malloc(length);
- if(!ppixels)
- return BadAlloc;
- if( (rc = AllocColorPlanes(client->index, pcmp, npixels,
- (int)stuff->red, (int)stuff->green, (int)stuff->blue,
- (Bool)stuff->contiguous, ppixels,
- &acpr.redMask, &acpr.greenMask, &acpr.blueMask)) )
- {
- free(ppixels);
- return rc;
- }
- acpr.length = bytes_to_int32(length);
-#ifdef PANORAMIX
- if (noPanoramiXExtension || !pcmp->pScreen->myNum)
-#endif
- {
- WriteReplyToClient(client, sizeof(xAllocColorPlanesReply), &acpr);
- client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write;
- WriteSwappedDataToClient(client, length, ppixels);
- }
- free(ppixels);
- return Success;
- }
- else
- {
- client->errorValue = stuff->cmap;
- return rc;
- }
-}
-
-int
-ProcFreeColors(ClientPtr client)
-{
- ColormapPtr pcmp;
- int rc;
- REQUEST(xFreeColorsReq);
-
- REQUEST_AT_LEAST_SIZE(xFreeColorsReq);
- rc = dixLookupResourceByType((pointer *)&pcmp, stuff->cmap, RT_COLORMAP, client,
- DixRemoveAccess);
- if (rc == Success)
- {
- int count;
-
- if(pcmp->flags & AllAllocated)
- return BadAccess;
- count = bytes_to_int32((client->req_len << 2) - sizeof(xFreeColorsReq));
- return FreeColors(pcmp, client->index, count,
- (Pixel *)&stuff[1], (Pixel)stuff->planeMask);
- }
- else
- {
- client->errorValue = stuff->cmap;
- return rc;
- }
-}
-
-int
-ProcStoreColors (ClientPtr client)
-{
- ColormapPtr pcmp;
- int rc;
- REQUEST(xStoreColorsReq);
-
- REQUEST_AT_LEAST_SIZE(xStoreColorsReq);
- rc = dixLookupResourceByType((pointer *)&pcmp, stuff->cmap, RT_COLORMAP, client,
- DixWriteAccess);
- if (rc == Success)
- {
- int count;
-
- count = (client->req_len << 2) - sizeof(xStoreColorsReq);
- if (count % sizeof(xColorItem))
- return BadLength;
- count /= sizeof(xColorItem);
- return StoreColors(pcmp, count, (xColorItem *)&stuff[1], client);
- }
- else
- {
- client->errorValue = stuff->cmap;
- return rc;
- }
-}
-
-int
-ProcStoreNamedColor (ClientPtr client)
-{
- ColormapPtr pcmp;
- int rc;
- REQUEST(xStoreNamedColorReq);
-
- REQUEST_FIXED_SIZE(xStoreNamedColorReq, stuff->nbytes);
- rc = dixLookupResourceByType((pointer *)&pcmp, stuff->cmap, RT_COLORMAP, client,
- DixWriteAccess);
- if (rc == Success)
- {
- xColorItem def;
-
- if(OsLookupColor(pcmp->pScreen->myNum, (char *)&stuff[1],
- stuff->nbytes, &def.red, &def.green, &def.blue))
- {
- def.flags = stuff->flags;
- def.pixel = stuff->pixel;
- return StoreColors(pcmp, 1, &def, client);
- }
- return BadName;
- }
- else
- {
- client->errorValue = stuff->cmap;
- return rc;
- }
-}
-
-int
-ProcQueryColors(ClientPtr client)
-{
- ColormapPtr pcmp;
- int rc;
- REQUEST(xQueryColorsReq);
-
- REQUEST_AT_LEAST_SIZE(xQueryColorsReq);
- rc = dixLookupResourceByType((pointer *)&pcmp, stuff->cmap, RT_COLORMAP, client,
- DixReadAccess);
- if (rc == Success)
- {
- int count;
- xrgb *prgbs;
- xQueryColorsReply qcr;
-
- count = bytes_to_int32((client->req_len << 2) - sizeof(xQueryColorsReq));
- prgbs = calloc(1, count * sizeof(xrgb));
- if(!prgbs && count)
- return BadAlloc;
- if( (rc = QueryColors(pcmp, count, (Pixel *)&stuff[1], prgbs, client)) )
- {
- free(prgbs);
- return rc;
- }
- memset(&qcr, 0, sizeof(xQueryColorsReply));
- qcr.type = X_Reply;
- qcr.length = bytes_to_int32(count * sizeof(xrgb));
- qcr.sequenceNumber = client->sequence;
- qcr.nColors = count;
- WriteReplyToClient(client, sizeof(xQueryColorsReply), &qcr);
- if (count)
- {
- client->pSwapReplyFunc = (ReplySwapPtr) SQColorsExtend;
- WriteSwappedDataToClient(client, count * sizeof(xrgb), prgbs);
- }
- free(prgbs);
- return Success;
-
- }
- else
- {
- client->errorValue = stuff->cmap;
- return rc;
- }
-}
-
-int
-ProcLookupColor(ClientPtr client)
-{
- ColormapPtr pcmp;
- int rc;
- REQUEST(xLookupColorReq);
-
- REQUEST_FIXED_SIZE(xLookupColorReq, stuff->nbytes);
- rc = dixLookupResourceByType((pointer *)&pcmp, stuff->cmap, RT_COLORMAP, client,
- DixReadAccess);
- if (rc == Success)
- {
- xLookupColorReply lcr;
-
- if(OsLookupColor(pcmp->pScreen->myNum, (char *)&stuff[1], stuff->nbytes,
- &lcr.exactRed, &lcr.exactGreen, &lcr.exactBlue))
- {
- lcr.type = X_Reply;
- lcr.length = 0;
- lcr.sequenceNumber = client->sequence;
- lcr.screenRed = lcr.exactRed;
- lcr.screenGreen = lcr.exactGreen;
- lcr.screenBlue = lcr.exactBlue;
- (*pcmp->pScreen->ResolveColor)(&lcr.screenRed,
- &lcr.screenGreen,
- &lcr.screenBlue,
- pcmp->pVisual);
- WriteReplyToClient(client, sizeof(xLookupColorReply), &lcr);
- return Success;
- }
- return BadName;
- }
- else
- {
- client->errorValue = stuff->cmap;
- return rc;
- }
-}
-
-int
-ProcCreateCursor (ClientPtr client)
-{
- CursorPtr pCursor;
- PixmapPtr src;
- PixmapPtr msk;
- unsigned char * srcbits;
- unsigned char * mskbits;
- unsigned short width, height;
- long n;
- CursorMetricRec cm;
- int rc;
-
- REQUEST(xCreateCursorReq);
-
- REQUEST_SIZE_MATCH(xCreateCursorReq);
- LEGAL_NEW_RESOURCE(stuff->cid, client);
-
- rc = dixLookupResourceByType((pointer *)&src, stuff->source, RT_PIXMAP, client,
- DixReadAccess);
- if (rc != Success) {
- client->errorValue = stuff->source;
- return rc;
- }
-
- rc = dixLookupResourceByType((pointer *)&msk, stuff->mask, RT_PIXMAP, client,
- DixReadAccess);
- if (rc != Success)
- {
- if (stuff->mask != None)
- {
- client->errorValue = stuff->mask;
- return rc;
- }
- }
- else if ( src->drawable.width != msk->drawable.width
- || src->drawable.height != msk->drawable.height
- || src->drawable.depth != 1
- || msk->drawable.depth != 1)
- return BadMatch;
-
- width = src->drawable.width;
- height = src->drawable.height;
-
- if ( stuff->x > width
- || stuff->y > height )
- return BadMatch;
-
- n = BitmapBytePad(width)*height;
- srcbits = calloc(1, n);
- if (!srcbits)
- return BadAlloc;
- mskbits = malloc(n);
- if (!mskbits)
- {
- free(srcbits);
- return BadAlloc;
- }
-
- (* src->drawable.pScreen->GetImage)( (DrawablePtr)src, 0, 0, width, height,
- XYPixmap, 1, (pointer)srcbits);
- if ( msk == (PixmapPtr)NULL)
- {
- unsigned char *bits = mskbits;
- while (--n >= 0)
- *bits++ = ~0;
- }
- else
- {
- /* zeroing the (pad) bits helps some ddx cursor handling */
- memset((char *)mskbits, 0, n);
- (* msk->drawable.pScreen->GetImage)( (DrawablePtr)msk, 0, 0, width,
- height, XYPixmap, 1, (pointer)mskbits);
- }
- cm.width = width;
- cm.height = height;
- cm.xhot = stuff->x;
- cm.yhot = stuff->y;
- rc = AllocARGBCursor(srcbits, mskbits, NULL, &cm,
- stuff->foreRed, stuff->foreGreen, stuff->foreBlue,
- stuff->backRed, stuff->backGreen, stuff->backBlue,
- &pCursor, client, stuff->cid);
-
- if (rc != Success)
- return rc;
- if (!AddResource(stuff->cid, RT_CURSOR, (pointer)pCursor))
- return BadAlloc;
-
- return Success;
-}
-
-int
-ProcCreateGlyphCursor (ClientPtr client)
-{
- CursorPtr pCursor;
- int res;
-
- REQUEST(xCreateGlyphCursorReq);
-
- REQUEST_SIZE_MATCH(xCreateGlyphCursorReq);
- LEGAL_NEW_RESOURCE(stuff->cid, client);
-
- res = AllocGlyphCursor(stuff->source, stuff->sourceChar,
- stuff->mask, stuff->maskChar,
- stuff->foreRed, stuff->foreGreen, stuff->foreBlue,
- stuff->backRed, stuff->backGreen, stuff->backBlue,
- &pCursor, client, stuff->cid);
- if (res != Success)
- return res;
- if (AddResource(stuff->cid, RT_CURSOR, (pointer)pCursor))
- return Success;
- return BadAlloc;
-}
-
-
-int
-ProcFreeCursor (ClientPtr client)
-{
- CursorPtr pCursor;
- int rc;
- REQUEST(xResourceReq);
-
- REQUEST_SIZE_MATCH(xResourceReq);
- rc = dixLookupResourceByType((pointer *)&pCursor, stuff->id, RT_CURSOR, client,
- DixDestroyAccess);
- if (rc == Success)
- {
- FreeResource(stuff->id, RT_NONE);
- return Success;
- }
- else
- {
- client->errorValue = stuff->id;
- return rc;
- }
-}
-
-int
-ProcQueryBestSize (ClientPtr client)
-{
- xQueryBestSizeReply reply;
- DrawablePtr pDraw;
- ScreenPtr pScreen;
- int rc;
- REQUEST(xQueryBestSizeReq);
- REQUEST_SIZE_MATCH(xQueryBestSizeReq);
-
- if ((stuff->class != CursorShape) &&
- (stuff->class != TileShape) &&
- (stuff->class != StippleShape))
- {
- client->errorValue = stuff->class;
- return BadValue;
- }
-
- rc = dixLookupDrawable(&pDraw, stuff->drawable, client, M_ANY,
- DixGetAttrAccess);
- if (rc != Success)
- return rc;
- if (stuff->class != CursorShape && pDraw->type == UNDRAWABLE_WINDOW)
- return BadMatch;
- pScreen = pDraw->pScreen;
- rc = XaceHook(XACE_SCREEN_ACCESS, client, pScreen, DixGetAttrAccess);
- if (rc != Success)
- return rc;
- (* pScreen->QueryBestSize)(stuff->class, &stuff->width,
- &stuff->height, pScreen);
- memset(&reply, 0, sizeof(xQueryBestSizeReply));
- reply.type = X_Reply;
- reply.length = 0;
- reply.sequenceNumber = client->sequence;
- reply.width = stuff->width;
- reply.height = stuff->height;
- WriteReplyToClient(client, sizeof(xQueryBestSizeReply), &reply);
- return Success;
-}
-
-
-int
-ProcSetScreenSaver (ClientPtr client)
-{
- int rc, i, blankingOption, exposureOption;
- REQUEST(xSetScreenSaverReq);
- REQUEST_SIZE_MATCH(xSetScreenSaverReq);
-
- for (i = 0; i < screenInfo.numScreens; i++) {
- rc = XaceHook(XACE_SCREENSAVER_ACCESS, client, screenInfo.screens[i],
- DixSetAttrAccess);
- if (rc != Success)
- return rc;
- }
-
- blankingOption = stuff->preferBlank;
- if ((blankingOption != DontPreferBlanking) &&
- (blankingOption != PreferBlanking) &&
- (blankingOption != DefaultBlanking))
- {
- client->errorValue = blankingOption;
- return BadValue;
- }
- exposureOption = stuff->allowExpose;
- if ((exposureOption != DontAllowExposures) &&
- (exposureOption != AllowExposures) &&
- (exposureOption != DefaultExposures))
- {
- client->errorValue = exposureOption;
- return BadValue;
- }
- if (stuff->timeout < -1)
- {
- client->errorValue = stuff->timeout;
- return BadValue;
- }
- if (stuff->interval < -1)
- {
- client->errorValue = stuff->interval;
- return BadValue;
- }
-
- if (blankingOption == DefaultBlanking)
- ScreenSaverBlanking = defaultScreenSaverBlanking;
- else
- ScreenSaverBlanking = blankingOption;
- if (exposureOption == DefaultExposures)
- ScreenSaverAllowExposures = defaultScreenSaverAllowExposures;
- else
- ScreenSaverAllowExposures = exposureOption;
-
- if (stuff->timeout >= 0)
- ScreenSaverTime = stuff->timeout * MILLI_PER_SECOND;
- else
- ScreenSaverTime = defaultScreenSaverTime;
- if (stuff->interval >= 0)
- ScreenSaverInterval = stuff->interval * MILLI_PER_SECOND;
- else
- ScreenSaverInterval = defaultScreenSaverInterval;
-
- SetScreenSaverTimer();
- return Success;
-}
-
-int
-ProcGetScreenSaver(ClientPtr client)
-{
- xGetScreenSaverReply rep;
- int rc, i;
- REQUEST_SIZE_MATCH(xReq);
-
- for (i = 0; i < screenInfo.numScreens; i++) {
- rc = XaceHook(XACE_SCREENSAVER_ACCESS, client, screenInfo.screens[i],
- DixGetAttrAccess);
- if (rc != Success)
- return rc;
- }
-
- rep.type = X_Reply;
- rep.length = 0;
- rep.sequenceNumber = client->sequence;
- rep.timeout = ScreenSaverTime / MILLI_PER_SECOND;
- rep.interval = ScreenSaverInterval / MILLI_PER_SECOND;
- rep.preferBlanking = ScreenSaverBlanking;
- rep.allowExposures = ScreenSaverAllowExposures;
- WriteReplyToClient(client, sizeof(xGetScreenSaverReply), &rep);
- return Success;
-}
-
-int
-ProcChangeHosts(ClientPtr client)
-{
- REQUEST(xChangeHostsReq);
-
- REQUEST_FIXED_SIZE(xChangeHostsReq, stuff->hostLength);
-
- if(stuff->mode == HostInsert)
- return AddHost(client, (int)stuff->hostFamily,
- stuff->hostLength, (pointer)&stuff[1]);
- if (stuff->mode == HostDelete)
- return RemoveHost(client, (int)stuff->hostFamily,
- stuff->hostLength, (pointer)&stuff[1]);
- client->errorValue = stuff->mode;
- return BadValue;
-}
-
-int
-ProcListHosts(ClientPtr client)
-{
- xListHostsReply reply;
- int len, nHosts, result;
- pointer pdata;
- /* REQUEST(xListHostsReq); */
-
- REQUEST_SIZE_MATCH(xListHostsReq);
-
- /* untrusted clients can't list hosts */
- result = XaceHook(XACE_SERVER_ACCESS, client, DixReadAccess);
- if (result != Success)
- return result;
-
- result = GetHosts(&pdata, &nHosts, &len, &reply.enabled);
- if (result != Success)
- return result;
- reply.type = X_Reply;
- reply.sequenceNumber = client->sequence;
- reply.nHosts = nHosts;
- reply.length = bytes_to_int32(len);
- WriteReplyToClient(client, sizeof(xListHostsReply), &reply);
- if (nHosts)
- {
- client->pSwapReplyFunc = (ReplySwapPtr) SLHostsExtend;
- WriteSwappedDataToClient(client, len, pdata);
- }
- free(pdata);
- return Success;
-}
-
-int
-ProcChangeAccessControl(ClientPtr client)
-{
- REQUEST(xSetAccessControlReq);
-
- REQUEST_SIZE_MATCH(xSetAccessControlReq);
- if ((stuff->mode != EnableAccess) && (stuff->mode != DisableAccess))
- {
- client->errorValue = stuff->mode;
- return BadValue;
- }
- return ChangeAccessControl(client, stuff->mode == EnableAccess);
-}
-
-/*********************
- * CloseDownRetainedResources
- *
- * Find all clients that are gone and have terminated in RetainTemporary
- * and destroy their resources.
- *********************/
-
-static void
-CloseDownRetainedResources(void)
-{
- int i;
- ClientPtr client;
-
- for (i=1; i<currentMaxClients; i++)
- {
- client = clients[i];
- if (client && (client->closeDownMode == RetainTemporary)
- && (client->clientGone))
- CloseDownClient(client);
- }
-}
-
-int
-ProcKillClient(ClientPtr client)
-{
- REQUEST(xResourceReq);
- ClientPtr killclient;
- int rc;
-
- REQUEST_SIZE_MATCH(xResourceReq);
- if (stuff->id == AllTemporary)
- {
- CloseDownRetainedResources();
- return Success;
- }
-
- rc = dixLookupClient(&killclient, stuff->id, client, DixDestroyAccess);
- if (rc == Success) {
- CloseDownClient(killclient);
- /* if an LBX proxy gets killed, isItTimeToYield will be set */
- if (isItTimeToYield || (client == killclient))
- {
- /* force yield and return Success, so that Dispatch()
- * doesn't try to touch client
- */
- isItTimeToYield = TRUE;
- return Success;
- }
- return Success;
- }
- else
- return rc;
-}
-
-int
-ProcSetFontPath(ClientPtr client)
-{
- unsigned char *ptr;
- unsigned long nbytes, total;
- long nfonts;
- int n;
- REQUEST(xSetFontPathReq);
-
- REQUEST_AT_LEAST_SIZE(xSetFontPathReq);
-
- nbytes = (client->req_len << 2) - sizeof(xSetFontPathReq);
- total = nbytes;
- ptr = (unsigned char *)&stuff[1];
- nfonts = stuff->nFonts;
- while (--nfonts >= 0)
- {
- if ((total == 0) || (total < (n = (*ptr + 1))))
- return BadLength;
- total -= n;
- ptr += n;
- }
- if (total >= 4)
- return BadLength;
- return SetFontPath(client, stuff->nFonts, (unsigned char *)&stuff[1]);
-}
-
-int
-ProcGetFontPath(ClientPtr client)
-{
- xGetFontPathReply reply;
- int rc, stringLens, numpaths;
- unsigned char *bufferStart;
- /* REQUEST (xReq); */
-
- REQUEST_SIZE_MATCH(xReq);
- rc = GetFontPath(client, &numpaths, &stringLens, &bufferStart);
- if (rc != Success)
- return rc;
-
- reply.type = X_Reply;
- reply.sequenceNumber = client->sequence;
- reply.length = bytes_to_int32(stringLens + numpaths);
- reply.nPaths = numpaths;
-
- WriteReplyToClient(client, sizeof(xGetFontPathReply), &reply);
- if (stringLens || numpaths)
- (void)WriteToClient(client, stringLens + numpaths, (char *)bufferStart);
- return Success;
-}
-
-int
-ProcChangeCloseDownMode(ClientPtr client)
-{
- int rc;
- REQUEST(xSetCloseDownModeReq);
- REQUEST_SIZE_MATCH(xSetCloseDownModeReq);
-
- rc = XaceHook(XACE_CLIENT_ACCESS, client, client, DixManageAccess);
- if (rc != Success)
- return rc;
-
- if ((stuff->mode == AllTemporary) ||
- (stuff->mode == RetainPermanent) ||
- (stuff->mode == RetainTemporary))
- {
- client->closeDownMode = stuff->mode;
- return Success;
- }
- else
- {
- client->errorValue = stuff->mode;
- return BadValue;
- }
-}
-
-int ProcForceScreenSaver(ClientPtr client)
-{
- int rc;
- REQUEST(xForceScreenSaverReq);
-
- REQUEST_SIZE_MATCH(xForceScreenSaverReq);
-
- if ((stuff->mode != ScreenSaverReset) &&
- (stuff->mode != ScreenSaverActive))
- {
- client->errorValue = stuff->mode;
- return BadValue;
- }
- rc = dixSaveScreens(client, SCREEN_SAVER_FORCER, (int)stuff->mode);
- if (rc != Success)
- return rc;
- return Success;
-}
-
-int ProcNoOperation(ClientPtr client)
-{
- REQUEST_AT_LEAST_SIZE(xReq);
-
- /* noop -- don't do anything */
- return Success;
-}
-
-/**********************
- * CloseDownClient
- *
- * Client can either mark his resources destroy or retain. If retained and
- * then killed again, the client is really destroyed.
- *********************/
-
-char dispatchExceptionAtReset = DE_RESET;
-
-void
-CloseDownClient(ClientPtr client)
-{
- Bool really_close_down = client->clientGone ||
- client->closeDownMode == DestroyAll;
-
- if (!client->clientGone)
- {
- /* ungrab server if grabbing client dies */
- if (grabState != GrabNone && grabClient == client)
- {
- UngrabServer(client);
- }
- BITCLEAR(grabWaiters, client->index);
- DeleteClientFromAnySelections(client);
- ReleaseActiveGrabs(client);
- DeleteClientFontStuff(client);
- if (!really_close_down)
- {
- /* This frees resources that should never be retained
- * no matter what the close down mode is. Actually we
- * could do this unconditionally, but it's probably
- * better not to traverse all the client's resources
- * twice (once here, once a few lines down in
- * FreeClientResources) in the common case of
- * really_close_down == TRUE.
- */
- FreeClientNeverRetainResources(client);
- client->clientState = ClientStateRetained;
- if (ClientStateCallback)
- {
- NewClientInfoRec clientinfo;
-
- clientinfo.client = client;
- clientinfo.prefix = (xConnSetupPrefix *)NULL;
- clientinfo.setup = (xConnSetup *) NULL;
- CallCallbacks((&ClientStateCallback), (pointer)&clientinfo);
- }
- }
- client->clientGone = TRUE; /* so events aren't sent to client */
- if (ClientIsAsleep(client))
- ClientSignal (client);
- ProcessWorkQueueZombies();
- CloseDownConnection(client);
-
- /* If the client made it to the Running stage, nClients has
- * been incremented on its behalf, so we need to decrement it
- * now. If it hasn't gotten to Running, nClients has *not*
- * been incremented, so *don't* decrement it.
- */
- if (client->clientState != ClientStateInitial &&
- client->clientState != ClientStateAuthenticating )
- {
- --nClients;
- }
- }
-
- if (really_close_down)
- {
- if (client->clientState == ClientStateRunning && nClients == 0)
- dispatchException |= dispatchExceptionAtReset;
-
- client->clientState = ClientStateGone;
- if (ClientStateCallback)
- {
- NewClientInfoRec clientinfo;
-
- clientinfo.client = client;
- clientinfo.prefix = (xConnSetupPrefix *)NULL;
- clientinfo.setup = (xConnSetup *) NULL;
- CallCallbacks((&ClientStateCallback), (pointer)&clientinfo);
- }
- FreeClientResources(client);
-#ifdef XSERVER_DTRACE
- XSERVER_CLIENT_DISCONNECT(client->index);
-#endif
- if (client->index < nextFreeClientID)
- nextFreeClientID = client->index;
- clients[client->index] = NullClient;
- SmartLastClient = NullClient;
- dixFreeObjectWithPrivates(client, PRIVATE_CLIENT);
-
- while (!clients[currentMaxClients-1])
- currentMaxClients--;
- }
-}
-
-static void
-KillAllClients(void)
-{
- int i;
- for (i=1; i<currentMaxClients; i++)
- if (clients[i]) {
- /* Make sure Retained clients are released. */
- clients[i]->closeDownMode = DestroyAll;
- CloseDownClient(clients[i]);
- }
-}
-
-void InitClient(ClientPtr client, int i, pointer ospriv)
-{
- client->index = i;
- client->clientAsMask = ((Mask)i) << CLIENTOFFSET;
- client->closeDownMode = i ? DestroyAll : RetainPermanent;
- client->requestVector = InitialVector;
- client->osPrivate = ospriv;
- QueryMinMaxKeyCodes(&client->minKC,&client->maxKC);
- client->smart_start_tick = SmartScheduleTime;
- client->smart_stop_tick = SmartScheduleTime;
- client->smart_check_tick = SmartScheduleTime;
-}
-
-/************************
- * int NextAvailableClient(ospriv)
- *
- * OS dependent portion can't assign client id's because of CloseDownModes.
- * Returns NULL if there are no free clients.
- *************************/
-
-ClientPtr NextAvailableClient(pointer ospriv)
-{
- int i;
- ClientPtr client;
- xReq data;
-
- i = nextFreeClientID;
- if (i == MAXCLIENTS)
- return (ClientPtr)NULL;
- clients[i] = client = dixAllocateObjectWithPrivates(ClientRec, PRIVATE_CLIENT);
- if (!client)
- return (ClientPtr)NULL;
- InitClient(client, i, ospriv);
- if (!InitClientResources(client))
- {
- dixFreeObjectWithPrivates(client, PRIVATE_CLIENT);
- return (ClientPtr)NULL;
- }
- data.reqType = 1;
- data.length = bytes_to_int32(sz_xReq + sz_xConnClientPrefix);
- if (!InsertFakeRequest(client, (char *)&data, sz_xReq))
- {
- FreeClientResources(client);
- dixFreeObjectWithPrivates(client, PRIVATE_CLIENT);
- return (ClientPtr)NULL;
- }
- if (i == currentMaxClients)
- currentMaxClients++;
- while ((nextFreeClientID < MAXCLIENTS) && clients[nextFreeClientID])
- nextFreeClientID++;
- if (ClientStateCallback)
- {
- NewClientInfoRec clientinfo;
-
- clientinfo.client = client;
- clientinfo.prefix = (xConnSetupPrefix *)NULL;
- clientinfo.setup = (xConnSetup *) NULL;
- CallCallbacks((&ClientStateCallback), (pointer)&clientinfo);
- }
- return client;
-}
-
-int
-ProcInitialConnection(ClientPtr client)
-{
- REQUEST(xReq);
- xConnClientPrefix *prefix;
- int whichbyte = 1;
-
- prefix = (xConnClientPrefix *)((char *)stuff + sz_xReq);
- if ((prefix->byteOrder != 'l') && (prefix->byteOrder != 'B'))
- return client->noClientException = -1;
- if (((*(char *) &whichbyte) && (prefix->byteOrder == 'B')) ||
- (!(*(char *) &whichbyte) && (prefix->byteOrder == 'l')))
- {
- client->swapped = TRUE;
- SwapConnClientPrefix(prefix);
- }
- stuff->reqType = 2;
- stuff->length += bytes_to_int32(prefix->nbytesAuthProto) +
- bytes_to_int32(prefix->nbytesAuthString);
- if (client->swapped)
- {
- swaps(&stuff->length, whichbyte);
- }
- ResetCurrentRequest(client);
- return Success;
-}
-
-static int
-SendConnSetup(ClientPtr client, char *reason)
-{
- xWindowRoot *root;
- int i;
- int numScreens;
- char* lConnectionInfo;
- xConnSetupPrefix* lconnSetupPrefix;
-
- if (reason)
- {
- xConnSetupPrefix csp;
-
- csp.success = xFalse;
- csp.lengthReason = strlen(reason);
- csp.length = bytes_to_int32(csp.lengthReason);
- csp.majorVersion = X_PROTOCOL;
- csp.minorVersion = X_PROTOCOL_REVISION;
- if (client->swapped)
- WriteSConnSetupPrefix(client, &csp);
- else
- (void)WriteToClient(client, sz_xConnSetupPrefix, (char *) &csp);
- (void)WriteToClient(client, (int)csp.lengthReason, reason);
- return client->noClientException = -1;
- }
-
- numScreens = screenInfo.numScreens;
- lConnectionInfo = ConnectionInfo;
- lconnSetupPrefix = &connSetupPrefix;
-
- /* We're about to start speaking X protocol back to the client by
- * sending the connection setup info. This means the authorization
- * step is complete, and we can count the client as an
- * authorized one.
- */
- nClients++;
-
- client->requestVector = client->swapped ? SwappedProcVector : ProcVector;
- client->sequence = 0;
- ((xConnSetup *)lConnectionInfo)->ridBase = client->clientAsMask;
- ((xConnSetup *)lConnectionInfo)->ridMask = RESOURCE_ID_MASK;
-#ifdef MATCH_CLIENT_ENDIAN
- ((xConnSetup *)lConnectionInfo)->imageByteOrder = ClientOrder (client);
- ((xConnSetup *)lConnectionInfo)->bitmapBitOrder = ClientOrder (client);
-#endif
- /* fill in the "currentInputMask" */
- root = (xWindowRoot *)(lConnectionInfo + connBlockScreenStart);
-#ifdef PANORAMIX
- if (noPanoramiXExtension)
- numScreens = screenInfo.numScreens;
- else
- numScreens = ((xConnSetup *)ConnectionInfo)->numRoots;
-#endif
-
- for (i=0; i<numScreens; i++)
- {
- unsigned int j;
- xDepth *pDepth;
- WindowPtr pRoot = screenInfo.screens[i]->root;
-
- root->currentInputMask = pRoot->eventMask | wOtherEventMasks(pRoot);
- pDepth = (xDepth *)(root + 1);
- for (j = 0; j < root->nDepths; j++)
- {
- pDepth = (xDepth *)(((char *)(pDepth + 1)) +
- pDepth->nVisuals * sizeof(xVisualType));
- }
- root = (xWindowRoot *)pDepth;
- }
-
- if (client->swapped)
- {
- WriteSConnSetupPrefix(client, lconnSetupPrefix);
- WriteSConnectionInfo(client,
- (unsigned long)(lconnSetupPrefix->length << 2),
- lConnectionInfo);
- }
- else
- {
- (void)WriteToClient(client, sizeof(xConnSetupPrefix),
- (char *) lconnSetupPrefix);
- (void)WriteToClient(client, (int)(lconnSetupPrefix->length << 2),
- lConnectionInfo);
- }
- client->clientState = ClientStateRunning;
- if (ClientStateCallback)
- {
- NewClientInfoRec clientinfo;
-
- clientinfo.client = client;
- clientinfo.prefix = lconnSetupPrefix;
- clientinfo.setup = (xConnSetup *)lConnectionInfo;
- CallCallbacks((&ClientStateCallback), (pointer)&clientinfo);
- }
- return Success;
-}
-
-int
-ProcEstablishConnection(ClientPtr client)
-{
- char *reason, *auth_proto, *auth_string;
- xConnClientPrefix *prefix;
- REQUEST(xReq);
-
- prefix = (xConnClientPrefix *)((char *)stuff + sz_xReq);
- auth_proto = (char *)prefix + sz_xConnClientPrefix;
- auth_string = auth_proto + pad_to_int32(prefix->nbytesAuthProto);
- if ((prefix->majorVersion != X_PROTOCOL) ||
- (prefix->minorVersion != X_PROTOCOL_REVISION))
- reason = "Protocol version mismatch";
- else
- reason = ClientAuthorized(client,
- (unsigned short)prefix->nbytesAuthProto,
- auth_proto,
- (unsigned short)prefix->nbytesAuthString,
- auth_string);
- /*
- * If Kerberos is being used for this client, the clientState
- * will be set to ClientStateAuthenticating at this point.
- * More messages need to be exchanged among the X server, Kerberos
- * server, and client to figure out if everyone is authorized.
- * So we don't want to send the connection setup info yet, since
- * the auth step isn't really done.
- */
- if (client->clientState == ClientStateCheckingSecurity)
- client->clientState = ClientStateCheckedSecurity;
- else if (client->clientState != ClientStateAuthenticating)
- return(SendConnSetup(client, reason));
- return Success;
-}
-
-void
-SendErrorToClient(ClientPtr client, unsigned majorCode, unsigned minorCode,
- XID resId, int errorCode)
-{
- xError rep;
-
- memset(&rep, 0, sizeof(xError));
- rep.type = X_Error;
- rep.errorCode = errorCode;
- rep.majorCode = majorCode;
- rep.minorCode = minorCode;
- rep.resourceID = resId;
-
- WriteEventsToClient (client, 1, (xEvent *)&rep);
-}
-
-void
-MarkClientException(ClientPtr client)
-{
- client->noClientException = -1;
-}
-
-/*
- * This array encodes the answer to the question "what is the log base 2
- * of the number of pixels that fit in a scanline pad unit?"
- * Note that ~0 is an invalid entry (mostly for the benefit of the reader).
- */
-static int answer[6][4] = {
- /* pad pad pad pad*/
- /* 8 16 32 64 */
-
- { 3, 4, 5 , 6 }, /* 1 bit per pixel */
- { 1, 2, 3 , 4 }, /* 4 bits per pixel */
- { 0, 1, 2 , 3 }, /* 8 bits per pixel */
- { ~0, 0, 1 , 2 }, /* 16 bits per pixel */
- { ~0, ~0, 0 , 1 }, /* 24 bits per pixel */
- { ~0, ~0, 0 , 1 } /* 32 bits per pixel */
-};
-
-/*
- * This array gives the answer to the question "what is the first index for
- * the answer array above given the number of bits per pixel?"
- * Note that ~0 is an invalid entry (mostly for the benefit of the reader).
- */
-static int indexForBitsPerPixel[ 33 ] = {
- ~0, 0, ~0, ~0, /* 1 bit per pixel */
- 1, ~0, ~0, ~0, /* 4 bits per pixel */
- 2, ~0, ~0, ~0, /* 8 bits per pixel */
- ~0,~0, ~0, ~0,
- 3, ~0, ~0, ~0, /* 16 bits per pixel */
- ~0,~0, ~0, ~0,
- 4, ~0, ~0, ~0, /* 24 bits per pixel */
- ~0,~0, ~0, ~0,
- 5 /* 32 bits per pixel */
-};
-
-/*
- * This array gives the bytesperPixel value for cases where the number
- * of bits per pixel is a multiple of 8 but not a power of 2.
- */
-static int answerBytesPerPixel[ 33 ] = {
- ~0, 0, ~0, ~0, /* 1 bit per pixel */
- 0, ~0, ~0, ~0, /* 4 bits per pixel */
- 0, ~0, ~0, ~0, /* 8 bits per pixel */
- ~0,~0, ~0, ~0,
- 0, ~0, ~0, ~0, /* 16 bits per pixel */
- ~0,~0, ~0, ~0,
- 3, ~0, ~0, ~0, /* 24 bits per pixel */
- ~0,~0, ~0, ~0,
- 0 /* 32 bits per pixel */
-};
-
-/*
- * This array gives the answer to the question "what is the second index for
- * the answer array above given the number of bits per scanline pad unit?"
- * Note that ~0 is an invalid entry (mostly for the benefit of the reader).
- */
-static int indexForScanlinePad[ 65 ] = {
- ~0, ~0, ~0, ~0,
- ~0, ~0, ~0, ~0,
- 0, ~0, ~0, ~0, /* 8 bits per scanline pad unit */
- ~0, ~0, ~0, ~0,
- 1, ~0, ~0, ~0, /* 16 bits per scanline pad unit */
- ~0, ~0, ~0, ~0,
- ~0, ~0, ~0, ~0,
- ~0, ~0, ~0, ~0,
- 2, ~0, ~0, ~0, /* 32 bits per scanline pad unit */
- ~0, ~0, ~0, ~0,
- ~0, ~0, ~0, ~0,
- ~0, ~0, ~0, ~0,
- ~0, ~0, ~0, ~0,
- ~0, ~0, ~0, ~0,
- ~0, ~0, ~0, ~0,
- ~0, ~0, ~0, ~0,
- 3 /* 64 bits per scanline pad unit */
-};
-
-/*
- grow the array of screenRecs if necessary.
- call the device-supplied initialization procedure
-with its screen number, a pointer to its ScreenRec, argc, and argv.
- return the number of successfully installed screens.
-
-*/
-
-int
-AddScreen(
- Bool (* pfnInit)(
- int /*index*/,
- ScreenPtr /*pScreen*/,
- int /*argc*/,
- char ** /*argv*/
- ),
- int argc,
- char **argv)
-{
-
- int i;
- int scanlinepad, format, depth, bitsPerPixel, j, k;
- ScreenPtr pScreen;
-
- i = screenInfo.numScreens;
- if (i == MAXSCREENS)
- return -1;
-
- pScreen = (ScreenPtr) calloc(1, sizeof(ScreenRec));
- if (!pScreen)
- return -1;
-
- if (!dixAllocatePrivates(&pScreen->devPrivates, PRIVATE_SCREEN)) {
- free (pScreen);
- return -1;
- }
- pScreen->myNum = i;
- pScreen->totalPixmapSize = 0; /* computed in CreateScratchPixmapForScreen */
- pScreen->ClipNotify = 0; /* for R4 ddx compatibility */
- pScreen->CreateScreenResources = 0;
-
- /*
- * This loop gets run once for every Screen that gets added,
- * but thats ok. If the ddx layer initializes the formats
- * one at a time calling AddScreen() after each, then each
- * iteration will make it a little more accurate. Worst case
- * we do this loop N * numPixmapFormats where N is # of screens.
- * Anyway, this must be called after InitOutput and before the
- * screen init routine is called.
- */
- for (format=0; format<screenInfo.numPixmapFormats; format++)
- {
- depth = screenInfo.formats[format].depth;
- bitsPerPixel = screenInfo.formats[format].bitsPerPixel;
- scanlinepad = screenInfo.formats[format].scanlinePad;
- j = indexForBitsPerPixel[ bitsPerPixel ];
- k = indexForScanlinePad[ scanlinepad ];
- PixmapWidthPaddingInfo[ depth ].padPixelsLog2 = answer[j][k];
- PixmapWidthPaddingInfo[ depth ].padRoundUp =
- (scanlinepad/bitsPerPixel) - 1;
- j = indexForBitsPerPixel[ 8 ]; /* bits per byte */
- PixmapWidthPaddingInfo[ depth ].padBytesLog2 = answer[j][k];
- PixmapWidthPaddingInfo[ depth ].bitsPerPixel = bitsPerPixel;
- if (answerBytesPerPixel[bitsPerPixel])
- {
- PixmapWidthPaddingInfo[ depth ].notPower2 = 1;
- PixmapWidthPaddingInfo[ depth ].bytesPerPixel =
- answerBytesPerPixel[bitsPerPixel];
- }
- else
- {
- PixmapWidthPaddingInfo[ depth ].notPower2 = 0;
- }
- }
-
- /* This is where screen specific stuff gets initialized. Load the
- screen structure, call the hardware, whatever.
- This is also where the default colormap should be allocated and
- also pixel values for blackPixel, whitePixel, and the cursor
- Note that InitScreen is NOT allowed to modify argc, argv, or
- any of the strings pointed to by argv. They may be passed to
- multiple screens.
- */
- screenInfo.screens[i] = pScreen;
- screenInfo.numScreens++;
- if (!(*pfnInit)(i, pScreen, argc, argv))
- {
- dixFreePrivates(pScreen->devPrivates, PRIVATE_SCREEN);
- free(pScreen);
- screenInfo.numScreens--;
- return -1;
- }
-
- dixRegisterPrivateKey(&cursorScreenDevPriv[i], PRIVATE_CURSOR, 0);
-
- return i;
-}
+/************************************************************ + +Copyright 1987, 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987, 1989 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission 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 that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY 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 THIS +SOFTWARE. + +********************************************************/ + +/* The panoramix components contained the following notice */ +/***************************************************************** + +Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING, +BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of Digital Equipment Corporation +shall not be used in advertising or otherwise to promote the sale, use or other +dealings in this Software without prior written authorization from Digital +Equipment Corporation. + +******************************************************************/ + +/* XSERVER_DTRACE additions: + * Copyright (c) 2005-2006, Oracle and/or its affiliates. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + + + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#include <version-config.h> +#endif + +#ifdef PANORAMIX_DEBUG +#include <stdio.h> +int ProcInitialConnection(); +#endif + +#include "windowstr.h" +#include <X11/fonts/fontstruct.h> +#include "dixfontstr.h" +#include "gcstruct.h" +#include "selection.h" +#include "colormapst.h" +#include "cursorstr.h" +#include "scrnintstr.h" +#include "opaque.h" +#include "input.h" +#include "servermd.h" +#include "extnsionst.h" +#include "dixfont.h" +#include "dispatch.h" +#include "swaprep.h" +#include "swapreq.h" +#include "privates.h" +#include "xace.h" +#include "inputstr.h" +#include "xkbsrv.h" +#include "site.h" +#include "client.h" + +#ifdef XSERVER_DTRACE +#include "registry.h" +#include <sys/types.h> +typedef const char *string; +#include "Xserver-dtrace.h" +#endif + +#define mskcnt ((MAXCLIENTS + 31) / 32) +#define BITMASK(i) (1U << ((i) & 31)) +#define MASKIDX(i) ((i) >> 5) +#define MASKWORD(buf, i) buf[MASKIDX(i)] +#define BITSET(buf, i) MASKWORD(buf, i) |= BITMASK(i) +#define BITCLEAR(buf, i) MASKWORD(buf, i) &= ~BITMASK(i) +#define GETBIT(buf, i) (MASKWORD(buf, i) & BITMASK(i)) + +xConnSetupPrefix connSetupPrefix; + +PaddingInfo PixmapWidthPaddingInfo[33]; + +static ClientPtr grabClient; +#define GrabNone 0 +#define GrabActive 1 +#define GrabKickout 2 +static int grabState = GrabNone; +static long grabWaiters[mskcnt]; +CallbackListPtr ServerGrabCallback = NULL; +HWEventQueuePtr checkForInput[2]; +int connBlockScreenStart; + +static void KillAllClients(void); + +static int nextFreeClientID; /* always MIN free client ID */ + +static int nClients; /* number of authorized clients */ + +CallbackListPtr ClientStateCallback; + +/* dispatchException & isItTimeToYield must be declared volatile since they + * are modified by signal handlers - otherwise optimizer may assume it doesn't + * need to actually check value in memory when used and may miss changes from + * signal handlers. + */ +volatile char dispatchException = 0; +volatile char isItTimeToYield; + +#define SAME_SCREENS(a, b) (\ + (a.pScreen == b.pScreen)) + +void +SetInputCheck(HWEventQueuePtr c0, HWEventQueuePtr c1) +{ + checkForInput[0] = c0; + checkForInput[1] = c1; +} + +void +UpdateCurrentTime(void) +{ + TimeStamp systime; + + /* To avoid time running backwards, we must call GetTimeInMillis before + * calling ProcessInputEvents. + */ + systime.months = currentTime.months; + systime.milliseconds = GetTimeInMillis(); + if (systime.milliseconds < currentTime.milliseconds) + systime.months++; + if (*checkForInput[0] != *checkForInput[1]) + ProcessInputEvents(); + if (CompareTimeStamps(systime, currentTime) == LATER) + currentTime = systime; +} + +/* Like UpdateCurrentTime, but can't call ProcessInputEvents */ +void +UpdateCurrentTimeIf(void) +{ + TimeStamp systime; + + systime.months = currentTime.months; + systime.milliseconds = GetTimeInMillis(); + if (systime.milliseconds < currentTime.milliseconds) + systime.months++; + if (*checkForInput[0] == *checkForInput[1]) + currentTime = systime; +} + + +#undef SMART_DEBUG + +#define SMART_SCHEDULE_DEFAULT_INTERVAL 20 /* ms */ +#define SMART_SCHEDULE_MAX_SLICE 200 /* ms */ + +Bool SmartScheduleDisable = FALSE; +long SmartScheduleSlice = SMART_SCHEDULE_DEFAULT_INTERVAL; +long SmartScheduleInterval = SMART_SCHEDULE_DEFAULT_INTERVAL; +long SmartScheduleMaxSlice = SMART_SCHEDULE_MAX_SLICE; +long SmartScheduleTime; +int SmartScheduleLatencyLimited = 0; +static ClientPtr SmartLastClient; +static int SmartLastIndex[SMART_MAX_PRIORITY-SMART_MIN_PRIORITY+1]; + +#ifdef SMART_DEBUG +long SmartLastPrint; +#endif + +void Dispatch(void); + +static int +SmartScheduleClient (int *clientReady, int nready) +{ + ClientPtr pClient; + int i; + int client; + int bestPrio, best = 0; + int bestRobin, robin; + long now = SmartScheduleTime; + long idle; + + bestPrio = -0x7fffffff; + bestRobin = 0; + idle = 2 * SmartScheduleSlice; + for (i = 0; i < nready; i++) + { + client = clientReady[i]; + pClient = clients[client]; + /* Praise clients which are idle */ + if ((now - pClient->smart_check_tick) >= idle) + { + if (pClient->smart_priority < 0) + pClient->smart_priority++; + } + pClient->smart_check_tick = now; + + /* check priority to select best client */ + robin = (pClient->index - SmartLastIndex[pClient->smart_priority-SMART_MIN_PRIORITY]) & 0xff; + if (pClient->smart_priority > bestPrio || + (pClient->smart_priority == bestPrio && robin > bestRobin)) + { + bestPrio = pClient->smart_priority; + bestRobin = robin; + best = client; + } +#ifdef SMART_DEBUG + if ((now - SmartLastPrint) >= 5000) + fprintf (stderr, " %2d: %3d", client, pClient->smart_priority); +#endif + } +#ifdef SMART_DEBUG + if ((now - SmartLastPrint) >= 5000) + { + fprintf (stderr, " use %2d\n", best); + SmartLastPrint = now; + } +#endif + pClient = clients[best]; + SmartLastIndex[bestPrio-SMART_MIN_PRIORITY] = pClient->index; + /* + * Set current client pointer + */ + if (SmartLastClient != pClient) + { + pClient->smart_start_tick = now; + SmartLastClient = pClient; + } + /* + * Adjust slice + */ + if (nready == 1 && SmartScheduleLatencyLimited == 0) + { + /* + * If it's been a long time since another client + * has run, bump the slice up to get maximal + * performance from a single client + */ + if ((now - pClient->smart_start_tick) > 1000 && + SmartScheduleSlice < SmartScheduleMaxSlice) + { + SmartScheduleSlice += SmartScheduleInterval; + } + } + else + { + SmartScheduleSlice = SmartScheduleInterval; + } + return best; +} + +void +EnableLimitedSchedulingLatency(void) +{ + ++SmartScheduleLatencyLimited; + SmartScheduleSlice = SmartScheduleInterval; +} + +void +DisableLimitedSchedulingLatency(void) +{ + --SmartScheduleLatencyLimited; + + /* protect against bugs */ + if (SmartScheduleLatencyLimited < 0) + SmartScheduleLatencyLimited = 0; +} + +#define MAJOROP ((xReq *)client->requestBuffer)->reqType + +void +Dispatch(void) +{ + int *clientReady; /* array of request ready clients */ + int result; + ClientPtr client; + int nready; + HWEventQueuePtr* icheck = checkForInput; + long start_tick; + + nextFreeClientID = 1; + nClients = 0; + + clientReady = malloc(sizeof(int) * MaxClients); + if (!clientReady) + return; + + SmartScheduleSlice = SmartScheduleInterval; + while (!dispatchException) + { + if (*icheck[0] != *icheck[1]) + { + ProcessInputEvents(); + FlushIfCriticalOutputPending(); + } + + nready = WaitForSomething(clientReady); + + if (nready && !SmartScheduleDisable) + { + clientReady[0] = SmartScheduleClient (clientReady, nready); + nready = 1; + } + /***************** + * Handle events in round robin fashion, doing input between + * each round + *****************/ + + while (!dispatchException && (--nready >= 0)) + { + client = clients[clientReady[nready]]; + if (! client) + { + /* KillClient can cause this to happen */ + continue; + } + /* GrabServer activation can cause this to be true */ + if (grabState == GrabKickout) + { + grabState = GrabActive; + break; + } + isItTimeToYield = FALSE; + + start_tick = SmartScheduleTime; + while (!isItTimeToYield) + { + if (*icheck[0] != *icheck[1]) + ProcessInputEvents(); + + FlushIfCriticalOutputPending(); + if (!SmartScheduleDisable && + (SmartScheduleTime - start_tick) >= SmartScheduleSlice) + { + /* Penalize clients which consume ticks */ + if (client->smart_priority > SMART_MIN_PRIORITY) + client->smart_priority--; + break; + } + /* now, finally, deal with client requests */ + + result = ReadRequestFromClient(client); + if (result <= 0) + { + if (result < 0) + CloseDownClient(client); + break; + } + + client->sequence++; +#ifdef XSERVER_DTRACE + XSERVER_REQUEST_START(LookupMajorName(MAJOROP), MAJOROP, + ((xReq *)client->requestBuffer)->length, + client->index, client->requestBuffer); +#endif + if (result > (maxBigRequestSize << 2)) + result = BadLength; + else { + result = XaceHookDispatch(client, MAJOROP); + if (result == Success) + result = (* client->requestVector[MAJOROP])(client); + XaceHookAuditEnd(client, result); + } +#ifdef XSERVER_DTRACE + XSERVER_REQUEST_DONE(LookupMajorName(MAJOROP), MAJOROP, + client->sequence, client->index, result); +#endif + + if (client->noClientException != Success) + { + CloseDownClient(client); + break; + } + else if (result != Success) + { + SendErrorToClient(client, MAJOROP, + MinorOpcodeOfRequest(client), + client->errorValue, result); + break; + } + } + FlushAllOutput(); + client = clients[clientReady[nready]]; + if (client) + client->smart_stop_tick = SmartScheduleTime; + } + dispatchException &= ~DE_PRIORITYCHANGE; + } +#if defined(DDXBEFORERESET) + ddxBeforeReset (); +#endif + KillAllClients(); + free(clientReady); + dispatchException &= ~DE_RESET; + SmartScheduleLatencyLimited = 0; +} + +#undef MAJOROP + +static int VendorRelease = VENDOR_RELEASE; +static char *VendorString = VENDOR_NAME; + +static const int padlength[4] = {0, 3, 2, 1}; + +void +SetVendorRelease(int release) +{ + VendorRelease = release; +} + +void +SetVendorString(char *string) +{ + VendorString = string; +} + +Bool +CreateConnectionBlock(void) +{ + xConnSetup setup; + xWindowRoot root; + xDepth depth; + xVisualType visual; + xPixmapFormat format; + unsigned long vid; + int i, j, k, + lenofblock, + sizesofar = 0; + char *pBuf; + + + memset(&setup, 0, sizeof(xConnSetup)); + /* Leave off the ridBase and ridMask, these must be sent with + connection */ + + setup.release = VendorRelease; + /* + * per-server image and bitmap parameters are defined in Xmd.h + */ + setup.imageByteOrder = screenInfo.imageByteOrder; + + setup.bitmapScanlineUnit = screenInfo.bitmapScanlineUnit; + setup.bitmapScanlinePad = screenInfo.bitmapScanlinePad; + + setup.bitmapBitOrder = screenInfo.bitmapBitOrder; + setup.motionBufferSize = NumMotionEvents(); + setup.numRoots = screenInfo.numScreens; + setup.nbytesVendor = strlen(VendorString); + setup.numFormats = screenInfo.numPixmapFormats; + setup.maxRequestSize = MAX_REQUEST_SIZE; + QueryMinMaxKeyCodes(&setup.minKeyCode, &setup.maxKeyCode); + + lenofblock = sizeof(xConnSetup) + + pad_to_int32(setup.nbytesVendor) + + (setup.numFormats * sizeof(xPixmapFormat)) + + (setup.numRoots * sizeof(xWindowRoot)); + ConnectionInfo = malloc(lenofblock); + if (!ConnectionInfo) + return FALSE; + + memmove(ConnectionInfo, (char *)&setup, sizeof(xConnSetup)); + sizesofar = sizeof(xConnSetup); + pBuf = ConnectionInfo + sizeof(xConnSetup); + + memmove(pBuf, VendorString, (int)setup.nbytesVendor); + sizesofar += setup.nbytesVendor; + pBuf += setup.nbytesVendor; + i = padlength[setup.nbytesVendor & 3]; + sizesofar += i; + while (--i >= 0) + *pBuf++ = 0; + + memset(&format, 0, sizeof(xPixmapFormat)); + for (i=0; i<screenInfo.numPixmapFormats; i++) + { + format.depth = screenInfo.formats[i].depth; + format.bitsPerPixel = screenInfo.formats[i].bitsPerPixel; + format.scanLinePad = screenInfo.formats[i].scanlinePad; + memmove(pBuf, (char *)&format, sizeof(xPixmapFormat)); + pBuf += sizeof(xPixmapFormat); + sizesofar += sizeof(xPixmapFormat); + } + + connBlockScreenStart = sizesofar; + memset(&depth, 0, sizeof(xDepth)); + memset(&visual, 0, sizeof(xVisualType)); + for (i=0; i<screenInfo.numScreens; i++) + { + ScreenPtr pScreen; + DepthPtr pDepth; + VisualPtr pVisual; + + pScreen = screenInfo.screens[i]; + root.windowId = pScreen->root->drawable.id; + root.defaultColormap = pScreen->defColormap; + root.whitePixel = pScreen->whitePixel; + root.blackPixel = pScreen->blackPixel; + root.currentInputMask = 0; /* filled in when sent */ + root.pixWidth = pScreen->width; + root.pixHeight = pScreen->height; + root.mmWidth = pScreen->mmWidth; + root.mmHeight = pScreen->mmHeight; + root.minInstalledMaps = pScreen->minInstalledCmaps; + root.maxInstalledMaps = pScreen->maxInstalledCmaps; + root.rootVisualID = pScreen->rootVisual; + root.backingStore = pScreen->backingStoreSupport; + root.saveUnders = FALSE; + root.rootDepth = pScreen->rootDepth; + root.nDepths = pScreen->numDepths; + memmove(pBuf, (char *)&root, sizeof(xWindowRoot)); + sizesofar += sizeof(xWindowRoot); + pBuf += sizeof(xWindowRoot); + + pDepth = pScreen->allowedDepths; + for(j = 0; j < pScreen->numDepths; j++, pDepth++) + { + lenofblock += sizeof(xDepth) + + (pDepth->numVids * sizeof(xVisualType)); + pBuf = (char *)realloc(ConnectionInfo, lenofblock); + if (!pBuf) + { + free(ConnectionInfo); + return FALSE; + } + ConnectionInfo = pBuf; + pBuf += sizesofar; + depth.depth = pDepth->depth; + depth.nVisuals = pDepth->numVids; + memmove(pBuf, (char *)&depth, sizeof(xDepth)); + pBuf += sizeof(xDepth); + sizesofar += sizeof(xDepth); + for(k = 0; k < pDepth->numVids; k++) + { + vid = pDepth->vids[k]; + for (pVisual = pScreen->visuals; + pVisual->vid != vid; + pVisual++) + ; + visual.visualID = vid; + visual.class = pVisual->class; + visual.bitsPerRGB = pVisual->bitsPerRGBValue; + visual.colormapEntries = pVisual->ColormapEntries; + visual.redMask = pVisual->redMask; + visual.greenMask = pVisual->greenMask; + visual.blueMask = pVisual->blueMask; + memmove(pBuf, (char *)&visual, sizeof(xVisualType)); + pBuf += sizeof(xVisualType); + sizesofar += sizeof(xVisualType); + } + } + } + connSetupPrefix.success = xTrue; + connSetupPrefix.length = lenofblock/4; + connSetupPrefix.majorVersion = X_PROTOCOL; + connSetupPrefix.minorVersion = X_PROTOCOL_REVISION; + return TRUE; +} + + +int +ProcBadRequest(ClientPtr client) +{ + return BadRequest; +} + +int +ProcCreateWindow(ClientPtr client) +{ + WindowPtr pParent, pWin; + REQUEST(xCreateWindowReq); + int len, rc; + + REQUEST_AT_LEAST_SIZE(xCreateWindowReq); + + LEGAL_NEW_RESOURCE(stuff->wid, client); + rc = dixLookupWindow(&pParent, stuff->parent, client, DixAddAccess); + if (rc != Success) + return rc; + len = client->req_len - bytes_to_int32(sizeof(xCreateWindowReq)); + if (Ones(stuff->mask) != len) + return BadLength; + if (!stuff->width || !stuff->height) + { + client->errorValue = 0; + return BadValue; + } + pWin = CreateWindow(stuff->wid, pParent, stuff->x, + stuff->y, stuff->width, stuff->height, + stuff->borderWidth, stuff->class, + stuff->mask, (XID *) &stuff[1], + (int)stuff->depth, + client, stuff->visual, &rc); + if (pWin) + { + Mask mask = pWin->eventMask; + + pWin->eventMask = 0; /* subterfuge in case AddResource fails */ + if (!AddResource(stuff->wid, RT_WINDOW, (pointer)pWin)) + return BadAlloc; + pWin->eventMask = mask; + } + return rc; +} + +int +ProcChangeWindowAttributes(ClientPtr client) +{ + WindowPtr pWin; + REQUEST(xChangeWindowAttributesReq); + int len, rc; + Mask access_mode = 0; + + REQUEST_AT_LEAST_SIZE(xChangeWindowAttributesReq); + access_mode |= (stuff->valueMask & CWEventMask) ? DixReceiveAccess : 0; + access_mode |= (stuff->valueMask & ~CWEventMask) ? DixSetAttrAccess : 0; + rc = dixLookupWindow(&pWin, stuff->window, client, access_mode); + if (rc != Success) + return rc; + len = client->req_len - bytes_to_int32(sizeof(xChangeWindowAttributesReq)); + if (len != Ones(stuff->valueMask)) + return BadLength; + return ChangeWindowAttributes(pWin, + stuff->valueMask, + (XID *) &stuff[1], + client); +} + +int +ProcGetWindowAttributes(ClientPtr client) +{ + WindowPtr pWin; + REQUEST(xResourceReq); + xGetWindowAttributesReply wa; + int rc; + + REQUEST_SIZE_MATCH(xResourceReq); + rc = dixLookupWindow(&pWin, stuff->id, client, DixGetAttrAccess); + if (rc != Success) + return rc; + memset(&wa, 0, sizeof(xGetWindowAttributesReply)); + GetWindowAttributes(pWin, client, &wa); + WriteReplyToClient(client, sizeof(xGetWindowAttributesReply), &wa); + return Success; +} + +int +ProcDestroyWindow(ClientPtr client) +{ + WindowPtr pWin; + REQUEST(xResourceReq); + int rc; + + REQUEST_SIZE_MATCH(xResourceReq); + rc = dixLookupWindow(&pWin, stuff->id, client, DixDestroyAccess); + if (rc != Success) + return rc; + if (pWin->parent) { + rc = dixLookupWindow(&pWin, pWin->parent->drawable.id, client, + DixRemoveAccess); + if (rc != Success) + return rc; + FreeResource(stuff->id, RT_NONE); + } + return Success; +} + +int +ProcDestroySubwindows(ClientPtr client) +{ + WindowPtr pWin; + REQUEST(xResourceReq); + int rc; + + REQUEST_SIZE_MATCH(xResourceReq); + rc = dixLookupWindow(&pWin, stuff->id, client, DixRemoveAccess); + if (rc != Success) + return rc; + DestroySubwindows(pWin, client); + return Success; +} + +int +ProcChangeSaveSet(ClientPtr client) +{ + WindowPtr pWin; + REQUEST(xChangeSaveSetReq); + int rc; + + REQUEST_SIZE_MATCH(xChangeSaveSetReq); + rc = dixLookupWindow(&pWin, stuff->window, client, DixManageAccess); + if (rc != Success) + return rc; + if (client->clientAsMask == (CLIENT_BITS(pWin->drawable.id))) + return BadMatch; + if ((stuff->mode == SetModeInsert) || (stuff->mode == SetModeDelete)) + return AlterSaveSetForClient(client, pWin, stuff->mode, FALSE, TRUE); + client->errorValue = stuff->mode; + return BadValue; +} + +int +ProcReparentWindow(ClientPtr client) +{ + WindowPtr pWin, pParent; + REQUEST(xReparentWindowReq); + int rc; + + REQUEST_SIZE_MATCH(xReparentWindowReq); + rc = dixLookupWindow(&pWin, stuff->window, client, DixManageAccess); + if (rc != Success) + return rc; + rc = dixLookupWindow(&pParent, stuff->parent, client, DixAddAccess); + if (rc != Success) + return rc; + if (!SAME_SCREENS(pWin->drawable, pParent->drawable)) + return BadMatch; + if ((pWin->backgroundState == ParentRelative) && + (pParent->drawable.depth != pWin->drawable.depth)) + return BadMatch; + if ((pWin->drawable.class != InputOnly) && + (pParent->drawable.class == InputOnly)) + return BadMatch; + return ReparentWindow(pWin, pParent, + (short)stuff->x, (short)stuff->y, client); +} + +int +ProcMapWindow(ClientPtr client) +{ + WindowPtr pWin; + REQUEST(xResourceReq); + int rc; + + REQUEST_SIZE_MATCH(xResourceReq); + rc = dixLookupWindow(&pWin, stuff->id, client, DixShowAccess); + if (rc != Success) + return rc; + MapWindow(pWin, client); + /* update cache to say it is mapped */ + return Success; +} + +int +ProcMapSubwindows(ClientPtr client) +{ + WindowPtr pWin; + REQUEST(xResourceReq); + int rc; + + REQUEST_SIZE_MATCH(xResourceReq); + rc = dixLookupWindow(&pWin, stuff->id, client, DixListAccess); + if (rc != Success) + return rc; + MapSubwindows(pWin, client); + /* update cache to say it is mapped */ + return Success; +} + +int +ProcUnmapWindow(ClientPtr client) +{ + WindowPtr pWin; + REQUEST(xResourceReq); + int rc; + + REQUEST_SIZE_MATCH(xResourceReq); + rc = dixLookupWindow(&pWin, stuff->id, client, DixHideAccess); + if (rc != Success) + return rc; + UnmapWindow(pWin, FALSE); + /* update cache to say it is mapped */ + return Success; +} + +int +ProcUnmapSubwindows(ClientPtr client) +{ + WindowPtr pWin; + REQUEST(xResourceReq); + int rc; + + REQUEST_SIZE_MATCH(xResourceReq); + rc = dixLookupWindow(&pWin, stuff->id, client, DixListAccess); + if (rc != Success) + return rc; + UnmapSubwindows(pWin); + return Success; +} + +int +ProcConfigureWindow(ClientPtr client) +{ + WindowPtr pWin; + REQUEST(xConfigureWindowReq); + int len, rc; + + REQUEST_AT_LEAST_SIZE(xConfigureWindowReq); + rc = dixLookupWindow(&pWin, stuff->window, client, + DixManageAccess|DixSetAttrAccess); + if (rc != Success) + return rc; + len = client->req_len - bytes_to_int32(sizeof(xConfigureWindowReq)); + if (Ones((Mask)stuff->mask) != len) + return BadLength; + return ConfigureWindow(pWin, (Mask)stuff->mask, (XID *) &stuff[1], client); +} + +int +ProcCirculateWindow(ClientPtr client) +{ + WindowPtr pWin; + REQUEST(xCirculateWindowReq); + int rc; + + REQUEST_SIZE_MATCH(xCirculateWindowReq); + if ((stuff->direction != RaiseLowest) && + (stuff->direction != LowerHighest)) + { + client->errorValue = stuff->direction; + return BadValue; + } + rc = dixLookupWindow(&pWin, stuff->window, client, DixManageAccess); + if (rc != Success) + return rc; + CirculateWindow(pWin, (int)stuff->direction, client); + return Success; +} + +static int +GetGeometry(ClientPtr client, xGetGeometryReply *rep) +{ + DrawablePtr pDraw; + int rc; + REQUEST(xResourceReq); + REQUEST_SIZE_MATCH(xResourceReq); + + rc = dixLookupDrawable(&pDraw, stuff->id, client, M_ANY, DixGetAttrAccess); + if (rc != Success) + return rc; + + rep->type = X_Reply; + rep->length = 0; + rep->sequenceNumber = client->sequence; + rep->root = pDraw->pScreen->root->drawable.id; + rep->depth = pDraw->depth; + rep->width = pDraw->width; + rep->height = pDraw->height; + + if (WindowDrawable(pDraw->type)) + { + WindowPtr pWin = (WindowPtr)pDraw; + rep->x = pWin->origin.x - wBorderWidth (pWin); + rep->y = pWin->origin.y - wBorderWidth (pWin); + rep->borderWidth = pWin->borderWidth; + } + else /* DRAWABLE_PIXMAP */ + { + rep->x = rep->y = rep->borderWidth = 0; + } + + return Success; +} + + +int +ProcGetGeometry(ClientPtr client) +{ + xGetGeometryReply rep; + int status; + + memset(&rep, 0, sizeof(xGetGeometryReply)); + if ((status = GetGeometry(client, &rep)) != Success) + return status; + + WriteReplyToClient(client, sizeof(xGetGeometryReply), &rep); + return Success; +} + + +int +ProcQueryTree(ClientPtr client) +{ + xQueryTreeReply reply; + int rc, numChildren = 0; + WindowPtr pChild, pWin, pHead; + Window *childIDs = (Window *)NULL; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + rc = dixLookupWindow(&pWin, stuff->id, client, DixListAccess); + if (rc != Success) + return rc; + memset(&reply, 0, sizeof(xQueryTreeReply)); + reply.type = X_Reply; + reply.root = pWin->drawable.pScreen->root->drawable.id; + reply.sequenceNumber = client->sequence; + if (pWin->parent) + reply.parent = pWin->parent->drawable.id; + else + reply.parent = (Window)None; + pHead = RealChildHead(pWin); + for (pChild = pWin->lastChild; pChild != pHead; pChild = pChild->prevSib) + numChildren++; + if (numChildren) + { + int curChild = 0; + + childIDs = malloc(numChildren * sizeof(Window)); + if (!childIDs) + return BadAlloc; + for (pChild = pWin->lastChild; pChild != pHead; pChild = pChild->prevSib) + childIDs[curChild++] = pChild->drawable.id; + } + + reply.nChildren = numChildren; + reply.length = bytes_to_int32(numChildren * sizeof(Window)); + + WriteReplyToClient(client, sizeof(xQueryTreeReply), &reply); + if (numChildren) + { + client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write; + WriteSwappedDataToClient(client, numChildren * sizeof(Window), childIDs); + free(childIDs); + } + + return Success; +} + +int +ProcInternAtom(ClientPtr client) +{ + Atom atom; + char *tchar; + REQUEST(xInternAtomReq); + + REQUEST_FIXED_SIZE(xInternAtomReq, stuff->nbytes); + if ((stuff->onlyIfExists != xTrue) && (stuff->onlyIfExists != xFalse)) + { + client->errorValue = stuff->onlyIfExists; + return BadValue; + } + tchar = (char *) &stuff[1]; + atom = MakeAtom(tchar, stuff->nbytes, !stuff->onlyIfExists); + if (atom != BAD_RESOURCE) + { + xInternAtomReply reply; + memset(&reply, 0, sizeof(xInternAtomReply)); + reply.type = X_Reply; + reply.length = 0; + reply.sequenceNumber = client->sequence; + reply.atom = atom; + WriteReplyToClient(client, sizeof(xInternAtomReply), &reply); + return Success; + } + else + return BadAlloc; +} + +int +ProcGetAtomName(ClientPtr client) +{ + const char *str; + xGetAtomNameReply reply; + int len; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + if ( (str = NameForAtom(stuff->id)) ) + { + len = strlen(str); + memset(&reply, 0, sizeof(xGetAtomNameReply)); + reply.type = X_Reply; + reply.length = bytes_to_int32(len); + reply.sequenceNumber = client->sequence; + reply.nameLength = len; + WriteReplyToClient(client, sizeof(xGetAtomNameReply), &reply); + (void)WriteToClient(client, len, str); + return Success; + } + else + { + client->errorValue = stuff->id; + return BadAtom; + } +} + +int +ProcGrabServer(ClientPtr client) +{ + int rc; + REQUEST_SIZE_MATCH(xReq); + if (grabState != GrabNone && client != grabClient) + { + ResetCurrentRequest(client); + client->sequence--; + BITSET(grabWaiters, client->index); + IgnoreClient(client); + return Success; + } + rc = OnlyListenToOneClient(client); + if (rc != Success) + return rc; + grabState = GrabKickout; + grabClient = client; + + if (ServerGrabCallback) + { + ServerGrabInfoRec grabinfo; + grabinfo.client = client; + grabinfo.grabstate = SERVER_GRABBED; + CallCallbacks(&ServerGrabCallback, (pointer)&grabinfo); + } + + return Success; +} + +static void +UngrabServer(ClientPtr client) +{ + int i; + + grabState = GrabNone; + ListenToAllClients(); + for (i = mskcnt; --i >= 0 && !grabWaiters[i]; ) + ; + if (i >= 0) + { + i <<= 5; + while (!GETBIT(grabWaiters, i)) + i++; + BITCLEAR(grabWaiters, i); + AttendClient(clients[i]); + } + + if (ServerGrabCallback) + { + ServerGrabInfoRec grabinfo; + grabinfo.client = client; + grabinfo.grabstate = SERVER_UNGRABBED; + CallCallbacks(&ServerGrabCallback, (pointer)&grabinfo); + } +} + +int +ProcUngrabServer(ClientPtr client) +{ + REQUEST_SIZE_MATCH(xReq); + UngrabServer(client); + return Success; +} + +int +ProcTranslateCoords(ClientPtr client) +{ + REQUEST(xTranslateCoordsReq); + + WindowPtr pWin, pDst; + xTranslateCoordsReply rep; + int rc; + + REQUEST_SIZE_MATCH(xTranslateCoordsReq); + rc = dixLookupWindow(&pWin, stuff->srcWid, client, DixGetAttrAccess); + if (rc != Success) + return rc; + rc = dixLookupWindow(&pDst, stuff->dstWid, client, DixGetAttrAccess); + if (rc != Success) + return rc; + memset(&rep, 0, sizeof(xTranslateCoordsReply)); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + if (!SAME_SCREENS(pWin->drawable, pDst->drawable)) + { + rep.sameScreen = xFalse; + rep.child = None; + rep.dstX = rep.dstY = 0; + } + else + { + INT16 x, y; + rep.sameScreen = xTrue; + rep.child = None; + /* computing absolute coordinates -- adjust to destination later */ + x = pWin->drawable.x + stuff->srcX; + y = pWin->drawable.y + stuff->srcY; + pWin = pDst->firstChild; + while (pWin) + { + BoxRec box; + if ((pWin->mapped) && + (x >= pWin->drawable.x - wBorderWidth (pWin)) && + (x < pWin->drawable.x + (int)pWin->drawable.width + + wBorderWidth (pWin)) && + (y >= pWin->drawable.y - wBorderWidth (pWin)) && + (y < pWin->drawable.y + (int)pWin->drawable.height + + wBorderWidth (pWin)) + /* When a window is shaped, a further check + * is made to see if the point is inside + * borderSize + */ + && (!wBoundingShape(pWin) || + RegionContainsPoint(&pWin->borderSize, x, y, &box)) + + && (!wInputShape(pWin) || + RegionContainsPoint(wInputShape(pWin), + x - pWin->drawable.x, + y - pWin->drawable.y, &box)) + ) + { + rep.child = pWin->drawable.id; + pWin = (WindowPtr) NULL; + } + else + pWin = pWin->nextSib; + } + /* adjust to destination coordinates */ + rep.dstX = x - pDst->drawable.x; + rep.dstY = y - pDst->drawable.y; + } + WriteReplyToClient(client, sizeof(xTranslateCoordsReply), &rep); + return Success; +} + +int +ProcOpenFont(ClientPtr client) +{ + int err; + REQUEST(xOpenFontReq); + + REQUEST_FIXED_SIZE(xOpenFontReq, stuff->nbytes); + client->errorValue = stuff->fid; + LEGAL_NEW_RESOURCE(stuff->fid, client); + err = OpenFont(client, stuff->fid, (Mask) 0, + stuff->nbytes, (char *)&stuff[1]); + if (err == Success) + { + return Success; + } + else + return err; +} + +int +ProcCloseFont(ClientPtr client) +{ + FontPtr pFont; + int rc; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + rc = dixLookupResourceByType((pointer *)&pFont, stuff->id, RT_FONT, + client, DixDestroyAccess); + if (rc == Success) + { + FreeResource(stuff->id, RT_NONE); + return Success; + } + else + { + client->errorValue = stuff->id; + return rc; + } +} + +int +ProcQueryFont(ClientPtr client) +{ + xQueryFontReply *reply; + FontPtr pFont; + int rc; + REQUEST(xResourceReq); + REQUEST_SIZE_MATCH(xResourceReq); + + rc = dixLookupFontable(&pFont, stuff->id, client, DixGetAttrAccess); + if (rc != Success) + return rc; + + { + xCharInfo *pmax = FONTINKMAX(pFont); + xCharInfo *pmin = FONTINKMIN(pFont); + int nprotoxcistructs; + int rlength; + + nprotoxcistructs = ( + pmax->rightSideBearing == pmin->rightSideBearing && + pmax->leftSideBearing == pmin->leftSideBearing && + pmax->descent == pmin->descent && + pmax->ascent == pmin->ascent && + pmax->characterWidth == pmin->characterWidth) ? + 0 : N2dChars(pFont); + + rlength = sizeof(xQueryFontReply) + + FONTINFONPROPS(FONTCHARSET(pFont)) * sizeof(xFontProp) + + nprotoxcistructs * sizeof(xCharInfo); + reply = calloc(1, rlength); + if(!reply) + { + return BadAlloc; + } + + reply->type = X_Reply; + reply->length = bytes_to_int32(rlength - sizeof(xGenericReply)); + reply->sequenceNumber = client->sequence; + QueryFont( pFont, reply, nprotoxcistructs); + + WriteReplyToClient(client, rlength, reply); + free(reply); + return Success; + } +} + +int +ProcQueryTextExtents(ClientPtr client) +{ + xQueryTextExtentsReply reply; + FontPtr pFont; + ExtentInfoRec info; + unsigned long length; + int rc; + REQUEST(xQueryTextExtentsReq); + REQUEST_AT_LEAST_SIZE(xQueryTextExtentsReq); + + rc = dixLookupFontable(&pFont, stuff->fid, client, DixGetAttrAccess); + if (rc != Success) + return rc; + + length = client->req_len - bytes_to_int32(sizeof(xQueryTextExtentsReq)); + length = length << 1; + if (stuff->oddLength) + { + if (length == 0) + return BadLength; + length--; + } + if (!QueryTextExtents(pFont, length, (unsigned char *)&stuff[1], &info)) + return BadAlloc; + reply.type = X_Reply; + reply.length = 0; + reply.sequenceNumber = client->sequence; + reply.drawDirection = info.drawDirection; + reply.fontAscent = info.fontAscent; + reply.fontDescent = info.fontDescent; + reply.overallAscent = info.overallAscent; + reply.overallDescent = info.overallDescent; + reply.overallWidth = info.overallWidth; + reply.overallLeft = info.overallLeft; + reply.overallRight = info.overallRight; + WriteReplyToClient(client, sizeof(xQueryTextExtentsReply), &reply); + return Success; +} + +int +ProcListFonts(ClientPtr client) +{ + REQUEST(xListFontsReq); + + REQUEST_FIXED_SIZE(xListFontsReq, stuff->nbytes); + + return ListFonts(client, (unsigned char *) &stuff[1], stuff->nbytes, + stuff->maxNames); +} + +int +ProcListFontsWithInfo(ClientPtr client) +{ + REQUEST(xListFontsWithInfoReq); + + REQUEST_FIXED_SIZE(xListFontsWithInfoReq, stuff->nbytes); + + return StartListFontsWithInfo(client, stuff->nbytes, + (unsigned char *) &stuff[1], stuff->maxNames); +} + +/** + * + * \param value must conform to DeleteType + */ +int +dixDestroyPixmap(pointer value, XID pid) +{ + PixmapPtr pPixmap = (PixmapPtr)value; + return (*pPixmap->drawable.pScreen->DestroyPixmap)(pPixmap); +} + +int +ProcCreatePixmap(ClientPtr client) +{ + PixmapPtr pMap; + DrawablePtr pDraw; + REQUEST(xCreatePixmapReq); + DepthPtr pDepth; + int i, rc; + + REQUEST_SIZE_MATCH(xCreatePixmapReq); + client->errorValue = stuff->pid; + LEGAL_NEW_RESOURCE(stuff->pid, client); + + rc = dixLookupDrawable(&pDraw, stuff->drawable, client, M_ANY, + DixGetAttrAccess); + if (rc != Success) + return rc; + + if (!stuff->width || !stuff->height) + { + client->errorValue = 0; + return BadValue; + } + if (stuff->width > 32767 || stuff->height > 32767) + { + /* It is allowed to try and allocate a pixmap which is larger than + * 32767 in either dimension. However, all of the framebuffer code + * is buggy and does not reliably draw to such big pixmaps, basically + * because the Region data structure operates with signed shorts + * for the rectangles in it. + * + * Furthermore, several places in the X server computes the + * size in bytes of the pixmap and tries to store it in an + * integer. This integer can overflow and cause the allocated size + * to be much smaller. + * + * So, such big pixmaps are rejected here with a BadAlloc + */ + return BadAlloc; + } + if (stuff->depth != 1) + { + pDepth = pDraw->pScreen->allowedDepths; + for (i=0; i<pDraw->pScreen->numDepths; i++, pDepth++) + if (pDepth->depth == stuff->depth) + goto CreatePmap; + client->errorValue = stuff->depth; + return BadValue; + } +CreatePmap: + pMap = (PixmapPtr)(*pDraw->pScreen->CreatePixmap) + (pDraw->pScreen, stuff->width, + stuff->height, stuff->depth, 0); + if (pMap) + { + pMap->drawable.serialNumber = NEXT_SERIAL_NUMBER; + pMap->drawable.id = stuff->pid; + /* security creation/labeling check */ + rc = XaceHook(XACE_RESOURCE_ACCESS, client, stuff->pid, RT_PIXMAP, + pMap, RT_NONE, NULL, DixCreateAccess); + if (rc != Success) { + (*pDraw->pScreen->DestroyPixmap)(pMap); + return rc; + } + if (AddResource(stuff->pid, RT_PIXMAP, (pointer)pMap)) + return Success; + (*pDraw->pScreen->DestroyPixmap)(pMap); + } + return BadAlloc; +} + +int +ProcFreePixmap(ClientPtr client) +{ + PixmapPtr pMap; + int rc; + REQUEST(xResourceReq); + REQUEST_SIZE_MATCH(xResourceReq); + + rc = dixLookupResourceByType((pointer *)&pMap, stuff->id, RT_PIXMAP, client, + DixDestroyAccess); + if (rc == Success) + { + FreeResource(stuff->id, RT_NONE); + return Success; + } + else + { + client->errorValue = stuff->id; + return rc; + } +} + +int +ProcCreateGC(ClientPtr client) +{ + int error, rc; + GC *pGC; + DrawablePtr pDraw; + unsigned len; + REQUEST(xCreateGCReq); + + REQUEST_AT_LEAST_SIZE(xCreateGCReq); + client->errorValue = stuff->gc; + LEGAL_NEW_RESOURCE(stuff->gc, client); + rc = dixLookupDrawable(&pDraw, stuff->drawable, client, 0, + DixGetAttrAccess); + if (rc != Success) + return rc; + + len = client->req_len - bytes_to_int32(sizeof(xCreateGCReq)); + if (len != Ones(stuff->mask)) + return BadLength; + pGC = (GC *)CreateGC(pDraw, stuff->mask, (XID *) &stuff[1], &error, + stuff->gc, client); + if (error != Success) + return error; + if (!AddResource(stuff->gc, RT_GC, (pointer)pGC)) + return BadAlloc; + return Success; +} + +int +ProcChangeGC(ClientPtr client) +{ + GC *pGC; + int result; + unsigned len; + REQUEST(xChangeGCReq); + REQUEST_AT_LEAST_SIZE(xChangeGCReq); + + result = dixLookupGC(&pGC, stuff->gc, client, DixSetAttrAccess); + if (result != Success) + return result; + + len = client->req_len - bytes_to_int32(sizeof(xChangeGCReq)); + if (len != Ones(stuff->mask)) + return BadLength; + + return ChangeGCXIDs(client, pGC, stuff->mask, (CARD32 *) &stuff[1]); +} + +int +ProcCopyGC(ClientPtr client) +{ + GC *dstGC; + GC *pGC; + int result; + REQUEST(xCopyGCReq); + REQUEST_SIZE_MATCH(xCopyGCReq); + + result = dixLookupGC(&pGC, stuff->srcGC, client, DixGetAttrAccess); + if (result != Success) + return result; + result = dixLookupGC(&dstGC, stuff->dstGC, client, DixSetAttrAccess); + if (result != Success) + return result; + if ((dstGC->pScreen != pGC->pScreen) || (dstGC->depth != pGC->depth)) + return BadMatch; + if (stuff->mask & ~GCAllBits) + { + client->errorValue = stuff->mask; + return BadValue; + } + return CopyGC(pGC, dstGC, stuff->mask); +} + +int +ProcSetDashes(ClientPtr client) +{ + GC *pGC; + int result; + REQUEST(xSetDashesReq); + + REQUEST_FIXED_SIZE(xSetDashesReq, stuff->nDashes); + if (stuff->nDashes == 0) + { + client->errorValue = 0; + return BadValue; + } + + result = dixLookupGC(&pGC,stuff->gc, client, DixSetAttrAccess); + if (result != Success) + return result; + + /* If there's an error, either there's no sensible errorValue, + * or there was a dash segment of 0. */ + client->errorValue = 0; + return SetDashes(pGC, stuff->dashOffset, stuff->nDashes, + (unsigned char *)&stuff[1]); +} + +int +ProcSetClipRectangles(ClientPtr client) +{ + int nr, result; + GC *pGC; + REQUEST(xSetClipRectanglesReq); + + REQUEST_AT_LEAST_SIZE(xSetClipRectanglesReq); + if ((stuff->ordering != Unsorted) && (stuff->ordering != YSorted) && + (stuff->ordering != YXSorted) && (stuff->ordering != YXBanded)) + { + client->errorValue = stuff->ordering; + return BadValue; + } + result = dixLookupGC(&pGC,stuff->gc, client, DixSetAttrAccess); + if (result != Success) + return result; + + nr = (client->req_len << 2) - sizeof(xSetClipRectanglesReq); + if (nr & 4) + return BadLength; + nr >>= 3; + return SetClipRects(pGC, stuff->xOrigin, stuff->yOrigin, + nr, (xRectangle *)&stuff[1], (int)stuff->ordering); +} + +int +ProcFreeGC(ClientPtr client) +{ + GC *pGC; + int rc; + REQUEST(xResourceReq); + REQUEST_SIZE_MATCH(xResourceReq); + + rc = dixLookupGC(&pGC, stuff->id, client, DixDestroyAccess); + if (rc != Success) + return rc; + + FreeResource(stuff->id, RT_NONE); + return Success; +} + +int +ProcClearToBackground(ClientPtr client) +{ + REQUEST(xClearAreaReq); + WindowPtr pWin; + int rc; + + REQUEST_SIZE_MATCH(xClearAreaReq); + rc = dixLookupWindow(&pWin, stuff->window, client, DixWriteAccess); + if (rc != Success) + return rc; + if (pWin->drawable.class == InputOnly) + { + client->errorValue = stuff->window; + return BadMatch; + } + if ((stuff->exposures != xTrue) && (stuff->exposures != xFalse)) + { + client->errorValue = stuff->exposures; + return BadValue; + } + (*pWin->drawable.pScreen->ClearToBackground)(pWin, stuff->x, stuff->y, + stuff->width, stuff->height, + (Bool)stuff->exposures); + return Success; +} + +int +ProcCopyArea(ClientPtr client) +{ + DrawablePtr pDst; + DrawablePtr pSrc; + GC *pGC; + REQUEST(xCopyAreaReq); + RegionPtr pRgn; + int rc; + + REQUEST_SIZE_MATCH(xCopyAreaReq); + + VALIDATE_DRAWABLE_AND_GC(stuff->dstDrawable, pDst, DixWriteAccess); + if (stuff->dstDrawable != stuff->srcDrawable) + { + rc = dixLookupDrawable(&pSrc, stuff->srcDrawable, client, 0, + DixReadAccess); + if (rc != Success) + return rc; + if ((pDst->pScreen != pSrc->pScreen) || (pDst->depth != pSrc->depth)) + { + client->errorValue = stuff->dstDrawable; + return BadMatch; + } + } + else + pSrc = pDst; + + pRgn = (*pGC->ops->CopyArea)(pSrc, pDst, pGC, stuff->srcX, stuff->srcY, + stuff->width, stuff->height, + stuff->dstX, stuff->dstY); + if (pGC->graphicsExposures) + { + (*pDst->pScreen->SendGraphicsExpose) + (client, pRgn, stuff->dstDrawable, X_CopyArea, 0); + if (pRgn) + RegionDestroy(pRgn); + } + + return Success; +} + +int +ProcCopyPlane(ClientPtr client) +{ + DrawablePtr psrcDraw, pdstDraw; + GC *pGC; + REQUEST(xCopyPlaneReq); + RegionPtr pRgn; + int rc; + + REQUEST_SIZE_MATCH(xCopyPlaneReq); + + VALIDATE_DRAWABLE_AND_GC(stuff->dstDrawable, pdstDraw, DixWriteAccess); + if (stuff->dstDrawable != stuff->srcDrawable) + { + rc = dixLookupDrawable(&psrcDraw, stuff->srcDrawable, client, 0, + DixReadAccess); + if (rc != Success) + return rc; + + if (pdstDraw->pScreen != psrcDraw->pScreen) + { + client->errorValue = stuff->dstDrawable; + return BadMatch; + } + } + else + psrcDraw = pdstDraw; + + /* Check to see if stuff->bitPlane has exactly ONE good bit set */ + if(stuff->bitPlane == 0 || (stuff->bitPlane & (stuff->bitPlane - 1)) || + (stuff->bitPlane > (1L << (psrcDraw->depth - 1)))) + { + client->errorValue = stuff->bitPlane; + return BadValue; + } + + pRgn = (*pGC->ops->CopyPlane)(psrcDraw, pdstDraw, pGC, stuff->srcX, stuff->srcY, + stuff->width, stuff->height, + stuff->dstX, stuff->dstY, stuff->bitPlane); + if (pGC->graphicsExposures) + { + (*pdstDraw->pScreen->SendGraphicsExpose) + (client, pRgn, stuff->dstDrawable, X_CopyPlane, 0); + if (pRgn) + RegionDestroy(pRgn); + } + return Success; +} + +int +ProcPolyPoint(ClientPtr client) +{ + int npoint; + GC *pGC; + DrawablePtr pDraw; + REQUEST(xPolyPointReq); + + REQUEST_AT_LEAST_SIZE(xPolyPointReq); + if ((stuff->coordMode != CoordModeOrigin) && + (stuff->coordMode != CoordModePrevious)) + { + client->errorValue = stuff->coordMode; + return BadValue; + } + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess); + npoint = bytes_to_int32((client->req_len << 2) - sizeof(xPolyPointReq)); + if (npoint) + (*pGC->ops->PolyPoint)(pDraw, pGC, stuff->coordMode, npoint, + (xPoint *) &stuff[1]); + return Success; +} + +int +ProcPolyLine(ClientPtr client) +{ + int npoint; + GC *pGC; + DrawablePtr pDraw; + REQUEST(xPolyLineReq); + + REQUEST_AT_LEAST_SIZE(xPolyLineReq); + if ((stuff->coordMode != CoordModeOrigin) && + (stuff->coordMode != CoordModePrevious)) + { + client->errorValue = stuff->coordMode; + return BadValue; + } + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess); + npoint = bytes_to_int32((client->req_len << 2) - sizeof(xPolyLineReq)); + if (npoint > 1) + (*pGC->ops->Polylines)(pDraw, pGC, stuff->coordMode, npoint, + (DDXPointPtr) &stuff[1]); + return Success; +} + +int +ProcPolySegment(ClientPtr client) +{ + int nsegs; + GC *pGC; + DrawablePtr pDraw; + REQUEST(xPolySegmentReq); + + REQUEST_AT_LEAST_SIZE(xPolySegmentReq); + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess); + nsegs = (client->req_len << 2) - sizeof(xPolySegmentReq); + if (nsegs & 4) + return BadLength; + nsegs >>= 3; + if (nsegs) + (*pGC->ops->PolySegment)(pDraw, pGC, nsegs, (xSegment *) &stuff[1]); + return Success; +} + +int +ProcPolyRectangle (ClientPtr client) +{ + int nrects; + GC *pGC; + DrawablePtr pDraw; + REQUEST(xPolyRectangleReq); + + REQUEST_AT_LEAST_SIZE(xPolyRectangleReq); + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess); + nrects = (client->req_len << 2) - sizeof(xPolyRectangleReq); + if (nrects & 4) + return BadLength; + nrects >>= 3; + if (nrects) + (*pGC->ops->PolyRectangle)(pDraw, pGC, + nrects, (xRectangle *) &stuff[1]); + return Success; +} + +int +ProcPolyArc(ClientPtr client) +{ + int narcs; + GC *pGC; + DrawablePtr pDraw; + REQUEST(xPolyArcReq); + + REQUEST_AT_LEAST_SIZE(xPolyArcReq); + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess); + narcs = (client->req_len << 2) - sizeof(xPolyArcReq); + if (narcs % sizeof(xArc)) + return BadLength; + narcs /= sizeof(xArc); + if (narcs) + (*pGC->ops->PolyArc)(pDraw, pGC, narcs, (xArc *) &stuff[1]); + return Success; +} + +int +ProcFillPoly(ClientPtr client) +{ + int things; + GC *pGC; + DrawablePtr pDraw; + REQUEST(xFillPolyReq); + + REQUEST_AT_LEAST_SIZE(xFillPolyReq); + if ((stuff->shape != Complex) && (stuff->shape != Nonconvex) && + (stuff->shape != Convex)) + { + client->errorValue = stuff->shape; + return BadValue; + } + if ((stuff->coordMode != CoordModeOrigin) && + (stuff->coordMode != CoordModePrevious)) + { + client->errorValue = stuff->coordMode; + return BadValue; + } + + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess); + things = bytes_to_int32((client->req_len << 2) - sizeof(xFillPolyReq)); + if (things) + (*pGC->ops->FillPolygon) (pDraw, pGC, stuff->shape, + stuff->coordMode, things, + (DDXPointPtr) &stuff[1]); + return Success; +} + +int +ProcPolyFillRectangle(ClientPtr client) +{ + int things; + GC *pGC; + DrawablePtr pDraw; + REQUEST(xPolyFillRectangleReq); + + REQUEST_AT_LEAST_SIZE(xPolyFillRectangleReq); + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess); + things = (client->req_len << 2) - sizeof(xPolyFillRectangleReq); + if (things & 4) + return BadLength; + things >>= 3; + + if (things) + (*pGC->ops->PolyFillRect) (pDraw, pGC, things, + (xRectangle *) &stuff[1]); + return Success; +} + +int +ProcPolyFillArc(ClientPtr client) +{ + int narcs; + GC *pGC; + DrawablePtr pDraw; + REQUEST(xPolyFillArcReq); + + REQUEST_AT_LEAST_SIZE(xPolyFillArcReq); + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess); + narcs = (client->req_len << 2) - sizeof(xPolyFillArcReq); + if (narcs % sizeof(xArc)) + return BadLength; + narcs /= sizeof(xArc); + if (narcs) + (*pGC->ops->PolyFillArc) (pDraw, pGC, narcs, (xArc *) &stuff[1]); + return Success; +} + +#ifdef MATCH_CLIENT_ENDIAN + +int +ServerOrder (void) +{ + int whichbyte = 1; + + if (*((char *) &whichbyte)) + return LSBFirst; + return MSBFirst; +} + +#define ClientOrder(client) ((client)->swapped ? !ServerOrder() : ServerOrder()) + +void +ReformatImage (char *base, int nbytes, int bpp, int order) +{ + switch (bpp) { + case 1: /* yuck */ + if (BITMAP_BIT_ORDER != order) + BitOrderInvert ((unsigned char *) base, nbytes); +#if IMAGE_BYTE_ORDER != BITMAP_BIT_ORDER && BITMAP_SCANLINE_UNIT != 8 + ReformatImage (base, nbytes, BITMAP_SCANLINE_UNIT, order); +#endif + break; + case 4: + break; /* yuck */ + case 8: + break; + case 16: + if (IMAGE_BYTE_ORDER != order) + TwoByteSwap ((unsigned char *) base, nbytes); + break; + case 32: + if (IMAGE_BYTE_ORDER != order) + FourByteSwap ((unsigned char *) base, nbytes); + break; + } +} +#else +#define ReformatImage(b,n,bpp,o) +#endif + +/* 64-bit server notes: the protocol restricts padding of images to + * 8-, 16-, or 32-bits. We would like to have 64-bits for the server + * to use internally. Removes need for internal alignment checking. + * All of the PutImage functions could be changed individually, but + * as currently written, they call other routines which require things + * to be 64-bit padded on scanlines, so we changed things here. + * If an image would be padded differently for 64- versus 32-, then + * copy each scanline to a 64-bit padded scanline. + * Also, we need to make sure that the image is aligned on a 64-bit + * boundary, even if the scanlines are padded to our satisfaction. + */ +int +ProcPutImage(ClientPtr client) +{ + GC *pGC; + DrawablePtr pDraw; + long length; /* length of scanline server padded */ + long lengthProto; /* length of scanline protocol padded */ + char *tmpImage; + REQUEST(xPutImageReq); + + REQUEST_AT_LEAST_SIZE(xPutImageReq); + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess); + if (stuff->format == XYBitmap) + { + if ((stuff->depth != 1) || + (stuff->leftPad >= (unsigned int)screenInfo.bitmapScanlinePad)) + return BadMatch; + length = BitmapBytePad(stuff->width + stuff->leftPad); + } + else if (stuff->format == XYPixmap) + { + if ((pDraw->depth != stuff->depth) || + (stuff->leftPad >= (unsigned int)screenInfo.bitmapScanlinePad)) + return BadMatch; + length = BitmapBytePad(stuff->width + stuff->leftPad); + length *= stuff->depth; + } + else if (stuff->format == ZPixmap) + { + if ((pDraw->depth != stuff->depth) || (stuff->leftPad != 0)) + return BadMatch; + length = PixmapBytePad(stuff->width, stuff->depth); + } + else + { + client->errorValue = stuff->format; + return BadValue; + } + + tmpImage = (char *)&stuff[1]; + lengthProto = length; + + if ((bytes_to_int32(lengthProto * stuff->height) + + bytes_to_int32(sizeof(xPutImageReq))) != client->req_len) + return BadLength; + + ReformatImage (tmpImage, lengthProto * stuff->height, + stuff->format == ZPixmap ? BitsPerPixel (stuff->depth) : 1, + ClientOrder(client)); + + (*pGC->ops->PutImage) (pDraw, pGC, stuff->depth, stuff->dstX, stuff->dstY, + stuff->width, stuff->height, + stuff->leftPad, stuff->format, tmpImage); + + return Success; +} + +static int +DoGetImage(ClientPtr client, int format, Drawable drawable, + int x, int y, int width, int height, + Mask planemask, xGetImageReply **im_return) +{ + DrawablePtr pDraw, pBoundingDraw; + int nlines, linesPerBuf, rc; + int linesDone; + /* coordinates relative to the bounding drawable */ + int relx, rely; + long widthBytesLine, length; + Mask plane = 0; + char *pBuf; + xGetImageReply xgi; + RegionPtr pVisibleRegion = NULL; + + if ((format != XYPixmap) && (format != ZPixmap)) + { + client->errorValue = format; + return BadValue; + } + rc = dixLookupDrawable(&pDraw, drawable, client, 0, DixReadAccess); + if (rc != Success) + return rc; + + memset(&xgi, 0, sizeof(xGetImageReply)); + + relx = x; + rely = y; + + if(pDraw->type == DRAWABLE_WINDOW) + { + WindowPtr pWin = (WindowPtr)pDraw; + + /* "If the drawable is a window, the window must be viewable ... or a + * BadMatch error results" */ + if (!pWin->viewable) + return BadMatch; + + relx += pDraw->x; + rely += pDraw->y; + + if (pDraw->pScreen->GetWindowPixmap) { + PixmapPtr pPix = (*pDraw->pScreen->GetWindowPixmap) (pWin); + + pBoundingDraw = &pPix->drawable; +#ifdef COMPOSITE + relx -= pPix->screen_x; + rely -= pPix->screen_y; +#endif + } + else + { + pBoundingDraw = (DrawablePtr)pDraw->pScreen->root; + } + + xgi.visual = wVisual (pWin); + } + else + { + pBoundingDraw = pDraw; + xgi.visual = None; + } + + /* "If the drawable is a pixmap, the given rectangle must be wholly + * contained within the pixmap, or a BadMatch error results. If the + * drawable is a window [...] it must be the case that if there were no + * inferiors or overlapping windows, the specified rectangle of the window + * would be fully visible on the screen and wholly contained within the + * outside edges of the window, or a BadMatch error results." + * + * We relax the window case slightly to mean that the rectangle must exist + * within the bounds of the window's backing pixmap. In particular, this + * means that a GetImage request may succeed or fail with BadMatch depending + * on whether any of its ancestor windows are redirected. */ + if(relx < 0 || relx + width > (int)pBoundingDraw->width || + rely < 0 || rely + height > (int)pBoundingDraw->height) + return BadMatch; + + xgi.type = X_Reply; + xgi.sequenceNumber = client->sequence; + xgi.depth = pDraw->depth; + if(format == ZPixmap) + { + widthBytesLine = PixmapBytePad(width, pDraw->depth); + length = widthBytesLine * height; + + } + else + { + widthBytesLine = BitmapBytePad(width); + plane = ((Mask)1) << (pDraw->depth - 1); + /* only planes asked for */ + length = widthBytesLine * height * + Ones(planemask & (plane | (plane - 1))); + + } + + xgi.length = length; + + if (im_return) { + pBuf = calloc(1, sz_xGetImageReply + length); + if (!pBuf) + return BadAlloc; + if (widthBytesLine == 0) + linesPerBuf = 0; + else + linesPerBuf = height; + *im_return = (xGetImageReply *)pBuf; + *(xGetImageReply *)pBuf = xgi; + pBuf += sz_xGetImageReply; + } else { + xgi.length = bytes_to_int32(xgi.length); + if (widthBytesLine == 0 || height == 0) + linesPerBuf = 0; + else if (widthBytesLine >= IMAGE_BUFSIZE) + linesPerBuf = 1; + else + { + linesPerBuf = IMAGE_BUFSIZE / widthBytesLine; + if (linesPerBuf > height) + linesPerBuf = height; + } + length = linesPerBuf * widthBytesLine; + if (linesPerBuf < height) + { + /* we have to make sure intermediate buffers don't need padding */ + while ((linesPerBuf > 1) && + (length & ((1L << LOG2_BYTES_PER_SCANLINE_PAD)-1))) + { + linesPerBuf--; + length -= widthBytesLine; + } + while (length & ((1L << LOG2_BYTES_PER_SCANLINE_PAD)-1)) + { + linesPerBuf++; + length += widthBytesLine; + } + } + if(!(pBuf = calloc(1, length))) + return BadAlloc; + WriteReplyToClient(client, sizeof (xGetImageReply), &xgi); + } + + if (pDraw->type == DRAWABLE_WINDOW) + { + pVisibleRegion = NotClippedByChildren((WindowPtr)pDraw); + if (pVisibleRegion) + { + RegionTranslate(pVisibleRegion, -pDraw->x, -pDraw->y); + } + } + + if (linesPerBuf == 0) + { + /* nothing to do */ + } + else if (format == ZPixmap) + { + linesDone = 0; + while (height - linesDone > 0) + { + nlines = min(linesPerBuf, height - linesDone); + (*pDraw->pScreen->GetImage) (pDraw, + x, + y + linesDone, + width, + nlines, + format, + planemask, + (pointer) pBuf); + if (pVisibleRegion) + XaceCensorImage(client, pVisibleRegion, widthBytesLine, + pDraw, x, y + linesDone, width, + nlines, format, pBuf); + + /* Note that this is NOT a call to WriteSwappedDataToClient, + as we do NOT byte swap */ + if (!im_return) + { + ReformatImage (pBuf, (int)(nlines * widthBytesLine), + BitsPerPixel (pDraw->depth), + ClientOrder(client)); + +/* Don't split me, gcc pukes when you do */ + (void)WriteToClient(client, + (int)(nlines * widthBytesLine), + pBuf); + } + linesDone += nlines; + } + } + else /* XYPixmap */ + { + for (; plane; plane >>= 1) + { + if (planemask & plane) + { + linesDone = 0; + while (height - linesDone > 0) + { + nlines = min(linesPerBuf, height - linesDone); + (*pDraw->pScreen->GetImage) (pDraw, + x, + y + linesDone, + width, + nlines, + format, + plane, + (pointer)pBuf); + if (pVisibleRegion) + XaceCensorImage(client, pVisibleRegion, + widthBytesLine, + pDraw, x, y + linesDone, width, + nlines, format, pBuf); + + /* Note: NOT a call to WriteSwappedDataToClient, + as we do NOT byte swap */ + if (im_return) { + pBuf += nlines * widthBytesLine; + } else { + ReformatImage (pBuf, + (int)(nlines * widthBytesLine), + 1, + ClientOrder (client)); + +/* Don't split me, gcc pukes when you do */ + (void)WriteToClient(client, + (int)(nlines * widthBytesLine), + pBuf); + } + linesDone += nlines; + } + } + } + } + if (pVisibleRegion) + RegionDestroy(pVisibleRegion); + if (!im_return) + free(pBuf); + return Success; +} + +int +ProcGetImage(ClientPtr client) +{ + REQUEST(xGetImageReq); + + REQUEST_SIZE_MATCH(xGetImageReq); + + return DoGetImage(client, stuff->format, stuff->drawable, + stuff->x, stuff->y, + (int)stuff->width, (int)stuff->height, + stuff->planeMask, (xGetImageReply **)NULL); +} + +int +ProcPolyText(ClientPtr client) +{ + int err; + REQUEST(xPolyTextReq); + DrawablePtr pDraw; + GC *pGC; + + REQUEST_AT_LEAST_SIZE(xPolyTextReq); + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess); + + err = PolyText(client, + pDraw, + pGC, + (unsigned char *)&stuff[1], + ((unsigned char *) stuff) + (client->req_len << 2), + stuff->x, + stuff->y, + stuff->reqType, + stuff->drawable); + + if (err == Success) + { + return Success; + } + else + return err; +} + +int +ProcImageText8(ClientPtr client) +{ + int err; + DrawablePtr pDraw; + GC *pGC; + + REQUEST(xImageTextReq); + + REQUEST_FIXED_SIZE(xImageTextReq, stuff->nChars); + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess); + + err = ImageText(client, + pDraw, + pGC, + stuff->nChars, + (unsigned char *)&stuff[1], + stuff->x, + stuff->y, + stuff->reqType, + stuff->drawable); + + if (err == Success) + { + return Success; + } + else + return err; +} + +int +ProcImageText16(ClientPtr client) +{ + int err; + DrawablePtr pDraw; + GC *pGC; + + REQUEST(xImageTextReq); + + REQUEST_FIXED_SIZE(xImageTextReq, stuff->nChars << 1); + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess); + + err = ImageText(client, + pDraw, + pGC, + stuff->nChars, + (unsigned char *)&stuff[1], + stuff->x, + stuff->y, + stuff->reqType, + stuff->drawable); + + if (err == Success) + { + return Success; + } + else + return err; +} + + +int +ProcCreateColormap(ClientPtr client) +{ + VisualPtr pVisual; + ColormapPtr pmap; + Colormap mid; + WindowPtr pWin; + ScreenPtr pScreen; + REQUEST(xCreateColormapReq); + int i, result; + + REQUEST_SIZE_MATCH(xCreateColormapReq); + + if ((stuff->alloc != AllocNone) && (stuff->alloc != AllocAll)) + { + client->errorValue = stuff->alloc; + return BadValue; + } + mid = stuff->mid; + LEGAL_NEW_RESOURCE(mid, client); + result = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); + if (result != Success) + return result; + + pScreen = pWin->drawable.pScreen; + for (i = 0, pVisual = pScreen->visuals; + i < pScreen->numVisuals; + i++, pVisual++) + { + if (pVisual->vid != stuff->visual) + continue; + return CreateColormap(mid, pScreen, pVisual, &pmap, + (int)stuff->alloc, client->index); + } + client->errorValue = stuff->visual; + return BadMatch; +} + +int +ProcFreeColormap(ClientPtr client) +{ + ColormapPtr pmap; + int rc; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + rc = dixLookupResourceByType((pointer *)&pmap, stuff->id, RT_COLORMAP, client, + DixDestroyAccess); + if (rc == Success) + { + /* Freeing a default colormap is a no-op */ + if (!(pmap->flags & IsDefault)) + FreeResource(stuff->id, RT_NONE); + return Success; + } + else + { + client->errorValue = stuff->id; + return rc; + } +} + + +int +ProcCopyColormapAndFree(ClientPtr client) +{ + Colormap mid; + ColormapPtr pSrcMap; + REQUEST(xCopyColormapAndFreeReq); + int rc; + + REQUEST_SIZE_MATCH(xCopyColormapAndFreeReq); + mid = stuff->mid; + LEGAL_NEW_RESOURCE(mid, client); + rc = dixLookupResourceByType((pointer *)&pSrcMap, stuff->srcCmap, RT_COLORMAP, + client, DixReadAccess|DixRemoveAccess); + if (rc == Success) + return CopyColormapAndFree(mid, pSrcMap, client->index); + client->errorValue = stuff->srcCmap; + return rc; +} + +int +ProcInstallColormap(ClientPtr client) +{ + ColormapPtr pcmp; + int rc; + REQUEST(xResourceReq); + REQUEST_SIZE_MATCH(xResourceReq); + + rc = dixLookupResourceByType((pointer *)&pcmp, stuff->id, RT_COLORMAP, client, + DixInstallAccess); + if (rc != Success) + goto out; + + rc = XaceHook(XACE_SCREEN_ACCESS, client, pcmp->pScreen, DixSetAttrAccess); + if (rc != Success) { + if (rc == BadValue) + rc = BadColor; + goto out; + } + + (*(pcmp->pScreen->InstallColormap)) (pcmp); + return Success; + +out: + client->errorValue = stuff->id; + return rc; +} + +int +ProcUninstallColormap(ClientPtr client) +{ + ColormapPtr pcmp; + int rc; + REQUEST(xResourceReq); + REQUEST_SIZE_MATCH(xResourceReq); + + rc = dixLookupResourceByType((pointer *)&pcmp, stuff->id, RT_COLORMAP, client, + DixUninstallAccess); + if (rc != Success) + goto out; + + rc = XaceHook(XACE_SCREEN_ACCESS, client, pcmp->pScreen, DixSetAttrAccess); + if (rc != Success) { + if (rc == BadValue) + rc = BadColor; + goto out; + } + + if(pcmp->mid != pcmp->pScreen->defColormap) + (*(pcmp->pScreen->UninstallColormap)) (pcmp); + return Success; + +out: + client->errorValue = stuff->id; + return rc; +} + +int +ProcListInstalledColormaps(ClientPtr client) +{ + xListInstalledColormapsReply *preply; + int nummaps, rc; + WindowPtr pWin; + REQUEST(xResourceReq); + REQUEST_SIZE_MATCH(xResourceReq); + + rc = dixLookupWindow(&pWin, stuff->id, client, DixGetAttrAccess); + if (rc != Success) + return rc; + + rc = XaceHook(XACE_SCREEN_ACCESS, client, pWin->drawable.pScreen, + DixGetAttrAccess); + if (rc != Success) + return rc; + + preply = malloc(sizeof(xListInstalledColormapsReply) + + pWin->drawable.pScreen->maxInstalledCmaps * + sizeof(Colormap)); + if(!preply) + return BadAlloc; + + preply->type = X_Reply; + preply->sequenceNumber = client->sequence; + nummaps = (*pWin->drawable.pScreen->ListInstalledColormaps) + (pWin->drawable.pScreen, (Colormap *)&preply[1]); + preply->nColormaps = nummaps; + preply->length = nummaps; + WriteReplyToClient(client, sizeof (xListInstalledColormapsReply), preply); + client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write; + WriteSwappedDataToClient(client, nummaps * sizeof(Colormap), &preply[1]); + free(preply); + return Success; +} + +int +ProcAllocColor (ClientPtr client) +{ + ColormapPtr pmap; + int rc; + xAllocColorReply acr; + REQUEST(xAllocColorReq); + + REQUEST_SIZE_MATCH(xAllocColorReq); + rc = dixLookupResourceByType((pointer *)&pmap, stuff->cmap, RT_COLORMAP, client, + DixAddAccess); + if (rc == Success) + { + acr.type = X_Reply; + acr.length = 0; + acr.sequenceNumber = client->sequence; + acr.red = stuff->red; + acr.green = stuff->green; + acr.blue = stuff->blue; + acr.pixel = 0; + if( (rc = AllocColor(pmap, &acr.red, &acr.green, &acr.blue, + &acr.pixel, client->index)) ) + return rc; +#ifdef PANORAMIX + if (noPanoramiXExtension || !pmap->pScreen->myNum) +#endif + WriteReplyToClient(client, sizeof(xAllocColorReply), &acr); + return Success; + + } + else + { + client->errorValue = stuff->cmap; + return rc; + } +} + +int +ProcAllocNamedColor (ClientPtr client) +{ + ColormapPtr pcmp; + int rc; + REQUEST(xAllocNamedColorReq); + + REQUEST_FIXED_SIZE(xAllocNamedColorReq, stuff->nbytes); + rc = dixLookupResourceByType((pointer *)&pcmp, stuff->cmap, RT_COLORMAP, client, + DixAddAccess); + if (rc == Success) + { + xAllocNamedColorReply ancr; + + ancr.type = X_Reply; + ancr.length = 0; + ancr.sequenceNumber = client->sequence; + + if(OsLookupColor(pcmp->pScreen->myNum, (char *)&stuff[1], stuff->nbytes, + &ancr.exactRed, &ancr.exactGreen, &ancr.exactBlue)) + { + ancr.screenRed = ancr.exactRed; + ancr.screenGreen = ancr.exactGreen; + ancr.screenBlue = ancr.exactBlue; + ancr.pixel = 0; + if( (rc = AllocColor(pcmp, + &ancr.screenRed, &ancr.screenGreen, &ancr.screenBlue, + &ancr.pixel, client->index)) ) + return rc; +#ifdef PANORAMIX + if (noPanoramiXExtension || !pcmp->pScreen->myNum) +#endif + WriteReplyToClient(client, sizeof (xAllocNamedColorReply), &ancr); + return Success; + } + else + return BadName; + + } + else + { + client->errorValue = stuff->cmap; + return rc; + } +} + +int +ProcAllocColorCells (ClientPtr client) +{ + ColormapPtr pcmp; + int rc; + REQUEST(xAllocColorCellsReq); + + REQUEST_SIZE_MATCH(xAllocColorCellsReq); + rc = dixLookupResourceByType((pointer *)&pcmp, stuff->cmap, RT_COLORMAP, client, + DixAddAccess); + if (rc == Success) + { + xAllocColorCellsReply accr; + int npixels, nmasks; + long length; + Pixel *ppixels, *pmasks; + + npixels = stuff->colors; + if (!npixels) + { + client->errorValue = npixels; + return BadValue; + } + if (stuff->contiguous != xTrue && stuff->contiguous != xFalse) + { + client->errorValue = stuff->contiguous; + return BadValue; + } + nmasks = stuff->planes; + length = ((long)npixels + (long)nmasks) * sizeof(Pixel); + ppixels = malloc(length); + if(!ppixels) + return BadAlloc; + pmasks = ppixels + npixels; + + if( (rc = AllocColorCells(client->index, pcmp, npixels, nmasks, + (Bool)stuff->contiguous, ppixels, pmasks)) ) + { + free(ppixels); + return rc; + } +#ifdef PANORAMIX + if (noPanoramiXExtension || !pcmp->pScreen->myNum) +#endif + { + accr.type = X_Reply; + accr.length = bytes_to_int32(length); + accr.sequenceNumber = client->sequence; + accr.nPixels = npixels; + accr.nMasks = nmasks; + WriteReplyToClient(client, sizeof (xAllocColorCellsReply), &accr); + client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write; + WriteSwappedDataToClient(client, length, ppixels); + } + free(ppixels); + return Success; + } + else + { + client->errorValue = stuff->cmap; + return rc; + } +} + +int +ProcAllocColorPlanes(ClientPtr client) +{ + ColormapPtr pcmp; + int rc; + REQUEST(xAllocColorPlanesReq); + + REQUEST_SIZE_MATCH(xAllocColorPlanesReq); + rc = dixLookupResourceByType((pointer *)&pcmp, stuff->cmap, RT_COLORMAP, client, + DixAddAccess); + if (rc == Success) + { + xAllocColorPlanesReply acpr; + int npixels; + long length; + Pixel *ppixels; + + npixels = stuff->colors; + if (!npixels) + { + client->errorValue = npixels; + return BadValue; + } + if (stuff->contiguous != xTrue && stuff->contiguous != xFalse) + { + client->errorValue = stuff->contiguous; + return BadValue; + } + acpr.type = X_Reply; + acpr.sequenceNumber = client->sequence; + acpr.nPixels = npixels; + length = (long)npixels * sizeof(Pixel); + ppixels = malloc(length); + if(!ppixels) + return BadAlloc; + if( (rc = AllocColorPlanes(client->index, pcmp, npixels, + (int)stuff->red, (int)stuff->green, (int)stuff->blue, + (Bool)stuff->contiguous, ppixels, + &acpr.redMask, &acpr.greenMask, &acpr.blueMask)) ) + { + free(ppixels); + return rc; + } + acpr.length = bytes_to_int32(length); +#ifdef PANORAMIX + if (noPanoramiXExtension || !pcmp->pScreen->myNum) +#endif + { + WriteReplyToClient(client, sizeof(xAllocColorPlanesReply), &acpr); + client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write; + WriteSwappedDataToClient(client, length, ppixels); + } + free(ppixels); + return Success; + } + else + { + client->errorValue = stuff->cmap; + return rc; + } +} + +int +ProcFreeColors(ClientPtr client) +{ + ColormapPtr pcmp; + int rc; + REQUEST(xFreeColorsReq); + + REQUEST_AT_LEAST_SIZE(xFreeColorsReq); + rc = dixLookupResourceByType((pointer *)&pcmp, stuff->cmap, RT_COLORMAP, client, + DixRemoveAccess); + if (rc == Success) + { + int count; + + if(pcmp->flags & AllAllocated) + return BadAccess; + count = bytes_to_int32((client->req_len << 2) - sizeof(xFreeColorsReq)); + return FreeColors(pcmp, client->index, count, + (Pixel *)&stuff[1], (Pixel)stuff->planeMask); + } + else + { + client->errorValue = stuff->cmap; + return rc; + } +} + +int +ProcStoreColors (ClientPtr client) +{ + ColormapPtr pcmp; + int rc; + REQUEST(xStoreColorsReq); + + REQUEST_AT_LEAST_SIZE(xStoreColorsReq); + rc = dixLookupResourceByType((pointer *)&pcmp, stuff->cmap, RT_COLORMAP, client, + DixWriteAccess); + if (rc == Success) + { + int count; + + count = (client->req_len << 2) - sizeof(xStoreColorsReq); + if (count % sizeof(xColorItem)) + return BadLength; + count /= sizeof(xColorItem); + return StoreColors(pcmp, count, (xColorItem *)&stuff[1], client); + } + else + { + client->errorValue = stuff->cmap; + return rc; + } +} + +int +ProcStoreNamedColor (ClientPtr client) +{ + ColormapPtr pcmp; + int rc; + REQUEST(xStoreNamedColorReq); + + REQUEST_FIXED_SIZE(xStoreNamedColorReq, stuff->nbytes); + rc = dixLookupResourceByType((pointer *)&pcmp, stuff->cmap, RT_COLORMAP, client, + DixWriteAccess); + if (rc == Success) + { + xColorItem def; + + if(OsLookupColor(pcmp->pScreen->myNum, (char *)&stuff[1], + stuff->nbytes, &def.red, &def.green, &def.blue)) + { + def.flags = stuff->flags; + def.pixel = stuff->pixel; + return StoreColors(pcmp, 1, &def, client); + } + return BadName; + } + else + { + client->errorValue = stuff->cmap; + return rc; + } +} + +int +ProcQueryColors(ClientPtr client) +{ + ColormapPtr pcmp; + int rc; + REQUEST(xQueryColorsReq); + + REQUEST_AT_LEAST_SIZE(xQueryColorsReq); + rc = dixLookupResourceByType((pointer *)&pcmp, stuff->cmap, RT_COLORMAP, client, + DixReadAccess); + if (rc == Success) + { + int count; + xrgb *prgbs; + xQueryColorsReply qcr; + + count = bytes_to_int32((client->req_len << 2) - sizeof(xQueryColorsReq)); + prgbs = calloc(1, count * sizeof(xrgb)); + if(!prgbs && count) + return BadAlloc; + if( (rc = QueryColors(pcmp, count, (Pixel *)&stuff[1], prgbs, client)) ) + { + free(prgbs); + return rc; + } + memset(&qcr, 0, sizeof(xQueryColorsReply)); + qcr.type = X_Reply; + qcr.length = bytes_to_int32(count * sizeof(xrgb)); + qcr.sequenceNumber = client->sequence; + qcr.nColors = count; + WriteReplyToClient(client, sizeof(xQueryColorsReply), &qcr); + if (count) + { + client->pSwapReplyFunc = (ReplySwapPtr) SQColorsExtend; + WriteSwappedDataToClient(client, count * sizeof(xrgb), prgbs); + } + free(prgbs); + return Success; + + } + else + { + client->errorValue = stuff->cmap; + return rc; + } +} + +int +ProcLookupColor(ClientPtr client) +{ + ColormapPtr pcmp; + int rc; + REQUEST(xLookupColorReq); + + REQUEST_FIXED_SIZE(xLookupColorReq, stuff->nbytes); + rc = dixLookupResourceByType((pointer *)&pcmp, stuff->cmap, RT_COLORMAP, client, + DixReadAccess); + if (rc == Success) + { + xLookupColorReply lcr; + + if(OsLookupColor(pcmp->pScreen->myNum, (char *)&stuff[1], stuff->nbytes, + &lcr.exactRed, &lcr.exactGreen, &lcr.exactBlue)) + { + lcr.type = X_Reply; + lcr.length = 0; + lcr.sequenceNumber = client->sequence; + lcr.screenRed = lcr.exactRed; + lcr.screenGreen = lcr.exactGreen; + lcr.screenBlue = lcr.exactBlue; + (*pcmp->pScreen->ResolveColor)(&lcr.screenRed, + &lcr.screenGreen, + &lcr.screenBlue, + pcmp->pVisual); + WriteReplyToClient(client, sizeof(xLookupColorReply), &lcr); + return Success; + } + return BadName; + } + else + { + client->errorValue = stuff->cmap; + return rc; + } +} + +int +ProcCreateCursor (ClientPtr client) +{ + CursorPtr pCursor; + PixmapPtr src; + PixmapPtr msk; + unsigned char * srcbits; + unsigned char * mskbits; + unsigned short width, height; + long n; + CursorMetricRec cm; + int rc; + + REQUEST(xCreateCursorReq); + + REQUEST_SIZE_MATCH(xCreateCursorReq); + LEGAL_NEW_RESOURCE(stuff->cid, client); + + rc = dixLookupResourceByType((pointer *)&src, stuff->source, RT_PIXMAP, client, + DixReadAccess); + if (rc != Success) { + client->errorValue = stuff->source; + return rc; + } + + rc = dixLookupResourceByType((pointer *)&msk, stuff->mask, RT_PIXMAP, client, + DixReadAccess); + if (rc != Success) + { + if (stuff->mask != None) + { + client->errorValue = stuff->mask; + return rc; + } + } + else if ( src->drawable.width != msk->drawable.width + || src->drawable.height != msk->drawable.height + || src->drawable.depth != 1 + || msk->drawable.depth != 1) + return BadMatch; + + width = src->drawable.width; + height = src->drawable.height; + + if ( stuff->x > width + || stuff->y > height ) + return BadMatch; + + n = BitmapBytePad(width)*height; + srcbits = calloc(1, n); + if (!srcbits) + return BadAlloc; + mskbits = malloc(n); + if (!mskbits) + { + free(srcbits); + return BadAlloc; + } + + (* src->drawable.pScreen->GetImage)( (DrawablePtr)src, 0, 0, width, height, + XYPixmap, 1, (pointer)srcbits); + if ( msk == (PixmapPtr)NULL) + { + unsigned char *bits = mskbits; + while (--n >= 0) + *bits++ = ~0; + } + else + { + /* zeroing the (pad) bits helps some ddx cursor handling */ + memset((char *)mskbits, 0, n); + (* msk->drawable.pScreen->GetImage)( (DrawablePtr)msk, 0, 0, width, + height, XYPixmap, 1, (pointer)mskbits); + } + cm.width = width; + cm.height = height; + cm.xhot = stuff->x; + cm.yhot = stuff->y; + rc = AllocARGBCursor(srcbits, mskbits, NULL, &cm, + stuff->foreRed, stuff->foreGreen, stuff->foreBlue, + stuff->backRed, stuff->backGreen, stuff->backBlue, + &pCursor, client, stuff->cid); + + if (rc != Success) + return rc; + if (!AddResource(stuff->cid, RT_CURSOR, (pointer)pCursor)) + return BadAlloc; + + return Success; +} + +int +ProcCreateGlyphCursor (ClientPtr client) +{ + CursorPtr pCursor; + int res; + + REQUEST(xCreateGlyphCursorReq); + + REQUEST_SIZE_MATCH(xCreateGlyphCursorReq); + LEGAL_NEW_RESOURCE(stuff->cid, client); + + res = AllocGlyphCursor(stuff->source, stuff->sourceChar, + stuff->mask, stuff->maskChar, + stuff->foreRed, stuff->foreGreen, stuff->foreBlue, + stuff->backRed, stuff->backGreen, stuff->backBlue, + &pCursor, client, stuff->cid); + if (res != Success) + return res; + if (AddResource(stuff->cid, RT_CURSOR, (pointer)pCursor)) + return Success; + return BadAlloc; +} + + +int +ProcFreeCursor (ClientPtr client) +{ + CursorPtr pCursor; + int rc; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + rc = dixLookupResourceByType((pointer *)&pCursor, stuff->id, RT_CURSOR, client, + DixDestroyAccess); + if (rc == Success) + { + FreeResource(stuff->id, RT_NONE); + return Success; + } + else + { + client->errorValue = stuff->id; + return rc; + } +} + +int +ProcQueryBestSize (ClientPtr client) +{ + xQueryBestSizeReply reply; + DrawablePtr pDraw; + ScreenPtr pScreen; + int rc; + REQUEST(xQueryBestSizeReq); + REQUEST_SIZE_MATCH(xQueryBestSizeReq); + + if ((stuff->class != CursorShape) && + (stuff->class != TileShape) && + (stuff->class != StippleShape)) + { + client->errorValue = stuff->class; + return BadValue; + } + + rc = dixLookupDrawable(&pDraw, stuff->drawable, client, M_ANY, + DixGetAttrAccess); + if (rc != Success) + return rc; + if (stuff->class != CursorShape && pDraw->type == UNDRAWABLE_WINDOW) + return BadMatch; + pScreen = pDraw->pScreen; + rc = XaceHook(XACE_SCREEN_ACCESS, client, pScreen, DixGetAttrAccess); + if (rc != Success) + return rc; + (* pScreen->QueryBestSize)(stuff->class, &stuff->width, + &stuff->height, pScreen); + memset(&reply, 0, sizeof(xQueryBestSizeReply)); + reply.type = X_Reply; + reply.length = 0; + reply.sequenceNumber = client->sequence; + reply.width = stuff->width; + reply.height = stuff->height; + WriteReplyToClient(client, sizeof(xQueryBestSizeReply), &reply); + return Success; +} + + +int +ProcSetScreenSaver (ClientPtr client) +{ + int rc, i, blankingOption, exposureOption; + REQUEST(xSetScreenSaverReq); + REQUEST_SIZE_MATCH(xSetScreenSaverReq); + + for (i = 0; i < screenInfo.numScreens; i++) { + rc = XaceHook(XACE_SCREENSAVER_ACCESS, client, screenInfo.screens[i], + DixSetAttrAccess); + if (rc != Success) + return rc; + } + + blankingOption = stuff->preferBlank; + if ((blankingOption != DontPreferBlanking) && + (blankingOption != PreferBlanking) && + (blankingOption != DefaultBlanking)) + { + client->errorValue = blankingOption; + return BadValue; + } + exposureOption = stuff->allowExpose; + if ((exposureOption != DontAllowExposures) && + (exposureOption != AllowExposures) && + (exposureOption != DefaultExposures)) + { + client->errorValue = exposureOption; + return BadValue; + } + if (stuff->timeout < -1) + { + client->errorValue = stuff->timeout; + return BadValue; + } + if (stuff->interval < -1) + { + client->errorValue = stuff->interval; + return BadValue; + } + + if (blankingOption == DefaultBlanking) + ScreenSaverBlanking = defaultScreenSaverBlanking; + else + ScreenSaverBlanking = blankingOption; + if (exposureOption == DefaultExposures) + ScreenSaverAllowExposures = defaultScreenSaverAllowExposures; + else + ScreenSaverAllowExposures = exposureOption; + + if (stuff->timeout >= 0) + ScreenSaverTime = stuff->timeout * MILLI_PER_SECOND; + else + ScreenSaverTime = defaultScreenSaverTime; + if (stuff->interval >= 0) + ScreenSaverInterval = stuff->interval * MILLI_PER_SECOND; + else + ScreenSaverInterval = defaultScreenSaverInterval; + + SetScreenSaverTimer(); + return Success; +} + +int +ProcGetScreenSaver(ClientPtr client) +{ + xGetScreenSaverReply rep; + int rc, i; + REQUEST_SIZE_MATCH(xReq); + + for (i = 0; i < screenInfo.numScreens; i++) { + rc = XaceHook(XACE_SCREENSAVER_ACCESS, client, screenInfo.screens[i], + DixGetAttrAccess); + if (rc != Success) + return rc; + } + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.timeout = ScreenSaverTime / MILLI_PER_SECOND; + rep.interval = ScreenSaverInterval / MILLI_PER_SECOND; + rep.preferBlanking = ScreenSaverBlanking; + rep.allowExposures = ScreenSaverAllowExposures; + WriteReplyToClient(client, sizeof(xGetScreenSaverReply), &rep); + return Success; +} + +int +ProcChangeHosts(ClientPtr client) +{ + REQUEST(xChangeHostsReq); + + REQUEST_FIXED_SIZE(xChangeHostsReq, stuff->hostLength); + + if(stuff->mode == HostInsert) + return AddHost(client, (int)stuff->hostFamily, + stuff->hostLength, (pointer)&stuff[1]); + if (stuff->mode == HostDelete) + return RemoveHost(client, (int)stuff->hostFamily, + stuff->hostLength, (pointer)&stuff[1]); + client->errorValue = stuff->mode; + return BadValue; +} + +int +ProcListHosts(ClientPtr client) +{ + xListHostsReply reply; + int len, nHosts, result; + pointer pdata; + /* REQUEST(xListHostsReq); */ + + REQUEST_SIZE_MATCH(xListHostsReq); + + /* untrusted clients can't list hosts */ + result = XaceHook(XACE_SERVER_ACCESS, client, DixReadAccess); + if (result != Success) + return result; + + result = GetHosts(&pdata, &nHosts, &len, &reply.enabled); + if (result != Success) + return result; + reply.type = X_Reply; + reply.sequenceNumber = client->sequence; + reply.nHosts = nHosts; + reply.length = bytes_to_int32(len); + WriteReplyToClient(client, sizeof(xListHostsReply), &reply); + if (nHosts) + { + client->pSwapReplyFunc = (ReplySwapPtr) SLHostsExtend; + WriteSwappedDataToClient(client, len, pdata); + } + free(pdata); + return Success; +} + +int +ProcChangeAccessControl(ClientPtr client) +{ + REQUEST(xSetAccessControlReq); + + REQUEST_SIZE_MATCH(xSetAccessControlReq); + if ((stuff->mode != EnableAccess) && (stuff->mode != DisableAccess)) + { + client->errorValue = stuff->mode; + return BadValue; + } + return ChangeAccessControl(client, stuff->mode == EnableAccess); +} + +/********************* + * CloseDownRetainedResources + * + * Find all clients that are gone and have terminated in RetainTemporary + * and destroy their resources. + *********************/ + +static void +CloseDownRetainedResources(void) +{ + int i; + ClientPtr client; + + for (i=1; i<currentMaxClients; i++) + { + client = clients[i]; + if (client && (client->closeDownMode == RetainTemporary) + && (client->clientGone)) + CloseDownClient(client); + } +} + +int +ProcKillClient(ClientPtr client) +{ + REQUEST(xResourceReq); + ClientPtr killclient; + int rc; + + REQUEST_SIZE_MATCH(xResourceReq); + if (stuff->id == AllTemporary) + { + CloseDownRetainedResources(); + return Success; + } + + rc = dixLookupClient(&killclient, stuff->id, client, DixDestroyAccess); + if (rc == Success) { + CloseDownClient(killclient); + /* if an LBX proxy gets killed, isItTimeToYield will be set */ + if (isItTimeToYield || (client == killclient)) + { + /* force yield and return Success, so that Dispatch() + * doesn't try to touch client + */ + isItTimeToYield = TRUE; + return Success; + } + return Success; + } + else + return rc; +} + +int +ProcSetFontPath(ClientPtr client) +{ + unsigned char *ptr; + unsigned long nbytes, total; + long nfonts; + int n; + REQUEST(xSetFontPathReq); + + REQUEST_AT_LEAST_SIZE(xSetFontPathReq); + + nbytes = (client->req_len << 2) - sizeof(xSetFontPathReq); + total = nbytes; + ptr = (unsigned char *)&stuff[1]; + nfonts = stuff->nFonts; + while (--nfonts >= 0) + { + if ((total == 0) || (total < (n = (*ptr + 1)))) + return BadLength; + total -= n; + ptr += n; + } + if (total >= 4) + return BadLength; + return SetFontPath(client, stuff->nFonts, (unsigned char *)&stuff[1]); +} + +int +ProcGetFontPath(ClientPtr client) +{ + xGetFontPathReply reply; + int rc, stringLens, numpaths; + unsigned char *bufferStart; + /* REQUEST (xReq); */ + + REQUEST_SIZE_MATCH(xReq); + rc = GetFontPath(client, &numpaths, &stringLens, &bufferStart); + if (rc != Success) + return rc; + + reply.type = X_Reply; + reply.sequenceNumber = client->sequence; + reply.length = bytes_to_int32(stringLens + numpaths); + reply.nPaths = numpaths; + + WriteReplyToClient(client, sizeof(xGetFontPathReply), &reply); + if (stringLens || numpaths) + (void)WriteToClient(client, stringLens + numpaths, (char *)bufferStart); + return Success; +} + +int +ProcChangeCloseDownMode(ClientPtr client) +{ + int rc; + REQUEST(xSetCloseDownModeReq); + REQUEST_SIZE_MATCH(xSetCloseDownModeReq); + + rc = XaceHook(XACE_CLIENT_ACCESS, client, client, DixManageAccess); + if (rc != Success) + return rc; + + if ((stuff->mode == AllTemporary) || + (stuff->mode == RetainPermanent) || + (stuff->mode == RetainTemporary)) + { + client->closeDownMode = stuff->mode; + return Success; + } + else + { + client->errorValue = stuff->mode; + return BadValue; + } +} + +int ProcForceScreenSaver(ClientPtr client) +{ + int rc; + REQUEST(xForceScreenSaverReq); + + REQUEST_SIZE_MATCH(xForceScreenSaverReq); + + if ((stuff->mode != ScreenSaverReset) && + (stuff->mode != ScreenSaverActive)) + { + client->errorValue = stuff->mode; + return BadValue; + } + rc = dixSaveScreens(client, SCREEN_SAVER_FORCER, (int)stuff->mode); + if (rc != Success) + return rc; + return Success; +} + +int ProcNoOperation(ClientPtr client) +{ + REQUEST_AT_LEAST_SIZE(xReq); + + /* noop -- don't do anything */ + return Success; +} + +/********************** + * CloseDownClient + * + * Client can either mark his resources destroy or retain. If retained and + * then killed again, the client is really destroyed. + *********************/ + +char dispatchExceptionAtReset = DE_RESET; + +void +CloseDownClient(ClientPtr client) +{ + Bool really_close_down = client->clientGone || + client->closeDownMode == DestroyAll; + + if (!client->clientGone) + { + /* ungrab server if grabbing client dies */ + if (grabState != GrabNone && grabClient == client) + { + UngrabServer(client); + } + BITCLEAR(grabWaiters, client->index); + DeleteClientFromAnySelections(client); + ReleaseActiveGrabs(client); + DeleteClientFontStuff(client); + if (!really_close_down) + { + /* This frees resources that should never be retained + * no matter what the close down mode is. Actually we + * could do this unconditionally, but it's probably + * better not to traverse all the client's resources + * twice (once here, once a few lines down in + * FreeClientResources) in the common case of + * really_close_down == TRUE. + */ + FreeClientNeverRetainResources(client); + client->clientState = ClientStateRetained; + if (ClientStateCallback) + { + NewClientInfoRec clientinfo; + + clientinfo.client = client; + clientinfo.prefix = (xConnSetupPrefix *)NULL; + clientinfo.setup = (xConnSetup *) NULL; + CallCallbacks((&ClientStateCallback), (pointer)&clientinfo); + } + } + client->clientGone = TRUE; /* so events aren't sent to client */ + if (ClientIsAsleep(client)) + ClientSignal (client); + ProcessWorkQueueZombies(); + CloseDownConnection(client); + + /* If the client made it to the Running stage, nClients has + * been incremented on its behalf, so we need to decrement it + * now. If it hasn't gotten to Running, nClients has *not* + * been incremented, so *don't* decrement it. + */ + if (client->clientState != ClientStateInitial && + client->clientState != ClientStateAuthenticating ) + { + --nClients; + } + } + + if (really_close_down) + { + if (client->clientState == ClientStateRunning && nClients == 0) + dispatchException |= dispatchExceptionAtReset; + + client->clientState = ClientStateGone; + if (ClientStateCallback) + { + NewClientInfoRec clientinfo; + + clientinfo.client = client; + clientinfo.prefix = (xConnSetupPrefix *)NULL; + clientinfo.setup = (xConnSetup *) NULL; + CallCallbacks((&ClientStateCallback), (pointer)&clientinfo); + } + FreeClientResources(client); + /* Disable client ID tracking. This must be done after + * ClientStateCallback. */ + ReleaseClientIds(client); +#ifdef XSERVER_DTRACE + XSERVER_CLIENT_DISCONNECT(client->index); +#endif + if (client->index < nextFreeClientID) + nextFreeClientID = client->index; + clients[client->index] = NullClient; + SmartLastClient = NullClient; + dixFreeObjectWithPrivates(client, PRIVATE_CLIENT); + + while (!clients[currentMaxClients-1]) + currentMaxClients--; + } +} + +static void +KillAllClients(void) +{ + int i; + for (i=1; i<currentMaxClients; i++) + if (clients[i]) { + /* Make sure Retained clients are released. */ + clients[i]->closeDownMode = DestroyAll; + CloseDownClient(clients[i]); + } +} + +void InitClient(ClientPtr client, int i, pointer ospriv) +{ + client->index = i; + client->clientAsMask = ((Mask)i) << CLIENTOFFSET; + client->closeDownMode = i ? DestroyAll : RetainPermanent; + client->requestVector = InitialVector; + client->osPrivate = ospriv; + QueryMinMaxKeyCodes(&client->minKC,&client->maxKC); + client->smart_start_tick = SmartScheduleTime; + client->smart_stop_tick = SmartScheduleTime; + client->smart_check_tick = SmartScheduleTime; + client->clientIds = NULL; +} + +/************************ + * int NextAvailableClient(ospriv) + * + * OS dependent portion can't assign client id's because of CloseDownModes. + * Returns NULL if there are no free clients. + *************************/ + +ClientPtr NextAvailableClient(pointer ospriv) +{ + int i; + ClientPtr client; + xReq data; + + i = nextFreeClientID; + if (i == MAXCLIENTS) + return (ClientPtr)NULL; + clients[i] = client = dixAllocateObjectWithPrivates(ClientRec, PRIVATE_CLIENT); + if (!client) + return (ClientPtr)NULL; + InitClient(client, i, ospriv); + if (!InitClientResources(client)) + { + dixFreeObjectWithPrivates(client, PRIVATE_CLIENT); + return (ClientPtr)NULL; + } + data.reqType = 1; + data.length = bytes_to_int32(sz_xReq + sz_xConnClientPrefix); + if (!InsertFakeRequest(client, (char *)&data, sz_xReq)) + { + FreeClientResources(client); + dixFreeObjectWithPrivates(client, PRIVATE_CLIENT); + return (ClientPtr)NULL; + } + if (i == currentMaxClients) + currentMaxClients++; + while ((nextFreeClientID < MAXCLIENTS) && clients[nextFreeClientID]) + nextFreeClientID++; + + /* Enable client ID tracking. This must be done before + * ClientStateCallback. */ + ReserveClientIds(client); + + if (ClientStateCallback) + { + NewClientInfoRec clientinfo; + + clientinfo.client = client; + clientinfo.prefix = (xConnSetupPrefix *)NULL; + clientinfo.setup = (xConnSetup *) NULL; + CallCallbacks((&ClientStateCallback), (pointer)&clientinfo); + } + return client; +} + +int +ProcInitialConnection(ClientPtr client) +{ + REQUEST(xReq); + xConnClientPrefix *prefix; + int whichbyte = 1; + + prefix = (xConnClientPrefix *)((char *)stuff + sz_xReq); + if ((prefix->byteOrder != 'l') && (prefix->byteOrder != 'B')) + return client->noClientException = -1; + if (((*(char *) &whichbyte) && (prefix->byteOrder == 'B')) || + (!(*(char *) &whichbyte) && (prefix->byteOrder == 'l'))) + { + client->swapped = TRUE; + SwapConnClientPrefix(prefix); + } + stuff->reqType = 2; + stuff->length += bytes_to_int32(prefix->nbytesAuthProto) + + bytes_to_int32(prefix->nbytesAuthString); + if (client->swapped) + { + swaps(&stuff->length, whichbyte); + } + ResetCurrentRequest(client); + return Success; +} + +static int +SendConnSetup(ClientPtr client, char *reason) +{ + xWindowRoot *root; + int i; + int numScreens; + char* lConnectionInfo; + xConnSetupPrefix* lconnSetupPrefix; + + if (reason) + { + xConnSetupPrefix csp; + + csp.success = xFalse; + csp.lengthReason = strlen(reason); + csp.length = bytes_to_int32(csp.lengthReason); + csp.majorVersion = X_PROTOCOL; + csp.minorVersion = X_PROTOCOL_REVISION; + if (client->swapped) + WriteSConnSetupPrefix(client, &csp); + else + (void)WriteToClient(client, sz_xConnSetupPrefix, (char *) &csp); + (void)WriteToClient(client, (int)csp.lengthReason, reason); + return client->noClientException = -1; + } + + numScreens = screenInfo.numScreens; + lConnectionInfo = ConnectionInfo; + lconnSetupPrefix = &connSetupPrefix; + + /* We're about to start speaking X protocol back to the client by + * sending the connection setup info. This means the authorization + * step is complete, and we can count the client as an + * authorized one. + */ + nClients++; + + client->requestVector = client->swapped ? SwappedProcVector : ProcVector; + client->sequence = 0; + ((xConnSetup *)lConnectionInfo)->ridBase = client->clientAsMask; + ((xConnSetup *)lConnectionInfo)->ridMask = RESOURCE_ID_MASK; +#ifdef MATCH_CLIENT_ENDIAN + ((xConnSetup *)lConnectionInfo)->imageByteOrder = ClientOrder (client); + ((xConnSetup *)lConnectionInfo)->bitmapBitOrder = ClientOrder (client); +#endif + /* fill in the "currentInputMask" */ + root = (xWindowRoot *)(lConnectionInfo + connBlockScreenStart); +#ifdef PANORAMIX + if (noPanoramiXExtension) + numScreens = screenInfo.numScreens; + else + numScreens = ((xConnSetup *)ConnectionInfo)->numRoots; +#endif + + for (i=0; i<numScreens; i++) + { + unsigned int j; + xDepth *pDepth; + WindowPtr pRoot = screenInfo.screens[i]->root; + + root->currentInputMask = pRoot->eventMask | wOtherEventMasks(pRoot); + pDepth = (xDepth *)(root + 1); + for (j = 0; j < root->nDepths; j++) + { + pDepth = (xDepth *)(((char *)(pDepth + 1)) + + pDepth->nVisuals * sizeof(xVisualType)); + } + root = (xWindowRoot *)pDepth; + } + + if (client->swapped) + { + WriteSConnSetupPrefix(client, lconnSetupPrefix); + WriteSConnectionInfo(client, + (unsigned long)(lconnSetupPrefix->length << 2), + lConnectionInfo); + } + else + { + (void)WriteToClient(client, sizeof(xConnSetupPrefix), + (char *) lconnSetupPrefix); + (void)WriteToClient(client, (int)(lconnSetupPrefix->length << 2), + lConnectionInfo); + } + client->clientState = ClientStateRunning; + if (ClientStateCallback) + { + NewClientInfoRec clientinfo; + + clientinfo.client = client; + clientinfo.prefix = lconnSetupPrefix; + clientinfo.setup = (xConnSetup *)lConnectionInfo; + CallCallbacks((&ClientStateCallback), (pointer)&clientinfo); + } + return Success; +} + +int +ProcEstablishConnection(ClientPtr client) +{ + char *reason, *auth_proto, *auth_string; + xConnClientPrefix *prefix; + REQUEST(xReq); + + prefix = (xConnClientPrefix *)((char *)stuff + sz_xReq); + auth_proto = (char *)prefix + sz_xConnClientPrefix; + auth_string = auth_proto + pad_to_int32(prefix->nbytesAuthProto); + if ((prefix->majorVersion != X_PROTOCOL) || + (prefix->minorVersion != X_PROTOCOL_REVISION)) + reason = "Protocol version mismatch"; + else + reason = ClientAuthorized(client, + (unsigned short)prefix->nbytesAuthProto, + auth_proto, + (unsigned short)prefix->nbytesAuthString, + auth_string); + /* + * If Kerberos is being used for this client, the clientState + * will be set to ClientStateAuthenticating at this point. + * More messages need to be exchanged among the X server, Kerberos + * server, and client to figure out if everyone is authorized. + * So we don't want to send the connection setup info yet, since + * the auth step isn't really done. + */ + if (client->clientState == ClientStateCheckingSecurity) + client->clientState = ClientStateCheckedSecurity; + else if (client->clientState != ClientStateAuthenticating) + return(SendConnSetup(client, reason)); + return Success; +} + +void +SendErrorToClient(ClientPtr client, unsigned majorCode, unsigned minorCode, + XID resId, int errorCode) +{ + xError rep; + + memset(&rep, 0, sizeof(xError)); + rep.type = X_Error; + rep.errorCode = errorCode; + rep.majorCode = majorCode; + rep.minorCode = minorCode; + rep.resourceID = resId; + + WriteEventsToClient (client, 1, (xEvent *)&rep); +} + +void +MarkClientException(ClientPtr client) +{ + client->noClientException = -1; +} + +/* + * This array encodes the answer to the question "what is the log base 2 + * of the number of pixels that fit in a scanline pad unit?" + * Note that ~0 is an invalid entry (mostly for the benefit of the reader). + */ +static int answer[6][4] = { + /* pad pad pad pad*/ + /* 8 16 32 64 */ + + { 3, 4, 5 , 6 }, /* 1 bit per pixel */ + { 1, 2, 3 , 4 }, /* 4 bits per pixel */ + { 0, 1, 2 , 3 }, /* 8 bits per pixel */ + { ~0, 0, 1 , 2 }, /* 16 bits per pixel */ + { ~0, ~0, 0 , 1 }, /* 24 bits per pixel */ + { ~0, ~0, 0 , 1 } /* 32 bits per pixel */ +}; + +/* + * This array gives the answer to the question "what is the first index for + * the answer array above given the number of bits per pixel?" + * Note that ~0 is an invalid entry (mostly for the benefit of the reader). + */ +static int indexForBitsPerPixel[ 33 ] = { + ~0, 0, ~0, ~0, /* 1 bit per pixel */ + 1, ~0, ~0, ~0, /* 4 bits per pixel */ + 2, ~0, ~0, ~0, /* 8 bits per pixel */ + ~0,~0, ~0, ~0, + 3, ~0, ~0, ~0, /* 16 bits per pixel */ + ~0,~0, ~0, ~0, + 4, ~0, ~0, ~0, /* 24 bits per pixel */ + ~0,~0, ~0, ~0, + 5 /* 32 bits per pixel */ +}; + +/* + * This array gives the bytesperPixel value for cases where the number + * of bits per pixel is a multiple of 8 but not a power of 2. + */ +static int answerBytesPerPixel[ 33 ] = { + ~0, 0, ~0, ~0, /* 1 bit per pixel */ + 0, ~0, ~0, ~0, /* 4 bits per pixel */ + 0, ~0, ~0, ~0, /* 8 bits per pixel */ + ~0,~0, ~0, ~0, + 0, ~0, ~0, ~0, /* 16 bits per pixel */ + ~0,~0, ~0, ~0, + 3, ~0, ~0, ~0, /* 24 bits per pixel */ + ~0,~0, ~0, ~0, + 0 /* 32 bits per pixel */ +}; + +/* + * This array gives the answer to the question "what is the second index for + * the answer array above given the number of bits per scanline pad unit?" + * Note that ~0 is an invalid entry (mostly for the benefit of the reader). + */ +static int indexForScanlinePad[ 65 ] = { + ~0, ~0, ~0, ~0, + ~0, ~0, ~0, ~0, + 0, ~0, ~0, ~0, /* 8 bits per scanline pad unit */ + ~0, ~0, ~0, ~0, + 1, ~0, ~0, ~0, /* 16 bits per scanline pad unit */ + ~0, ~0, ~0, ~0, + ~0, ~0, ~0, ~0, + ~0, ~0, ~0, ~0, + 2, ~0, ~0, ~0, /* 32 bits per scanline pad unit */ + ~0, ~0, ~0, ~0, + ~0, ~0, ~0, ~0, + ~0, ~0, ~0, ~0, + ~0, ~0, ~0, ~0, + ~0, ~0, ~0, ~0, + ~0, ~0, ~0, ~0, + ~0, ~0, ~0, ~0, + 3 /* 64 bits per scanline pad unit */ +}; + +/* + grow the array of screenRecs if necessary. + call the device-supplied initialization procedure +with its screen number, a pointer to its ScreenRec, argc, and argv. + return the number of successfully installed screens. + +*/ + +int +AddScreen( + Bool (* pfnInit)( + int /*index*/, + ScreenPtr /*pScreen*/, + int /*argc*/, + char ** /*argv*/ + ), + int argc, + char **argv) +{ + + int i; + int scanlinepad, format, depth, bitsPerPixel, j, k; + ScreenPtr pScreen; + + i = screenInfo.numScreens; + if (i == MAXSCREENS) + return -1; + + pScreen = (ScreenPtr) calloc(1, sizeof(ScreenRec)); + if (!pScreen) + return -1; + + if (!dixAllocatePrivates(&pScreen->devPrivates, PRIVATE_SCREEN)) { + free (pScreen); + return -1; + } + pScreen->myNum = i; + pScreen->totalPixmapSize = 0; /* computed in CreateScratchPixmapForScreen */ + pScreen->ClipNotify = 0; /* for R4 ddx compatibility */ + pScreen->CreateScreenResources = 0; + + /* + * This loop gets run once for every Screen that gets added, + * but thats ok. If the ddx layer initializes the formats + * one at a time calling AddScreen() after each, then each + * iteration will make it a little more accurate. Worst case + * we do this loop N * numPixmapFormats where N is # of screens. + * Anyway, this must be called after InitOutput and before the + * screen init routine is called. + */ + for (format=0; format<screenInfo.numPixmapFormats; format++) + { + depth = screenInfo.formats[format].depth; + bitsPerPixel = screenInfo.formats[format].bitsPerPixel; + scanlinepad = screenInfo.formats[format].scanlinePad; + j = indexForBitsPerPixel[ bitsPerPixel ]; + k = indexForScanlinePad[ scanlinepad ]; + PixmapWidthPaddingInfo[ depth ].padPixelsLog2 = answer[j][k]; + PixmapWidthPaddingInfo[ depth ].padRoundUp = + (scanlinepad/bitsPerPixel) - 1; + j = indexForBitsPerPixel[ 8 ]; /* bits per byte */ + PixmapWidthPaddingInfo[ depth ].padBytesLog2 = answer[j][k]; + PixmapWidthPaddingInfo[ depth ].bitsPerPixel = bitsPerPixel; + if (answerBytesPerPixel[bitsPerPixel]) + { + PixmapWidthPaddingInfo[ depth ].notPower2 = 1; + PixmapWidthPaddingInfo[ depth ].bytesPerPixel = + answerBytesPerPixel[bitsPerPixel]; + } + else + { + PixmapWidthPaddingInfo[ depth ].notPower2 = 0; + } + } + + /* This is where screen specific stuff gets initialized. Load the + screen structure, call the hardware, whatever. + This is also where the default colormap should be allocated and + also pixel values for blackPixel, whitePixel, and the cursor + Note that InitScreen is NOT allowed to modify argc, argv, or + any of the strings pointed to by argv. They may be passed to + multiple screens. + */ + screenInfo.screens[i] = pScreen; + screenInfo.numScreens++; + if (!(*pfnInit)(i, pScreen, argc, argv)) + { + dixFreePrivates(pScreen->devPrivates, PRIVATE_SCREEN); + free(pScreen); + screenInfo.numScreens--; + return -1; + } + + dixRegisterPrivateKey(&cursorScreenDevPriv[i], PRIVATE_CURSOR, 0); + + return i; +} diff --git a/xorg-server/dix/eventconvert.c b/xorg-server/dix/eventconvert.c index dd1ca460b..760729beb 100644 --- a/xorg-server/dix/eventconvert.c +++ b/xorg-server/dix/eventconvert.c @@ -97,8 +97,12 @@ EventIsKeyRepeat(xEvent *event) * @return Success or the matching error code. */ int -EventToCore(InternalEvent *event, xEvent *core) +EventToCore(InternalEvent *event, xEvent **core_out, int *count_out) { + xEvent *core = NULL; + int count = 0; + int ret = BadImplementation; + switch(event->any.type) { case ET_Motion: @@ -108,7 +112,10 @@ EventToCore(InternalEvent *event, xEvent *core) * present */ if (!BitIsOn(e->valuators.mask, 0) && !BitIsOn(e->valuators.mask, 1)) - return BadMatch; + { + ret = BadMatch; + goto out; + } } /* fallthrough */ case ET_ButtonPress: @@ -119,9 +126,15 @@ EventToCore(InternalEvent *event, xEvent *core) DeviceEvent *e = &event->device_event; if (e->detail.key > 0xFF) - return BadMatch; - - memset(core, 0, sizeof(xEvent)); + { + ret = BadMatch; + goto out; + } + + core = calloc(1, sizeof(*core)); + if (!core) + return BadAlloc; + count = 1; core->u.u.type = e->type - ET_KeyPress + KeyPress; core->u.u.detail = e->detail.key & 0xFF; core->u.keyButtonPointer.time = e->time; @@ -129,7 +142,10 @@ EventToCore(InternalEvent *event, xEvent *core) core->u.keyButtonPointer.rootY = e->root_y; core->u.keyButtonPointer.state = e->corestate; core->u.keyButtonPointer.root = e->root; - EventSetKeyRepeatFlag(core, (e->type == ET_KeyPress && e->key_repeat)); + EventSetKeyRepeatFlag(core, + (e->type == ET_KeyPress && + e->key_repeat)); + ret = Success; } break; case ET_ProximityIn: @@ -139,13 +155,18 @@ EventToCore(InternalEvent *event, xEvent *core) case ET_RawButtonPress: case ET_RawButtonRelease: case ET_RawMotion: - return BadMatch; + ret = BadMatch; + goto out; default: /* XXX: */ ErrorF("[dix] EventToCore: Not implemented yet \n"); - return BadImplementation; + ret = BadImplementation; } - return Success; + +out: + *core_out = core; + *count_out = count; + return ret; } /** diff --git a/xorg-server/dix/events.c b/xorg-server/dix/events.c index 07f8b05ea..df62e839b 100644 --- a/xorg-server/dix/events.c +++ b/xorg-server/dix/events.c @@ -328,6 +328,13 @@ IsMaster(DeviceIntPtr dev) return dev->type == MASTER_POINTER || dev->type == MASTER_KEYBOARD; } +Bool +IsFloating(DeviceIntPtr dev) +{ + return GetMaster(dev, MASTER_KEYBOARD) == NULL; +} + + /** * Max event opcode. */ @@ -1397,10 +1404,10 @@ CheckGrabForSyncs(DeviceIntPtr thisDev, Bool thisMode, Bool otherMode) static void DetachFromMaster(DeviceIntPtr dev) { - if (!dev->u.master) + if (!IsFloating(dev)) return; - dev->saved_master_id = dev->u.master->id; + dev->saved_master_id = GetMaster(dev, MASTER_ATTACHED)->id; AttachDevice(NULL, dev, NULL); } @@ -2287,8 +2294,8 @@ FixUpEventFromWindow( * @param[in] event The event that is to be sent. * @param[in] win The current event window. * - * @return Bitmask of ::XI2_MASK, ::XI_MASK, ::CORE_MASK, and - * ::DONT_PROPAGATE_MASK. + * @return Bitmask of ::EVENT_XI2_MASK, ::EVENT_XI1_MASK, ::EVENT_CORE_MASK, and + * ::EVENT_DONT_PROPAGATE_MASK. */ int EventIsDeliverable(DeviceIntPtr dev, InternalEvent* event, WindowPtr win) @@ -2309,7 +2316,7 @@ EventIsDeliverable(DeviceIntPtr dev, InternalEvent* event, WindowPtr win) ((inputMasks->xi2mask[XIAllDevices][type/8] & filter) || ((inputMasks->xi2mask[XIAllMasterDevices][type/8] & filter) && IsMaster(dev)) || (inputMasks->xi2mask[dev->id][type/8] & filter))) - rc |= XI2_MASK; + rc |= EVENT_XI2_MASK; type = GetXIType(event); ev.u.u.type = type; @@ -2319,22 +2326,22 @@ EventIsDeliverable(DeviceIntPtr dev, InternalEvent* event, WindowPtr win) if (type && inputMasks && (inputMasks->deliverableEvents[dev->id] & filter) && (inputMasks->inputEvents[dev->id] & filter)) - rc |= XI_MASK; + rc |= EVENT_XI1_MASK; /* Check for XI DontPropagate mask */ if (type && inputMasks && (inputMasks->dontPropagateMask[dev->id] & filter)) - rc |= DONT_PROPAGATE_MASK; + rc |= EVENT_DONT_PROPAGATE_MASK; /* Check for core mask */ type = GetCoreType(event); if (type && (win->deliverableEvents & filter) && ((wOtherEventMasks(win) | win->eventMask) & filter)) - rc |= CORE_MASK; + rc |= EVENT_CORE_MASK; /* Check for core DontPropagate mask */ if (type && (filter & wDontPropagateMask(win))) - rc |= DONT_PROPAGATE_MASK; + rc |= EVENT_DONT_PROPAGATE_MASK; return rc; } @@ -2366,8 +2373,7 @@ DeliverDeviceEvents(WindowPtr pWin, InternalEvent *event, GrabPtr grab, Window child = None; Mask filter; int deliveries = 0; - xEvent core; - xEvent *xE = NULL; + xEvent *xE = NULL, *core = NULL; int rc, mask, count = 0; CHECKEVENT(event); @@ -2377,7 +2383,7 @@ DeliverDeviceEvents(WindowPtr pWin, InternalEvent *event, GrabPtr grab, if ((mask = EventIsDeliverable(dev, event, pWin))) { /* XI2 events first */ - if (mask & XI2_MASK) + if (mask & EVENT_XI2_MASK) { xEvent *xi2 = NULL; rc = EventToXI2(event, &xi2); @@ -2397,7 +2403,7 @@ DeliverDeviceEvents(WindowPtr pWin, InternalEvent *event, GrabPtr grab, } /* XI events */ - if (mask & XI_MASK) + if (mask & EVENT_XI1_MASK) { rc = EventToXI(event, &xE, &count); if (rc == Success) { @@ -2415,15 +2421,15 @@ DeliverDeviceEvents(WindowPtr pWin, InternalEvent *event, GrabPtr grab, } /* Core event */ - if ((mask & CORE_MASK) && IsMaster(dev) && dev->coreEvents) + if ((mask & EVENT_CORE_MASK) && IsMaster(dev) && dev->coreEvents) { - rc = EventToCore(event, &core); + rc = EventToCore(event, &core, &count); if (rc == Success) { - if (XaceHook(XACE_SEND_ACCESS, NULL, dev, pWin, &core, 1) == Success) { - filter = GetEventFilter(dev, &core); - FixUpEventFromWindow(pSprite, &core, pWin, child, FALSE); - deliveries = DeliverEventsToWindow(dev, pWin, &core, 1, - filter, grab); + if (XaceHook(XACE_SEND_ACCESS, NULL, dev, pWin, core, count) == Success) { + filter = GetEventFilter(dev, core); + FixUpEventFromWindow(pSprite, core, pWin, child, FALSE); + deliveries = DeliverEventsToWindow(dev, pWin, core, + count, filter, grab); if (deliveries > 0) goto unwind; } @@ -2433,7 +2439,7 @@ DeliverDeviceEvents(WindowPtr pWin, InternalEvent *event, GrabPtr grab, } if ((deliveries < 0) || (pWin == stopAt) || - (mask & DONT_PROPAGATE_MASK)) + (mask & EVENT_DONT_PROPAGATE_MASK)) { deliveries = 0; goto unwind; @@ -2445,14 +2451,11 @@ DeliverDeviceEvents(WindowPtr pWin, InternalEvent *event, GrabPtr grab, } unwind: + free(core); free(xE); return deliveries; } -#undef XI_MASK -#undef CORE_MASK -#undef DONT_PROPAGATE_MASK - /** * Deliver event to a window and it's immediate parent. Used for most window * events (CreateNotify, ConfigureNotify, etc.). Not useful for events that @@ -2470,9 +2473,8 @@ int DeliverEvents(WindowPtr pWin, xEvent *xE, int count, WindowPtr otherParent) { - Mask filter; - int deliveries; DeviceIntRec dummy; + int deliveries; #ifdef PANORAMIX if(!noPanoramiXExtension && pWin->drawable.pScreen->myNum) @@ -2483,11 +2485,42 @@ DeliverEvents(WindowPtr pWin, xEvent *xE, int count, return 0; dummy.id = XIAllDevices; - filter = GetEventFilter(&dummy, xE); - if ((filter & SubstructureNotifyMask) && (xE->u.u.type != CreateNotify)) - xE->u.destroyNotify.event = pWin->drawable.id; - if (filter != StructureAndSubMask) - return DeliverEventsToWindow(&dummy, pWin, xE, count, filter, NullGrab); + + switch (xE->u.u.type) + { + case DestroyNotify: + case UnmapNotify: + case MapNotify: + case MapRequest: + case ReparentNotify: + case ConfigureNotify: + case ConfigureRequest: + case GravityNotify: + case CirculateNotify: + case CirculateRequest: + xE->u.destroyNotify.event = pWin->drawable.id; + break; + } + + switch (xE->u.u.type) + { + case DestroyNotify: + case UnmapNotify: + case MapNotify: + case ReparentNotify: + case ConfigureNotify: + case GravityNotify: + case CirculateNotify: + break; + default: + { + Mask filter; + filter = GetEventFilter(&dummy, xE); + return DeliverEventsToWindow(&dummy, pWin, xE, count, filter, + NullGrab); + } + } + deliveries = DeliverEventsToWindow(&dummy, pWin, xE, count, StructureNotifyMask, NullGrab); if (pWin->parent) @@ -2799,7 +2832,7 @@ WindowsRestructured(void) DeviceIntPtr pDev = inputInfo.devices; while(pDev) { - if (IsMaster(pDev) || !pDev->u.master) + if (IsMaster(pDev) || IsFloating(pDev)) CheckMotion(NULL, pDev); pDev = pDev->next; } @@ -3230,15 +3263,15 @@ ProcWarpPointer(ClientPtr client) dev = PickPointer(client); for (tmp = inputInfo.devices; tmp; tmp = tmp->next) { - if ((tmp == dev) || (!IsMaster(tmp) && tmp->u.master == dev)) { + if (GetMaster(tmp, MASTER_ATTACHED) == dev) { rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixWriteAccess); if (rc != Success) return rc; } } - if (dev->u.lastSlave) - dev = dev->u.lastSlave; + if (dev->lastSlave) + dev = dev->lastSlave; pSprite = dev->spriteInfo->sprite; #ifdef PANORAMIX @@ -3394,7 +3427,7 @@ CheckPassiveGrabsOnWindow( * attached master keyboard. Since the slave may have been * reattached after the grab, the modifier device may not be the * same. */ - if (!IsMaster(grab->device) && device->u.master) + if (!IsMaster(grab->device) && !IsFloating(device)) gdev = GetMaster(device, MASTER_KEYBOARD); } @@ -3434,7 +3467,6 @@ CheckPassiveGrabsOnWindow( { int rc, count = 0; xEvent *xE = NULL; - xEvent core; event->corestate &= 0x1f00; event->corestate |= tempGrab.modifiersDetail.exact & (~0x1f00); @@ -3486,7 +3518,7 @@ CheckPassiveGrabsOnWindow( if (match & CORE_MATCH) { - rc = EventToCore((InternalEvent*)event, &core); + rc = EventToCore((InternalEvent*)event, &xE, &count); if (rc != Success) { if (rc != BadMatch) @@ -3494,8 +3526,6 @@ CheckPassiveGrabsOnWindow( "(%d, %d).\n", device->name, event->type, rc); continue; } - xE = &core; - count = 1; } else if (match & XI2_MATCH) { rc = EventToXI2((InternalEvent*)event, &xE); @@ -3525,6 +3555,7 @@ CheckPassiveGrabsOnWindow( { FixUpEventFromWindow(pSprite, xE, grab->window, None, TRUE); + /* XXX: XACE? */ TryClientEvents(rClient(grab), device, xE, count, GetEventFilter(device, xE), GetEventFilter(device, xE), grab); @@ -3538,8 +3569,7 @@ CheckPassiveGrabsOnWindow( grabinfo->sync.state = FROZEN_WITH_EVENT; } - if (match & (XI_MATCH | XI2_MATCH)) - free(xE); /* on core match xE == &core */ + free(xE); return grab; } } @@ -3582,6 +3612,7 @@ CheckDeviceGrabs(DeviceIntPtr device, DeviceEvent *event, WindowPtr ancestor) WindowPtr pWin = NULL; FocusClassPtr focus = IsPointerEvent((InternalEvent*)event) ? NULL : device->focus; BOOL sendCore = (IsMaster(device) && device->coreEvents); + Bool ret = FALSE; if (event->type != ET_ButtonPress && event->type != ET_KeyPress) @@ -3601,7 +3632,7 @@ CheckDeviceGrabs(DeviceIntPtr device, DeviceEvent *event, WindowPtr ancestor) if (device->spriteInfo->sprite->spriteTrace[i++] == ancestor) break; if (i == device->spriteInfo->sprite->spriteTraceGood) - return FALSE; + goto out; } if (focus) @@ -3610,23 +3641,32 @@ CheckDeviceGrabs(DeviceIntPtr device, DeviceEvent *event, WindowPtr ancestor) { pWin = focus->trace[i]; if (CheckPassiveGrabsOnWindow(pWin, device, event, sendCore, TRUE)) - return TRUE; + { + ret = TRUE; + goto out; + } } if ((focus->win == NoneWin) || (i >= device->spriteInfo->sprite->spriteTraceGood) || (pWin && pWin != device->spriteInfo->sprite->spriteTrace[i-1])) - return FALSE; + goto out; } for (; i < device->spriteInfo->sprite->spriteTraceGood; i++) { pWin = device->spriteInfo->sprite->spriteTrace[i]; if (CheckPassiveGrabsOnWindow(pWin, device, event, sendCore, TRUE)) - return TRUE; + { + ret = TRUE; + goto out; + } } - return FALSE; +out: + if (ret == TRUE && event->type == ET_KeyPress) + device->deviceGrab.activatingKey = event->detail.key; + return ret; } /** @@ -3646,8 +3686,7 @@ DeliverFocusedEvent(DeviceIntPtr keybd, InternalEvent *event, WindowPtr window) DeviceIntPtr ptr; WindowPtr focus = keybd->focus->win; BOOL sendCore = (IsMaster(keybd) && keybd->coreEvents); - xEvent core; - xEvent *xE = NULL, *xi2 = NULL; + xEvent *core = NULL, *xE = NULL, *xi2 = NULL; int count, rc; int deliveries = 0; @@ -3701,13 +3740,13 @@ DeliverFocusedEvent(DeviceIntPtr keybd, InternalEvent *event, WindowPtr window) if (sendCore) { - rc = EventToCore(event, &core); + rc = EventToCore(event, &core, &count); if (rc == Success) { - if (XaceHook(XACE_SEND_ACCESS, NULL, keybd, focus, &core, 1) == Success) { - FixUpEventFromWindow(keybd->spriteInfo->sprite, &core, focus, + if (XaceHook(XACE_SEND_ACCESS, NULL, keybd, focus, core, count) == Success) { + FixUpEventFromWindow(keybd->spriteInfo->sprite, core, focus, None, FALSE); - deliveries = DeliverEventsToWindow(keybd, focus, &core, 1, - GetEventFilter(keybd, &core), + deliveries = DeliverEventsToWindow(keybd, focus, core, count, + GetEventFilter(keybd, core), NullGrab); } } else if (rc != BadMatch) @@ -3716,6 +3755,7 @@ DeliverFocusedEvent(DeviceIntPtr keybd, InternalEvent *event, WindowPtr window) } unwind: + free(core); free(xE); free(xi2); return; @@ -3741,6 +3781,7 @@ DeliverGrabbedEvent(InternalEvent *event, DeviceIntPtr thisDev, int rc, count = 0; xEvent *xi = NULL; xEvent *xi2 = NULL; + xEvent *core = NULL; grabinfo = &thisDev->deviceGrab; grab = grabinfo->grab; @@ -3790,22 +3831,20 @@ DeliverGrabbedEvent(InternalEvent *event, DeviceIntPtr thisDev, /* try core event */ if (sendCore && grab->grabtype == GRABTYPE_CORE) { - xEvent core; - - rc = EventToCore(event, &core); + rc = EventToCore(event, &core, &count); if (rc == Success) { - FixUpEventFromWindow(pSprite, &core, grab->window, None, TRUE); + FixUpEventFromWindow(pSprite, core, grab->window, None, TRUE); if (XaceHook(XACE_SEND_ACCESS, 0, thisDev, - grab->window, &core, 1) || + grab->window, core, count) || XaceHook(XACE_RECEIVE_ACCESS, rClient(grab), - grab->window, &core, 1)) + grab->window, core, count)) deliveries = 1; /* don't send, but pretend we did */ - else if (!IsInterferingGrab(rClient(grab), thisDev, &core)) + else if (!IsInterferingGrab(rClient(grab), thisDev, core)) { deliveries = TryClientEvents(rClient(grab), thisDev, - &core, 1, mask, - GetEventFilter(thisDev, &core), + core, count, mask, + GetEventFilter(thisDev, core), grab); } } else if (rc != BadMatch) @@ -3872,16 +3911,15 @@ DeliverGrabbedEvent(InternalEvent *event, DeviceIntPtr thisDev, switch (grabinfo->sync.state) { case FREEZE_BOTH_NEXT_EVENT: - for (dev = inputInfo.devices; dev; dev = dev->next) + dev = GetPairedDevice(thisDev); + if (dev) { - if (dev == thisDev) - continue; FreezeThaw(dev, TRUE); if ((dev->deviceGrab.sync.state == FREEZE_BOTH_NEXT_EVENT) && (CLIENT_BITS(grab->resource) == CLIENT_BITS(dev->deviceGrab.grab->resource))) dev->deviceGrab.sync.state = FROZEN_NO_EVENT; - else if (GetPairedDevice(thisDev) == dev) + else dev->deviceGrab.sync.other = grab; } /* fall through */ @@ -3895,6 +3933,7 @@ DeliverGrabbedEvent(InternalEvent *event, DeviceIntPtr thisDev, } } + free(core); free(xi); free(xi2); } @@ -4277,7 +4316,7 @@ DeviceEnterLeaveEvent( if (BitIsOn(mouse->button->down, i)) SetBit(&event[1], i); - kbd = (IsMaster(mouse) || mouse->u.master) ? GetPairedDevice(mouse) : NULL; + kbd = GetMaster(mouse, MASTER_KEYBOARD); if (kbd && kbd->key) { event->mods.base_mods = kbd->key->xkbInfo->state.base_mods; diff --git a/xorg-server/dix/getevents.c b/xorg-server/dix/getevents.c index 794df420b..5b8e3798d 100644 --- a/xorg-server/dix/getevents.c +++ b/xorg-server/dix/getevents.c @@ -767,7 +767,7 @@ moveRelative(DeviceIntPtr dev, int *x, int *y, ValuatorMask *mask) /* if attached, clip both x and y to the defined limits (usually * co-ord space limit). If it is attached, we need x/y to go over the * limits to be able to change screens. */ - if(dev->u.master && dev->valuator) { + if(dev->valuator && IsMaster(dev) || !IsFloating(dev)) { if (valuator_get_mode(dev, 0) == Absolute) clipAxis(dev, 0, x); if (valuator_get_mode(dev, 1) == Absolute) @@ -865,11 +865,12 @@ positionSprite(DeviceIntPtr dev, int *x, int *y, float x_frac, float y_frac, * to the current screen. */ miPointerSetPosition(dev, screenx, screeny); - if (dev->u.master) { - dev->u.master->last.valuators[0] = *screenx; - dev->u.master->last.valuators[1] = *screeny; - dev->u.master->last.remainder[0] = *screenx_frac; - dev->u.master->last.remainder[1] = *screeny_frac; + if(!IsMaster(dev) || !IsFloating(dev)) { + DeviceIntPtr master = GetMaster(dev, MASTER_POINTER); + master->last.valuators[0] = *screenx; + master->last.valuators[1] = *screeny; + master->last.remainder[0] = *screenx_frac; + master->last.remainder[1] = *screeny_frac; } if (dev->valuator) @@ -911,7 +912,7 @@ updateHistory(DeviceIntPtr dev, ValuatorMask *mask, CARD32 ms) return; updateMotionHistory(dev, ms, mask, dev->last.valuators); - if (dev->u.master) + if(!IsMaster(dev) || !IsFloating(dev)) { DeviceIntPtr master = GetMaster(dev, MASTER_POINTER); updateMotionHistory(master, ms, mask, dev->last.valuators); diff --git a/xorg-server/dix/inpututils.c b/xorg-server/dix/inpututils.c index ef3142c84..077ffce01 100644 --- a/xorg-server/dix/inpututils.c +++ b/xorg-server/dix/inpututils.c @@ -268,15 +268,15 @@ change_modmap(ClientPtr client, DeviceIntPtr dev, KeyCode *modkeymap, /* Change any attached masters/slaves. */ if (IsMaster(dev)) { for (tmp = inputInfo.devices; tmp; tmp = tmp->next) { - if (!IsMaster(tmp) && tmp->u.master == dev) + if (!IsMaster(tmp) && GetMaster(tmp, MASTER_KEYBOARD) == dev) if (check_modmap_change_slave(client, dev, tmp, modmap)) do_modmap_change(client, tmp, modmap); } } - else if (dev->u.master && dev->u.master->u.lastSlave == dev) { + else if (!IsFloating(dev) && GetMaster(dev, MASTER_KEYBOARD)->lastSlave == dev) { /* If this fails, expect the results to be weird. */ - if (check_modmap_change(client, dev->u.master, modmap)) - do_modmap_change(client, dev->u.master, modmap); + if (check_modmap_change(client, dev->master, modmap)) + do_modmap_change(client, dev->master, modmap); } return Success; diff --git a/xorg-server/dix/main.c b/xorg-server/dix/main.c index 15d39d7be..31e2d48c4 100644 --- a/xorg-server/dix/main.c +++ b/xorg-server/dix/main.c @@ -1,351 +1,354 @@ -/***********************************************************
-
-Copyright 1987, 1998 The Open Group
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation.
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
-AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of The Open Group shall not be
-used in advertising or otherwise to promote the sale, use or other dealings
-in this Software without prior written authorization from The Open Group.
-
-
-Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
-
- All Rights Reserved
-
-Permission 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 that
-both that copyright notice and this permission notice appear in
-supporting documentation, and that the name of Digital not be
-used in advertising or publicity pertaining to distribution of the
-software without specific, written prior permission.
-
-DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
-ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
-DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
-ANY 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 THIS
-SOFTWARE.
-
-******************************************************************/
-
-/* The panoramix components contained the following notice */
-/*****************************************************************
-
-Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software.
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING,
-BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY,
-WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
-IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of Digital Equipment Corporation
-shall not be used in advertising or otherwise to promote the sale, use or other
-dealings in this Software without prior written authorization from Digital
-Equipment Corporation.
-
-******************************************************************/
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#include <version-config.h>
-#endif
-
-#include <X11/X.h>
-#include <X11/Xos.h> /* for unistd.h */
-#include <X11/Xproto.h>
-#include <pixman.h>
-#include "scrnintstr.h"
-#include "misc.h"
-#include "os.h"
-#include "windowstr.h"
-#include "resource.h"
-#include "dixstruct.h"
-#include "gcstruct.h"
-#include "extension.h"
-#include "colormap.h"
-#include "colormapst.h"
-#include "cursorstr.h"
-#include "selection.h"
-#include <X11/fonts/font.h>
-#include "opaque.h"
-#include "servermd.h"
-#include "hotplug.h"
-#include "site.h"
-#include "dixfont.h"
-#include "extnsionst.h"
-#include "privates.h"
-#include "registry.h"
-#ifdef PANORAMIX
-#include "panoramiXsrv.h"
-#else
-#include "dixevents.h" /* InitEvents() */
-#endif
-
-#ifdef DPMSExtension
-#include <X11/extensions/dpmsconst.h>
-#include "dpmsproc.h"
-#endif
-
-extern void Dispatch(void);
-
-#ifdef XQUARTZ
-#include <pthread.h>
-
-BOOL serverInitComplete = FALSE;
-pthread_mutex_t serverInitCompleteMutex = PTHREAD_MUTEX_INITIALIZER;
-pthread_cond_t serverInitCompleteCond = PTHREAD_COND_INITIALIZER;
-
-int dix_main(int argc, char *argv[], char *envp[]);
-
-int dix_main(int argc, char *argv[], char *envp[])
-#else
-int main(int argc, char *argv[], char *envp[])
-#endif
-{
- int i;
- HWEventQueueType alwaysCheckForInput[2];
-
- display = "0";
-
- InitRegions();
-
- pixman_disable_out_of_bounds_workaround();
-
- CheckUserParameters(argc, argv, envp);
-
- CheckUserAuthorization();
-
- InitConnectionLimits();
-
- ProcessCommandLine(argc, argv);
-
- alwaysCheckForInput[0] = 0;
- alwaysCheckForInput[1] = 1;
- while(1)
- {
- serverGeneration++;
- ScreenSaverTime = defaultScreenSaverTime;
- ScreenSaverInterval = defaultScreenSaverInterval;
- ScreenSaverBlanking = defaultScreenSaverBlanking;
- ScreenSaverAllowExposures = defaultScreenSaverAllowExposures;
-#ifdef DPMSExtension
- DPMSStandbyTime = DPMSSuspendTime = DPMSOffTime = ScreenSaverTime;
- DPMSEnabled = TRUE;
- DPMSPowerLevel = 0;
-#endif
- InitBlockAndWakeupHandlers();
- /* Perform any operating system dependent initializations you'd like */
- OsInit();
- if(serverGeneration == 1)
- {
- CreateWellKnownSockets();
- for (i=1; i<MAXCLIENTS; i++)
- clients[i] = NullClient;
- serverClient = calloc(sizeof(ClientRec), 1);
- if (!serverClient)
- FatalError("couldn't create server client");
- InitClient(serverClient, 0, (pointer)NULL);
- }
- else
- ResetWellKnownSockets ();
- clients[0] = serverClient;
- currentMaxClients = 1;
-
- /* Initialize privates before first allocation */
- dixResetPrivates();
-
- /* Initialize server client devPrivates, to be reallocated as
- * more client privates are registered
- */
- if (!dixAllocatePrivates(&serverClient->devPrivates, PRIVATE_CLIENT))
- FatalError("failed to create server client privates");
-
- if (!InitClientResources(serverClient)) /* for root resources */
- FatalError("couldn't init server resources");
-
- SetInputCheck(&alwaysCheckForInput[0], &alwaysCheckForInput[1]);
- screenInfo.numScreens = 0;
-
- InitAtoms();
- InitEvents();
- InitSelections();
- InitGlyphCaching();
- dixResetRegistry();
- ResetFontPrivateIndex();
- InitCallbackManager();
- InitOutput(&screenInfo, argc, argv);
-
- if (screenInfo.numScreens < 1)
- FatalError("no screens found");
- InitExtensions(argc, argv);
-
- for (i = 0; i < screenInfo.numScreens; i++)
- {
- ScreenPtr pScreen = screenInfo.screens[i];
- if (!CreateScratchPixmapsForScreen(i))
- FatalError("failed to create scratch pixmaps");
- if (pScreen->CreateScreenResources &&
- !(*pScreen->CreateScreenResources)(pScreen))
- FatalError("failed to create screen resources");
- if (!CreateGCperDepth(i))
- FatalError("failed to create scratch GCs");
- if (!CreateDefaultStipple(i))
- FatalError("failed to create default stipple");
- if (!CreateRootWindow(pScreen))
- FatalError("failed to create root window");
- }
-
- InitFonts();
- if (SetDefaultFontPath(defaultFontPath) != Success) {
- ErrorF("[dix] failed to set default font path '%s'", defaultFontPath);
- }
- if (!SetDefaultFont(defaultTextFont)) {
- FatalError("could not open default font '%s'", defaultTextFont);
- }
-
- if (!(rootCursor = CreateRootCursor(NULL, 0))) {
- FatalError("could not open default cursor font '%s'",
- defaultCursorFont);
- }
-
-#ifdef DPMSExtension
- /* check all screens, looking for DPMS Capabilities */
- DPMSCapableFlag = DPMSSupported();
- if (!DPMSCapableFlag)
- DPMSEnabled = FALSE;
-#endif
-
-#ifdef PANORAMIX
- /*
- * Consolidate window and colourmap information for each screen
- */
- if (!noPanoramiXExtension)
- PanoramiXConsolidate();
-#endif
-
- for (i = 0; i < screenInfo.numScreens; i++)
- InitRootWindow(screenInfo.screens[i]->root);
-
- InitCoreDevices();
- InitInput(argc, argv);
- InitAndStartDevices();
-
- dixSaveScreens(serverClient, SCREEN_SAVER_FORCER, ScreenSaverReset);
-
-#ifdef PANORAMIX
- if (!noPanoramiXExtension) {
- if (!PanoramiXCreateConnectionBlock()) {
- FatalError("could not create connection block info");
- }
- } else
-#endif
- {
- if (!CreateConnectionBlock()) {
- FatalError("could not create connection block info");
- }
- }
-
-#ifdef XQUARTZ
- /* Let the other threads know the server is done with its init */
- pthread_mutex_lock(&serverInitCompleteMutex);
- serverInitComplete = TRUE;
- pthread_cond_broadcast(&serverInitCompleteCond);
- pthread_mutex_unlock(&serverInitCompleteMutex);
-#endif
-
- NotifyParentProcess();
-
- Dispatch();
-
- UndisplayDevices();
-
- /* Now free up whatever must be freed */
- if (screenIsSaved == SCREEN_SAVER_ON)
- dixSaveScreens(serverClient, SCREEN_SAVER_OFF, ScreenSaverReset);
- FreeScreenSaverTimer();
- CloseDownExtensions();
-
-#ifdef PANORAMIX
- {
- Bool remember_it = noPanoramiXExtension;
- noPanoramiXExtension = TRUE;
- FreeAllResources();
- noPanoramiXExtension = remember_it;
- }
-#else
- FreeAllResources();
-#endif
-
- CloseInput();
-
- for (i = 0; i < screenInfo.numScreens; i++)
- screenInfo.screens[i]->root = NullWindow;
- CloseDownDevices();
- CloseDownEvents();
-
- for (i = screenInfo.numScreens - 1; i >= 0; i--)
- {
- FreeScratchPixmapsForScreen(i);
- FreeGCperDepth(i);
- FreeDefaultStipple(i);
- (* screenInfo.screens[i]->CloseScreen)(i, screenInfo.screens[i]);
- dixFreePrivates(screenInfo.screens[i]->devPrivates, PRIVATE_SCREEN);
- free(screenInfo.screens[i]);
- screenInfo.numScreens = i;
- }
-
- dixFreePrivates(serverClient->devPrivates, PRIVATE_CLIENT);
- serverClient->devPrivates = NULL;
-
- FreeFonts();
-
- FreeAuditTimer();
-
- if (dispatchException & DE_TERMINATE)
- {
- CloseWellKnownConnections();
- }
-
- OsCleanup((dispatchException & DE_TERMINATE) != 0);
-
- if (dispatchException & DE_TERMINATE)
- {
- ddxGiveUp();
- break;
- }
-
- free(ConnectionInfo);
- ConnectionInfo = NULL;
- }
- return 0;
-}
-
+/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission 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 that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY 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 THIS +SOFTWARE. + +******************************************************************/ + +/* The panoramix components contained the following notice */ +/***************************************************************** + +Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING, +BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of Digital Equipment Corporation +shall not be used in advertising or otherwise to promote the sale, use or other +dealings in this Software without prior written authorization from Digital +Equipment Corporation. + +******************************************************************/ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#include <version-config.h> +#endif + +#include <X11/X.h> +#include <X11/Xos.h> /* for unistd.h */ +#include <X11/Xproto.h> +#include <pixman.h> +#include "scrnintstr.h" +#include "misc.h" +#include "os.h" +#include "windowstr.h" +#include "resource.h" +#include "dixstruct.h" +#include "gcstruct.h" +#include "extension.h" +#include "colormap.h" +#include "colormapst.h" +#include "cursorstr.h" +#include "selection.h" +#include <X11/fonts/font.h> +#include "opaque.h" +#include "servermd.h" +#include "hotplug.h" +#include "site.h" +#include "dixfont.h" +#include "extnsionst.h" +#include "privates.h" +#include "registry.h" +#include "client.h" +#ifdef PANORAMIX +#include "panoramiXsrv.h" +#else +#include "dixevents.h" /* InitEvents() */ +#endif + +#ifdef DPMSExtension +#include <X11/extensions/dpmsconst.h> +#include "dpmsproc.h" +#endif + +extern void Dispatch(void); + +#ifdef XQUARTZ +#include <pthread.h> + +BOOL serverInitComplete = FALSE; +pthread_mutex_t serverInitCompleteMutex = PTHREAD_MUTEX_INITIALIZER; +pthread_cond_t serverInitCompleteCond = PTHREAD_COND_INITIALIZER; + +int dix_main(int argc, char *argv[], char *envp[]); + +int dix_main(int argc, char *argv[], char *envp[]) +#else +int main(int argc, char *argv[], char *envp[]) +#endif +{ + int i; + HWEventQueueType alwaysCheckForInput[2]; + + display = "0"; + + InitRegions(); + + pixman_disable_out_of_bounds_workaround(); + + CheckUserParameters(argc, argv, envp); + + CheckUserAuthorization(); + + InitConnectionLimits(); + + ProcessCommandLine(argc, argv); + + alwaysCheckForInput[0] = 0; + alwaysCheckForInput[1] = 1; + while(1) + { + serverGeneration++; + ScreenSaverTime = defaultScreenSaverTime; + ScreenSaverInterval = defaultScreenSaverInterval; + ScreenSaverBlanking = defaultScreenSaverBlanking; + ScreenSaverAllowExposures = defaultScreenSaverAllowExposures; +#ifdef DPMSExtension + DPMSStandbyTime = DPMSSuspendTime = DPMSOffTime = ScreenSaverTime; + DPMSEnabled = TRUE; + DPMSPowerLevel = 0; +#endif + InitBlockAndWakeupHandlers(); + /* Perform any operating system dependent initializations you'd like */ + OsInit(); + if(serverGeneration == 1) + { + CreateWellKnownSockets(); + for (i=1; i<MAXCLIENTS; i++) + clients[i] = NullClient; + serverClient = calloc(sizeof(ClientRec), 1); + if (!serverClient) + FatalError("couldn't create server client"); + InitClient(serverClient, 0, (pointer)NULL); + } + else + ResetWellKnownSockets (); + clients[0] = serverClient; + currentMaxClients = 1; + + /* Initialize privates before first allocation */ + dixResetPrivates(); + + /* Initialize server client devPrivates, to be reallocated as + * more client privates are registered + */ + if (!dixAllocatePrivates(&serverClient->devPrivates, PRIVATE_CLIENT)) + FatalError("failed to create server client privates"); + + if (!InitClientResources(serverClient)) /* for root resources */ + FatalError("couldn't init server resources"); + + SetInputCheck(&alwaysCheckForInput[0], &alwaysCheckForInput[1]); + screenInfo.numScreens = 0; + + InitAtoms(); + InitEvents(); + InitSelections(); + InitGlyphCaching(); + dixResetRegistry(); + ResetFontPrivateIndex(); + InitCallbackManager(); + InitOutput(&screenInfo, argc, argv); + + if (screenInfo.numScreens < 1) + FatalError("no screens found"); + InitExtensions(argc, argv); + + for (i = 0; i < screenInfo.numScreens; i++) + { + ScreenPtr pScreen = screenInfo.screens[i]; + if (!CreateScratchPixmapsForScreen(i)) + FatalError("failed to create scratch pixmaps"); + if (pScreen->CreateScreenResources && + !(*pScreen->CreateScreenResources)(pScreen)) + FatalError("failed to create screen resources"); + if (!CreateGCperDepth(i)) + FatalError("failed to create scratch GCs"); + if (!CreateDefaultStipple(i)) + FatalError("failed to create default stipple"); + if (!CreateRootWindow(pScreen)) + FatalError("failed to create root window"); + } + + InitFonts(); + if (SetDefaultFontPath(defaultFontPath) != Success) { + ErrorF("[dix] failed to set default font path '%s'", defaultFontPath); + } + if (!SetDefaultFont(defaultTextFont)) { + FatalError("could not open default font '%s'", defaultTextFont); + } + + if (!(rootCursor = CreateRootCursor(NULL, 0))) { + FatalError("could not open default cursor font '%s'", + defaultCursorFont); + } + +#ifdef DPMSExtension + /* check all screens, looking for DPMS Capabilities */ + DPMSCapableFlag = DPMSSupported(); + if (!DPMSCapableFlag) + DPMSEnabled = FALSE; +#endif + +#ifdef PANORAMIX + /* + * Consolidate window and colourmap information for each screen + */ + if (!noPanoramiXExtension) + PanoramiXConsolidate(); +#endif + + for (i = 0; i < screenInfo.numScreens; i++) + InitRootWindow(screenInfo.screens[i]->root); + + InitCoreDevices(); + InitInput(argc, argv); + InitAndStartDevices(); + ReserveClientIds(serverClient); + + dixSaveScreens(serverClient, SCREEN_SAVER_FORCER, ScreenSaverReset); + +#ifdef PANORAMIX + if (!noPanoramiXExtension) { + if (!PanoramiXCreateConnectionBlock()) { + FatalError("could not create connection block info"); + } + } else +#endif + { + if (!CreateConnectionBlock()) { + FatalError("could not create connection block info"); + } + } + +#ifdef XQUARTZ + /* Let the other threads know the server is done with its init */ + pthread_mutex_lock(&serverInitCompleteMutex); + serverInitComplete = TRUE; + pthread_cond_broadcast(&serverInitCompleteCond); + pthread_mutex_unlock(&serverInitCompleteMutex); +#endif + + NotifyParentProcess(); + + Dispatch(); + + UndisplayDevices(); + + /* Now free up whatever must be freed */ + if (screenIsSaved == SCREEN_SAVER_ON) + dixSaveScreens(serverClient, SCREEN_SAVER_OFF, ScreenSaverReset); + FreeScreenSaverTimer(); + CloseDownExtensions(); + +#ifdef PANORAMIX + { + Bool remember_it = noPanoramiXExtension; + noPanoramiXExtension = TRUE; + FreeAllResources(); + noPanoramiXExtension = remember_it; + } +#else + FreeAllResources(); +#endif + + CloseInput(); + + for (i = 0; i < screenInfo.numScreens; i++) + screenInfo.screens[i]->root = NullWindow; + CloseDownDevices(); + CloseDownEvents(); + + for (i = screenInfo.numScreens - 1; i >= 0; i--) + { + FreeScratchPixmapsForScreen(i); + FreeGCperDepth(i); + FreeDefaultStipple(i); + (* screenInfo.screens[i]->CloseScreen)(i, screenInfo.screens[i]); + dixFreePrivates(screenInfo.screens[i]->devPrivates, PRIVATE_SCREEN); + free(screenInfo.screens[i]); + screenInfo.numScreens = i; + } + + ReleaseClientIds(serverClient); + dixFreePrivates(serverClient->devPrivates, PRIVATE_CLIENT); + serverClient->devPrivates = NULL; + + FreeFonts(); + + FreeAuditTimer(); + + if (dispatchException & DE_TERMINATE) + { + CloseWellKnownConnections(); + } + + OsCleanup((dispatchException & DE_TERMINATE) != 0); + + if (dispatchException & DE_TERMINATE) + { + ddxGiveUp(); + break; + } + + free(ConnectionInfo); + ConnectionInfo = NULL; + } + return 0; +} + diff --git a/xorg-server/dix/ptrveloc.c b/xorg-server/dix/ptrveloc.c index 9a8737cf4..e6ac2ed14 100644 --- a/xorg-server/dix/ptrveloc.c +++ b/xorg-server/dix/ptrveloc.c @@ -1,1175 +1,1197 @@ -/*
- *
- * Copyright © 2006-2009 Simon Thum simon dot thum at gmx dot de
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#include <math.h>
-#include <ptrveloc.h>
-#include <exevents.h>
-#include <X11/Xatom.h>
-
-#include <xserver-properties.h>
-
-/*****************************************************************************
- * Predictable pointer acceleration
- *
- * 2006-2009 by Simon Thum (simon [dot] thum [at] gmx de)
- *
- * Serves 3 complementary functions:
- * 1) provide a sophisticated ballistic velocity estimate to improve
- * the relation between velocity (of the device) and acceleration
- * 2) make arbitrary acceleration profiles possible
- * 3) decelerate by two means (constant and adaptive) if enabled
- *
- * Important concepts are the
- *
- * - Scheme
- * which selects the basic algorithm
- * (see devices.c/InitPointerAccelerationScheme)
- * - Profile
- * which returns an acceleration
- * for a given velocity
- *
- * The profile can be selected by the user at runtime.
- * The classic profile is intended to cleanly perform old-style
- * function selection (threshold =/!= 0)
- *
- ****************************************************************************/
-
-/* fwds */
-int
-SetAccelerationProfile(DeviceVelocityPtr vel, int profile_num);
-static float
-SimpleSmoothProfile(DeviceIntPtr dev, DeviceVelocityPtr vel, float velocity,
- float threshold, float acc);
-static PointerAccelerationProfileFunc
-GetAccelerationProfile(DeviceVelocityPtr vel, int profile_num);
-
-/*#define PTRACCEL_DEBUGGING*/
-
-#ifdef PTRACCEL_DEBUGGING
-#define DebugAccelF ErrorF
-#else
-#define DebugAccelF(...) /* */
-#endif
-
-/********************************
- * Init/Uninit
- *******************************/
-
-/* some int which is not a profile number */
-#define PROFILE_UNINITIALIZE (-100)
-
-
-/**
- * Init struct so it should match the average case
- */
-void
-InitVelocityData(DeviceVelocityPtr vel)
-{
- memset(vel, 0, sizeof(DeviceVelocityRec));
-
- vel->corr_mul = 10.0; /* dots per 10 milisecond should be usable */
- vel->const_acceleration = 1.0; /* no acceleration/deceleration */
- vel->reset_time = 300;
- vel->use_softening = 1;
- vel->min_acceleration = 1.0; /* don't decelerate */
- vel->max_rel_diff = 0.2;
- vel->max_diff = 1.0;
- vel->initial_range = 2;
- vel->average_accel = TRUE;
- SetAccelerationProfile(vel, AccelProfileClassic);
- InitTrackers(vel, 16);
-}
-
-
-/**
- * Clean up
- */
-void
-FreeVelocityData(DeviceVelocityPtr vel){
- free(vel->tracker);
- SetAccelerationProfile(vel, PROFILE_UNINITIALIZE);
-}
-
-
-/*
- * dix uninit helper, called through scheme
- */
-void
-AccelerationDefaultCleanup(DeviceIntPtr dev)
-{
- /*sanity check*/
- if( dev->valuator->accelScheme.AccelSchemeProc == acceleratePointerPredictable
- && dev->valuator->accelScheme.accelData != NULL){
- dev->valuator->accelScheme.AccelSchemeProc = NULL;
- FreeVelocityData(dev->valuator->accelScheme.accelData);
- free(dev->valuator->accelScheme.accelData);
- dev->valuator->accelScheme.accelData = NULL;
- DeletePredictableAccelerationProperties(dev);
- }
-}
-
-
-/*************************
- * Input property support
- ************************/
-
-/**
- * choose profile
- */
-static int
-AccelSetProfileProperty(DeviceIntPtr dev, Atom atom,
- XIPropertyValuePtr val, BOOL checkOnly)
-{
- DeviceVelocityPtr vel;
- int profile, *ptr = &profile;
- int rc;
- int nelem = 1;
-
- if (atom != XIGetKnownProperty(ACCEL_PROP_PROFILE_NUMBER))
- return Success;
-
- vel = GetDevicePredictableAccelData(dev);
- if (!vel)
- return BadValue;
- rc = XIPropToInt(val, &nelem, &ptr);
-
- if(checkOnly)
- {
- if (rc)
- return rc;
-
- if (GetAccelerationProfile(vel, profile) == NULL)
- return BadValue;
- } else
- SetAccelerationProfile(vel, profile);
-
- return Success;
-}
-
-static long
-AccelInitProfileProperty(DeviceIntPtr dev, DeviceVelocityPtr vel)
-{
- int profile = vel->statistics.profile_number;
- Atom prop_profile_number = XIGetKnownProperty(ACCEL_PROP_PROFILE_NUMBER);
-
- XIChangeDeviceProperty(dev, prop_profile_number, XA_INTEGER, 32,
- PropModeReplace, 1, &profile, FALSE);
- XISetDevicePropertyDeletable(dev, prop_profile_number, FALSE);
- return XIRegisterPropertyHandler(dev, AccelSetProfileProperty, NULL, NULL);
-}
-
-/**
- * constant deceleration
- */
-static int
-AccelSetDecelProperty(DeviceIntPtr dev, Atom atom,
- XIPropertyValuePtr val, BOOL checkOnly)
-{
- DeviceVelocityPtr vel;
- float v, *ptr = &v;
- int rc;
- int nelem = 1;
-
- if (atom != XIGetKnownProperty(ACCEL_PROP_CONSTANT_DECELERATION))
- return Success;
-
- vel = GetDevicePredictableAccelData(dev);
- if (!vel)
- return BadValue;
- rc = XIPropToFloat(val, &nelem, &ptr);
-
- if(checkOnly)
- {
- if (rc)
- return rc;
- return (v >= 1.0f) ? Success : BadValue;
- }
-
- if(v >= 1.0f)
- vel->const_acceleration = 1/v;
-
- return Success;
-}
-
-static long
-AccelInitDecelProperty(DeviceIntPtr dev, DeviceVelocityPtr vel)
-{
- float fval = 1.0/vel->const_acceleration;
- Atom prop_const_decel = XIGetKnownProperty(ACCEL_PROP_CONSTANT_DECELERATION);
- XIChangeDeviceProperty(dev, prop_const_decel,
- XIGetKnownProperty(XATOM_FLOAT), 32,
- PropModeReplace, 1, &fval, FALSE);
- XISetDevicePropertyDeletable(dev, prop_const_decel, FALSE);
- return XIRegisterPropertyHandler(dev, AccelSetDecelProperty, NULL, NULL);
-}
-
-
-/**
- * adaptive deceleration
- */
-static int
-AccelSetAdaptDecelProperty(DeviceIntPtr dev, Atom atom,
- XIPropertyValuePtr val, BOOL checkOnly)
-{
- DeviceVelocityPtr veloc;
- float v, *ptr = &v;
- int rc;
- int nelem = 1;
-
- if (atom != XIGetKnownProperty(ACCEL_PROP_ADAPTIVE_DECELERATION))
- return Success;
-
- veloc = GetDevicePredictableAccelData(dev);
- if (!veloc)
- return BadValue;
- rc = XIPropToFloat(val, &nelem, &ptr);
-
- if(checkOnly)
- {
- if (rc)
- return rc;
- return (v >= 1.0f) ? Success : BadValue;
- }
-
- if(v >= 1.0f)
- veloc->min_acceleration = 1/v;
-
- return Success;
-}
-
-static long
-AccelInitAdaptDecelProperty(DeviceIntPtr dev, DeviceVelocityPtr vel)
-{
- float fval = 1.0/vel->min_acceleration;
- Atom prop_adapt_decel = XIGetKnownProperty(ACCEL_PROP_ADAPTIVE_DECELERATION);
-
- XIChangeDeviceProperty(dev, prop_adapt_decel, XIGetKnownProperty(XATOM_FLOAT), 32,
- PropModeReplace, 1, &fval, FALSE);
- XISetDevicePropertyDeletable(dev, prop_adapt_decel, FALSE);
- return XIRegisterPropertyHandler(dev, AccelSetAdaptDecelProperty, NULL, NULL);
-}
-
-
-/**
- * velocity scaling
- */
-static int
-AccelSetScaleProperty(DeviceIntPtr dev, Atom atom,
- XIPropertyValuePtr val, BOOL checkOnly)
-{
- DeviceVelocityPtr vel;
- float v, *ptr = &v;
- int rc;
- int nelem = 1;
-
- if (atom != XIGetKnownProperty(ACCEL_PROP_VELOCITY_SCALING))
- return Success;
-
- vel = GetDevicePredictableAccelData(dev);
- if (!vel)
- return BadValue;
- rc = XIPropToFloat(val, &nelem, &ptr);
-
- if (checkOnly)
- {
- if (rc)
- return rc;
-
- return (v > 0) ? Success : BadValue;
- }
-
- if(v > 0)
- vel->corr_mul = v;
-
- return Success;
-}
-
-static long
-AccelInitScaleProperty(DeviceIntPtr dev, DeviceVelocityPtr vel)
-{
- float fval = vel->corr_mul;
- Atom prop_velo_scale = XIGetKnownProperty(ACCEL_PROP_VELOCITY_SCALING);
-
- XIChangeDeviceProperty(dev, prop_velo_scale, XIGetKnownProperty(XATOM_FLOAT), 32,
- PropModeReplace, 1, &fval, FALSE);
- XISetDevicePropertyDeletable(dev, prop_velo_scale, FALSE);
- return XIRegisterPropertyHandler(dev, AccelSetScaleProperty, NULL, NULL);
-}
-
-BOOL
-InitializePredictableAccelerationProperties(DeviceIntPtr dev)
-{
- DeviceVelocityPtr vel = GetDevicePredictableAccelData(dev);
-
- if(!vel)
- return FALSE;
-
- vel->prop_handlers[0] = AccelInitProfileProperty(dev, vel);
- vel->prop_handlers[1] = AccelInitDecelProperty(dev, vel);
- vel->prop_handlers[2] = AccelInitAdaptDecelProperty(dev, vel);
- vel->prop_handlers[3] = AccelInitScaleProperty(dev, vel);
-
- return TRUE;
-}
-
-BOOL
-DeletePredictableAccelerationProperties(DeviceIntPtr dev)
-{
- DeviceVelocityPtr vel;
- Atom prop;
- int i;
-
- prop = XIGetKnownProperty(ACCEL_PROP_VELOCITY_SCALING);
- XIDeleteDeviceProperty(dev, prop, FALSE);
- prop = XIGetKnownProperty(ACCEL_PROP_ADAPTIVE_DECELERATION);
- XIDeleteDeviceProperty(dev, prop, FALSE);
- prop = XIGetKnownProperty(ACCEL_PROP_CONSTANT_DECELERATION);
- XIDeleteDeviceProperty(dev, prop, FALSE);
- prop = XIGetKnownProperty(ACCEL_PROP_PROFILE_NUMBER);
- XIDeleteDeviceProperty(dev, prop, FALSE);
-
- vel = GetDevicePredictableAccelData(dev);
- for (i = 0; vel && i < NPROPS_PREDICTABLE_ACCEL; i++)
- if (vel->prop_handlers[i])
- XIUnregisterPropertyHandler(dev, vel->prop_handlers[i]);
-
- return TRUE;
-}
-
-/*********************
- * Tracking logic
- ********************/
-
-void
-InitTrackers(DeviceVelocityPtr vel, int ntracker)
-{
- if(ntracker < 1){
- ErrorF("(dix ptracc) invalid number of trackers\n");
- return;
- }
- free(vel->tracker);
- vel->tracker = (MotionTrackerPtr)malloc(ntracker * sizeof(MotionTracker));
- memset(vel->tracker, 0, ntracker * sizeof(MotionTracker));
- vel->num_tracker = ntracker;
-}
-
-/**
- * return a bit field of possible directions.
- * 0 = N, 2 = E, 4 = S, 6 = W, in-between is as you guess.
- * There's no reason against widening to more precise directions (<45 degrees),
- * should it not perform well. All this is needed for is sort out non-linear
- * motion, so precision isn't paramount. However, one should not flag direction
- * too narrow, since it would then cut the linear segment to zero size way too
- * often.
- */
-static int
-DoGetDirection(int dx, int dy){
- float r;
- int i1, i2;
- /* on insignificant mickeys, flag 135 degrees */
- if(abs(dx) < 2 && abs(dy < 2)){
- /* first check diagonal cases */
- if(dx > 0 && dy > 0)
- return 4+8+16;
- if(dx > 0 && dy < 0)
- return 1+2+4;
- if(dx < 0 && dy < 0)
- return 1+128+64;
- if(dx < 0 && dy > 0)
- return 16+32+64;
- /* check axis-aligned directions */
- if(dx > 0)
- return 2+4+8; /*E*/
- if(dx < 0)
- return 128+64+32; /*W*/
- if(dy > 0)
- return 32+16+8; /*S*/
- if(dy < 0)
- return 128+1+2; /*N*/
- return 255; /* shouldn't happen */
- }
- /* else, compute angle and set appropriate flags */
-#ifdef _ISOC99_SOURCE
- r = atan2f(dy, dx);
-#else
- r = atan2(dy, dx);
-#endif
- /* find direction. We avoid r to become negative,
- * since C has no well-defined modulo for such cases. */
- r = (r+(M_PI*2.5))/(M_PI/4);
- /* this intends to flag 2 directions (90 degrees),
- * except on very well-aligned mickeys. */
- i1 = (int)(r+0.1) % 8;
- i2 = (int)(r+0.9) % 8;
- if(i1 < 0 || i1 > 7 || i2 < 0 || i2 > 7)
- return 255; /* shouldn't happen */
- return 1 << i1 | 1 << i2;
-}
-
-#define DIRECTION_CACHE_RANGE 5
-#define DIRECTION_CACHE_SIZE (DIRECTION_CACHE_RANGE*2+1)
-
-/* cache DoGetDirection(). */
-static int
-GetDirection(int dx, int dy){
- static int cache[DIRECTION_CACHE_SIZE][DIRECTION_CACHE_SIZE];
- int i;
- if (abs(dx) <= DIRECTION_CACHE_RANGE &&
- abs(dy) <= DIRECTION_CACHE_RANGE) {
- /* cacheable */
- i = cache[DIRECTION_CACHE_RANGE+dx][DIRECTION_CACHE_RANGE+dy];
- if(i != 0){
- return i;
- }else{
- i = DoGetDirection(dx, dy);
- cache[DIRECTION_CACHE_RANGE+dx][DIRECTION_CACHE_RANGE+dy] = i;
- return i;
- }
- }else{
- /* non-cacheable */
- return DoGetDirection(dx, dy);
- }
-}
-
-#undef DIRECTION_CACHE_RANGE
-#undef DIRECTION_CACHE_SIZE
-
-
-/* convert offset (age) to array index */
-#define TRACKER_INDEX(s, d) (((s)->num_tracker + (s)->cur_tracker - (d)) % (s)->num_tracker)
-
-static inline void
-FeedTrackers(DeviceVelocityPtr vel, int dx, int dy, int cur_t)
-{
- int n;
- for(n = 0; n < vel->num_tracker; n++){
- vel->tracker[n].dx += dx;
- vel->tracker[n].dy += dy;
- }
- n = (vel->cur_tracker + 1) % vel->num_tracker;
- vel->tracker[n].dx = 0;
- vel->tracker[n].dy = 0;
- vel->tracker[n].time = cur_t;
- vel->tracker[n].dir = GetDirection(dx, dy);
- DebugAccelF("(dix prtacc) motion [dx: %i dy: %i dir:%i diff: %i]\n",
- dx, dy, vel->tracker[n].dir,
- cur_t - vel->tracker[vel->cur_tracker].time);
- vel->cur_tracker = n;
-}
-
-/**
- * calc velocity for given tracker, with
- * velocity scaling.
- * This assumes linear motion.
- */
-static float
-CalcTracker(DeviceVelocityPtr vel, int offset, int cur_t){
- int index = TRACKER_INDEX(vel, offset);
- float dist = sqrt( vel->tracker[index].dx * vel->tracker[index].dx
- + vel->tracker[index].dy * vel->tracker[index].dy);
- int dtime = cur_t - vel->tracker[index].time;
- if(dtime > 0)
- return dist / dtime;
- else
- return 0;/* synonymous for NaN, since we're not C99 */
-}
-
-/* find the most plausible velocity. That is, the most distant
- * (in time) tracker which isn't too old, beyond a linear partition,
- * or simply too much off initial velocity.
- *
- * May return 0.
- */
-static float
-QueryTrackers(DeviceVelocityPtr vel, int cur_t){
- int n, offset, dir = 255, i = -1, age_ms;
- /* initial velocity: a low-offset, valid velocity */
- float iveloc = 0, res = 0, tmp, vdiff;
- float vfac = vel->corr_mul * vel->const_acceleration; /* premultiply */
- /* loop from current to older data */
- for(offset = 1; offset < vel->num_tracker; offset++){
- n = TRACKER_INDEX(vel, offset);
-
- age_ms = cur_t - vel->tracker[n].time;
-
- /* bail out if data is too old and protect from overrun */
- if (age_ms >= vel->reset_time || age_ms < 0) {
- DebugAccelF("(dix prtacc) query: tracker too old\n");
- break;
- }
-
- /*
- * this heuristic avoids using the linear-motion velocity formula
- * in CalcTracker() on motion that isn't exactly linear. So to get
- * even more precision we could subdivide as a final step, so possible
- * non-linearities are accounted for.
- */
- dir &= vel->tracker[n].dir;
- if(dir == 0){
- DebugAccelF("(dix prtacc) query: no longer linear\n");
- /* instead of breaking it we might also inspect the partition after,
- * but actual improvement with this is probably rare. */
- break;
- }
-
- tmp = CalcTracker(vel, offset, cur_t) * vfac;
-
- if ((iveloc == 0 || offset <= vel->initial_range) && tmp != 0) {
- /* set initial velocity and result */
- res = iveloc = tmp;
- i = offset;
- } else if (iveloc != 0 && tmp != 0) {
- vdiff = fabs(iveloc - tmp);
- if (vdiff <= vel->max_diff ||
- vdiff/(iveloc + tmp) < vel->max_rel_diff) {
- /* we're in range with the initial velocity,
- * so this result is likely better
- * (it contains more information). */
- res = tmp;
- i = offset;
- }else{
- /* we're not in range, quit - it won't get better. */
- DebugAccelF("(dix prtacc) query: tracker too different:"
- " old %2.2f initial %2.2f diff: %2.2f\n",
- tmp, iveloc, vdiff);
- break;
- }
- }
- }
- if(offset == vel->num_tracker){
- DebugAccelF("(dix prtacc) query: last tracker in effect\n");
- i = vel->num_tracker-1;
- }
- if(i>=0){
- n = TRACKER_INDEX(vel, i);
- DebugAccelF("(dix prtacc) result: offset %i [dx: %i dy: %i diff: %i]\n",
- i,
- vel->tracker[n].dx,
- vel->tracker[n].dy,
- cur_t - vel->tracker[n].time);
- }
- return res;
-}
-
-#undef TRACKER_INDEX
-
-/**
- * Perform velocity approximation based on 2D 'mickeys' (mouse motion delta).
- * return true if non-visible state reset is suggested
- */
-short
-ProcessVelocityData2D(
- DeviceVelocityPtr vel,
- int dx,
- int dy,
- int time)
-{
- float velocity;
-
- vel->last_velocity = vel->velocity;
-
- FeedTrackers(vel, dx, dy, time);
-
- velocity = QueryTrackers(vel, time);
-
- vel->velocity = velocity;
- return velocity == 0;
-}
-
-/**
- * this flattens significant ( > 1) mickeys a little bit for more steady
- * constant-velocity response
- */
-static inline float
-ApplySimpleSoftening(int od, int d)
-{
- float res = d;
- if (d <= 1 && d >= -1)
- return res;
- if (d > od)
- res -= 0.5;
- else if (d < od)
- res += 0.5;
- return res;
-}
-
-
-static void
-ApplySofteningAndConstantDeceleration(
- DeviceVelocityPtr vel,
- int dx,
- int dy,
- float* fdx,
- float* fdy,
- short do_soften)
-{
- if (do_soften && vel->use_softening) {
- *fdx = ApplySimpleSoftening(vel->last_dx, dx);
- *fdy = ApplySimpleSoftening(vel->last_dy, dy);
- } else {
- *fdx = dx;
- *fdy = dy;
- }
-
- *fdx *= vel->const_acceleration;
- *fdy *= vel->const_acceleration;
-}
-
-/*
- * compute the acceleration for given velocity and enforce min_acceleartion
- */
-float
-BasicComputeAcceleration(
- DeviceIntPtr dev,
- DeviceVelocityPtr vel,
- float velocity,
- float threshold,
- float acc){
-
- float result;
- result = vel->Profile(dev, vel, velocity, threshold, acc);
-
- /* enforce min_acceleration */
- if (result < vel->min_acceleration)
- result = vel->min_acceleration;
- return result;
-}
-
-/**
- * Compute acceleration. Takes into account averaging, nv-reset, etc.
- */
-static float
-ComputeAcceleration(
- DeviceIntPtr dev,
- DeviceVelocityPtr vel,
- float threshold,
- float acc){
- float res;
-
- if(vel->velocity <= 0){
- DebugAccelF("(dix ptracc) profile skipped\n");
- /*
- * If we have no idea about device velocity, don't pretend it.
- */
- return 1;
- }
-
- if(vel->average_accel && vel->velocity != vel->last_velocity){
- /* use simpson's rule to average acceleration between
- * current and previous velocity.
- * Though being the more natural choice, it causes a minor delay
- * in comparison, so it can be disabled. */
- res = BasicComputeAcceleration(
- dev, vel, vel->velocity, threshold, acc);
- res += BasicComputeAcceleration(
- dev, vel, vel->last_velocity, threshold, acc);
- res += 4.0f * BasicComputeAcceleration(dev, vel,
- (vel->last_velocity + vel->velocity) / 2,
- threshold, acc);
- res /= 6.0f;
- DebugAccelF("(dix ptracc) profile average [%.2f ... %.2f] is %.3f\n",
- vel->velocity, vel->last_velocity, res);
- return res;
- }else{
- res = BasicComputeAcceleration(dev, vel,
- vel->velocity, threshold, acc);
- DebugAccelF("(dix ptracc) profile sample [%.2f] is %.3f\n",
- vel->velocity, res);
- return res;
- }
-}
-
-
-/*****************************************
- * Acceleration functions and profiles
- ****************************************/
-
-/**
- * Polynomial function similar previous one, but with f(1) = 1
- */
-static float
-PolynomialAccelerationProfile(
- DeviceIntPtr dev,
- DeviceVelocityPtr vel,
- float velocity,
- float ignored,
- float acc)
-{
- return pow(velocity, (acc - 1.0) * 0.5);
-}
-
-
-/**
- * returns acceleration for velocity.
- * This profile selects the two functions like the old scheme did
- */
-static float
-ClassicProfile(
- DeviceIntPtr dev,
- DeviceVelocityPtr vel,
- float velocity,
- float threshold,
- float acc)
-{
- if (threshold > 0) {
- return SimpleSmoothProfile (dev,
- vel,
- velocity,
- threshold,
- acc);
- } else {
- return PolynomialAccelerationProfile (dev,
- vel,
- velocity,
- 0,
- acc);
- }
-}
-
-
-/**
- * Power profile
- * This has a completely smooth transition curve, i.e. no jumps in the
- * derivatives.
- *
- * This has the expense of overall response dependency on min-acceleration.
- * In effect, min_acceleration mimics const_acceleration in this profile.
- */
-static float
-PowerProfile(
- DeviceIntPtr dev,
- DeviceVelocityPtr vel,
- float velocity,
- float threshold,
- float acc)
-{
- float vel_dist;
-
- acc = (acc-1.0) * 0.1f + 1.0; /* without this, acc of 2 is unuseable */
-
- if (velocity <= threshold)
- return vel->min_acceleration;
- vel_dist = velocity - threshold;
- return (pow(acc, vel_dist)) * vel->min_acceleration;
-}
-
-
-/**
- * just a smooth function in [0..1] -> [0..1]
- * - point symmetry at 0.5
- * - f'(0) = f'(1) = 0
- * - starts faster than a sinoid
- * - smoothness C1 (Cinf if you dare to ignore endpoints)
- */
-static inline float
-CalcPenumbralGradient(float x){
- x *= 2.0f;
- x -= 1.0f;
- return 0.5f + (x * sqrt(1.0f - x*x) + asin(x))/M_PI;
-}
-
-
-/**
- * acceleration function similar to classic accelerated/unaccelerated,
- * but with smooth transition in between (and towards zero for adaptive dec.).
- */
-static float
-SimpleSmoothProfile(
- DeviceIntPtr dev,
- DeviceVelocityPtr vel,
- float velocity,
- float threshold,
- float acc)
-{
- if(velocity < 1.0f)
- return CalcPenumbralGradient(0.5 + velocity*0.5) * 2.0f - 1.0f;
- if(threshold < 1.0f)
- threshold = 1.0f;
- if (velocity <= threshold)
- return 1;
- velocity /= threshold;
- if (velocity >= acc)
- return acc;
- else
- return 1.0f + (CalcPenumbralGradient(velocity/acc) * (acc - 1.0f));
-}
-
-
-/**
- * This profile uses the first half of the penumbral gradient as a start
- * and then scales linearly.
- */
-static float
-SmoothLinearProfile(
- DeviceIntPtr dev,
- DeviceVelocityPtr vel,
- float velocity,
- float threshold,
- float acc)
-{
- float res, nv;
-
- if(acc > 1.0f)
- acc -= 1.0f; /*this is so acc = 1 is no acceleration */
- else
- return 1.0f;
-
- nv = (velocity - threshold) * acc * 0.5f;
-
- if(nv < 0){
- res = 0;
- }else if(nv < 2){
- res = CalcPenumbralGradient(nv*0.25f)*2.0f;
- }else{
- nv -= 2.0f;
- res = nv * 2.0f / M_PI /* steepness of gradient at 0.5 */
- + 1.0f; /* gradient crosses 2|1 */
- }
- res += vel->min_acceleration;
- return res;
-}
-
-
-/**
- * From 0 to threshold, the response graduates smoothly from min_accel to
- * acceleration. Beyond threshold it is exactly the specified acceleration.
- */
-static float
-SmoothLimitedProfile(
- DeviceIntPtr dev,
- DeviceVelocityPtr vel,
- float velocity,
- float threshold,
- float acc)
-{
- float res;
-
- if(velocity >= threshold || threshold == 0.0f)
- return acc;
-
- velocity /= threshold; /* should be [0..1[ now */
-
- res = CalcPenumbralGradient(velocity) * (acc - vel->min_acceleration);
-
- return vel->min_acceleration + res;
-}
-
-
-static float
-LinearProfile(
- DeviceIntPtr dev,
- DeviceVelocityPtr vel,
- float velocity,
- float threshold,
- float acc)
-{
- return acc * velocity;
-}
-
-static float
-NoProfile(
- DeviceIntPtr dev,
- DeviceVelocityPtr vel,
- float velocity,
- float threshold,
- float acc)
-{
- return 1.0f;
-}
-
-static PointerAccelerationProfileFunc
-GetAccelerationProfile(
- DeviceVelocityPtr vel,
- int profile_num)
-{
- switch(profile_num){
- case AccelProfileClassic:
- return ClassicProfile;
- case AccelProfileDeviceSpecific:
- return vel->deviceSpecificProfile;
- case AccelProfilePolynomial:
- return PolynomialAccelerationProfile;
- case AccelProfileSmoothLinear:
- return SmoothLinearProfile;
- case AccelProfileSimple:
- return SimpleSmoothProfile;
- case AccelProfilePower:
- return PowerProfile;
- case AccelProfileLinear:
- return LinearProfile;
- case AccelProfileSmoothLimited:
- return SmoothLimitedProfile;
- case AccelProfileNone:
- return NoProfile;
- default:
- return NULL;
- }
-}
-
-/**
- * Set the profile by number.
- * Intended to make profiles exchangeable at runtime.
- * If you created a profile, give it a number here and in the header to
- * make it selectable. In case some profile-specific init is needed, here
- * would be a good place, since FreeVelocityData() also calls this with
- * PROFILE_UNINITIALIZE.
- *
- * returns FALSE if profile number is unavailable, TRUE otherwise.
- */
-int
-SetAccelerationProfile(
- DeviceVelocityPtr vel,
- int profile_num)
-{
- PointerAccelerationProfileFunc profile;
- profile = GetAccelerationProfile(vel, profile_num);
-
- if(profile == NULL && profile_num != PROFILE_UNINITIALIZE)
- return FALSE;
-
- /* Here one could free old profile-private data */
- free(vel->profile_private);
- vel->profile_private = NULL;
- /* Here one could init profile-private data */
- vel->Profile = profile;
- vel->statistics.profile_number = profile_num;
- return TRUE;
-}
-
-/**********************************************
- * driver interaction
- **********************************************/
-
-
-/**
- * device-specific profile
- *
- * The device-specific profile is intended as a hook for a driver
- * which may want to provide an own acceleration profile.
- * It should not rely on profile-private data, instead
- * it should do init/uninit in the driver (ie. with DEVICE_INIT and friends).
- * Users may override or choose it.
- */
-void
-SetDeviceSpecificAccelerationProfile(
- DeviceVelocityPtr vel,
- PointerAccelerationProfileFunc profile)
-{
- if(vel)
- vel->deviceSpecificProfile = profile;
-}
-
-/**
- * Use this function to obtain a DeviceVelocityPtr for a device. Will return NULL if
- * the predictable acceleration scheme is not in effect.
- */
-DeviceVelocityPtr
-GetDevicePredictableAccelData(
- DeviceIntPtr dev)
-{
- /*sanity check*/
- if(!dev){
- ErrorF("[dix] accel: DeviceIntPtr was NULL");
- return NULL;
- }
- if( dev->valuator &&
- dev->valuator->accelScheme.AccelSchemeProc ==
- acceleratePointerPredictable &&
- dev->valuator->accelScheme.accelData != NULL){
-
- return (DeviceVelocityPtr)dev->valuator->accelScheme.accelData;
- }
- return NULL;
-}
-
-/********************************
- * acceleration schemes
- *******************************/
-
-/**
- * Modifies valuators in-place.
- * This version employs a velocity approximation algorithm to
- * enable fine-grained predictable acceleration profiles.
- */
-void
-acceleratePointerPredictable(
- DeviceIntPtr dev,
- int first_valuator,
- int num_valuators,
- int *valuators,
- int evtime)
-{
- float mult = 0.0;
- int dx = 0, dy = 0;
- int *px = NULL, *py = NULL;
- DeviceVelocityPtr velocitydata =
- (DeviceVelocityPtr) dev->valuator->accelScheme.accelData;
- float fdx, fdy, tmp; /* no need to init */
- Bool soften = TRUE;
-
- if (!num_valuators || !valuators || !velocitydata)
- return;
-
- if (velocitydata->statistics.profile_number == AccelProfileNone &&
- velocitydata->const_acceleration == 1.0f) {
- return; /*we're inactive anyway, so skip the whole thing.*/
- }
-
- if (first_valuator == 0) {
- dx = valuators[0];
- px = &valuators[0];
- }
- if (first_valuator <= 1 && num_valuators >= (2 - first_valuator)) {
- dy = valuators[1 - first_valuator];
- py = &valuators[1 - first_valuator];
- }
-
- if (dx || dy){
- /* reset non-visible state? */
- if (ProcessVelocityData2D(velocitydata, dx , dy, evtime)) {
- soften = FALSE;
- }
-
- if (dev->ptrfeed && dev->ptrfeed->ctrl.num) {
- /* invoke acceleration profile to determine acceleration */
- mult = ComputeAcceleration (dev, velocitydata,
- dev->ptrfeed->ctrl.threshold,
- (float)dev->ptrfeed->ctrl.num /
- (float)dev->ptrfeed->ctrl.den);
-
- if(mult != 1.0 || velocitydata->const_acceleration != 1.0) {
- ApplySofteningAndConstantDeceleration( velocitydata,
- dx, dy,
- &fdx, &fdy,
- (mult > 1.0) && soften);
-
- if (dx) {
- tmp = mult * fdx + dev->last.remainder[0];
- /* Since it may not be apparent: lrintf() does not offer
- * strong statements about rounding; however because we
- * process each axis conditionally, there's no danger
- * of a toggling remainder. Its lack of guarantees likely
- * makes it faster on the average target. */
- *px = lrintf(tmp);
- dev->last.remainder[0] = tmp - (float)*px;
- }
- if (dy) {
- tmp = mult * fdy + dev->last.remainder[1];
- *py = lrintf(tmp);
- dev->last.remainder[1] = tmp - (float)*py;
- }
- DebugAccelF("pos (%i | %i) remainders x: %.3f y: %.3f delta x:%.3f y:%.3f\n",
- *px, *py, dev->last.remainder[0], dev->last.remainder[1], fdx, fdy);
- }
- }
- }
- /* remember last motion delta (for softening/slow movement treatment) */
- velocitydata->last_dx = dx;
- velocitydata->last_dy = dy;
-}
-
-
-
-/**
- * Originally a part of xf86PostMotionEvent; modifies valuators
- * in-place. Retained mostly for embedded scenarios.
- */
-void
-acceleratePointerLightweight(
- DeviceIntPtr dev,
- int first_valuator,
- int num_valuators,
- int *valuators,
- int ignored)
-{
- float mult = 0.0;
- int dx = 0, dy = 0;
- int *px = NULL, *py = NULL;
-
- if (!num_valuators || !valuators)
- return;
-
- if (first_valuator == 0) {
- dx = valuators[0];
- px = &valuators[0];
- }
- if (first_valuator <= 1 && num_valuators >= (2 - first_valuator)) {
- dy = valuators[1 - first_valuator];
- py = &valuators[1 - first_valuator];
- }
-
- if (!dx && !dy)
- return;
-
- if (dev->ptrfeed && dev->ptrfeed->ctrl.num) {
- /* modeled from xf86Events.c */
- if (dev->ptrfeed->ctrl.threshold) {
- if ((abs(dx) + abs(dy)) >= dev->ptrfeed->ctrl.threshold) {
- dev->last.remainder[0] = ((float)dx *
- (float)(dev->ptrfeed->ctrl.num)) /
- (float)(dev->ptrfeed->ctrl.den) +
- dev->last.remainder[0];
- if (px) {
- *px = (int)dev->last.remainder[0];
- dev->last.remainder[0] = dev->last.remainder[0] -
- (float)(*px);
- }
-
- dev->last.remainder[1] = ((float)dy *
- (float)(dev->ptrfeed->ctrl.num)) /
- (float)(dev->ptrfeed->ctrl.den) +
- dev->last.remainder[1];
- if (py) {
- *py = (int)dev->last.remainder[1];
- dev->last.remainder[1] = dev->last.remainder[1] -
- (float)(*py);
- }
- }
- }
- else {
- mult = pow((float)dx * (float)dx + (float)dy * (float)dy,
- ((float)(dev->ptrfeed->ctrl.num) /
- (float)(dev->ptrfeed->ctrl.den) - 1.0) /
- 2.0) / 2.0;
- if (dx) {
- dev->last.remainder[0] = mult * (float)dx +
- dev->last.remainder[0];
- *px = (int)dev->last.remainder[0];
- dev->last.remainder[0] = dev->last.remainder[0] -
- (float)(*px);
- }
- if (dy) {
- dev->last.remainder[1] = mult * (float)dy +
- dev->last.remainder[1];
- *py = (int)dev->last.remainder[1];
- dev->last.remainder[1] = dev->last.remainder[1] -
- (float)(*py);
- }
- }
- }
-}
+/* + * + * Copyright © 2006-2009 Simon Thum simon dot thum at gmx dot de + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include <math.h> +#include <ptrveloc.h> +#include <exevents.h> +#include <X11/Xatom.h> + +#include <xserver-properties.h> + +/***************************************************************************** + * Predictable pointer acceleration + * + * 2006-2009 by Simon Thum (simon [dot] thum [at] gmx de) + * + * Serves 3 complementary functions: + * 1) provide a sophisticated ballistic velocity estimate to improve + * the relation between velocity (of the device) and acceleration + * 2) make arbitrary acceleration profiles possible + * 3) decelerate by two means (constant and adaptive) if enabled + * + * Important concepts are the + * + * - Scheme + * which selects the basic algorithm + * (see devices.c/InitPointerAccelerationScheme) + * - Profile + * which returns an acceleration + * for a given velocity + * + * The profile can be selected by the user at runtime. + * The classic profile is intended to cleanly perform old-style + * function selection (threshold =/!= 0) + * + ****************************************************************************/ + +/* fwds */ +int +SetAccelerationProfile(DeviceVelocityPtr vel, int profile_num); +static float +SimpleSmoothProfile(DeviceIntPtr dev, DeviceVelocityPtr vel, float velocity, + float threshold, float acc); +static PointerAccelerationProfileFunc +GetAccelerationProfile(DeviceVelocityPtr vel, int profile_num); +static BOOL +InitializePredictableAccelerationProperties(DeviceIntPtr dev); +static BOOL +DeletePredictableAccelerationProperties(DeviceIntPtr dev); + +/*#define PTRACCEL_DEBUGGING*/ + +#ifdef PTRACCEL_DEBUGGING +#define DebugAccelF ErrorF +#else +#define DebugAccelF(...) /* */ +#endif + +/******************************** + * Init/Uninit + *******************************/ + +/* some int which is not a profile number */ +#define PROFILE_UNINITIALIZE (-100) + + +/** + * Init DeviceVelocity struct so it should match the average case + */ +void +InitVelocityData(DeviceVelocityPtr vel) +{ + memset(vel, 0, sizeof(DeviceVelocityRec)); + + vel->corr_mul = 10.0; /* dots per 10 milisecond should be usable */ + vel->const_acceleration = 1.0; /* no acceleration/deceleration */ + vel->reset_time = 300; + vel->use_softening = 1; + vel->min_acceleration = 1.0; /* don't decelerate */ + vel->max_rel_diff = 0.2; + vel->max_diff = 1.0; + vel->initial_range = 2; + vel->average_accel = TRUE; + SetAccelerationProfile(vel, AccelProfileClassic); + InitTrackers(vel, 16); +} + + +/** + * Clean up DeviceVelocityRec + */ +void +FreeVelocityData(DeviceVelocityPtr vel){ + free(vel->tracker); + SetAccelerationProfile(vel, PROFILE_UNINITIALIZE); +} + + +/** + * Init predictable scheme + */ +Bool +InitPredictableAccelerationScheme(DeviceIntPtr dev, + ValuatorAccelerationPtr protoScheme) { + DeviceVelocityPtr vel; + ValuatorAccelerationRec scheme; + scheme = *protoScheme; + vel = calloc(1, sizeof(DeviceVelocityRec)); + if (!vel) + return FALSE; + InitVelocityData(vel); + scheme.accelData = vel; + dev->valuator->accelScheme = scheme; + InitializePredictableAccelerationProperties(dev); + return TRUE; +} + + +/** + * Uninit scheme + */ +void +AccelerationDefaultCleanup(DeviceIntPtr dev) +{ + /*sanity check*/ + if( dev->valuator->accelScheme.AccelSchemeProc == acceleratePointerPredictable + && dev->valuator->accelScheme.accelData != NULL){ + dev->valuator->accelScheme.AccelSchemeProc = NULL; + FreeVelocityData(dev->valuator->accelScheme.accelData); + free(dev->valuator->accelScheme.accelData); + dev->valuator->accelScheme.accelData = NULL; + DeletePredictableAccelerationProperties(dev); + } +} + + +/************************* + * Input property support + ************************/ + +/** + * choose profile + */ +static int +AccelSetProfileProperty(DeviceIntPtr dev, Atom atom, + XIPropertyValuePtr val, BOOL checkOnly) +{ + DeviceVelocityPtr vel; + int profile, *ptr = &profile; + int rc; + int nelem = 1; + + if (atom != XIGetKnownProperty(ACCEL_PROP_PROFILE_NUMBER)) + return Success; + + vel = GetDevicePredictableAccelData(dev); + if (!vel) + return BadValue; + rc = XIPropToInt(val, &nelem, &ptr); + + if(checkOnly) + { + if (rc) + return rc; + + if (GetAccelerationProfile(vel, profile) == NULL) + return BadValue; + } else + SetAccelerationProfile(vel, profile); + + return Success; +} + +static long +AccelInitProfileProperty(DeviceIntPtr dev, DeviceVelocityPtr vel) +{ + int profile = vel->statistics.profile_number; + Atom prop_profile_number = XIGetKnownProperty(ACCEL_PROP_PROFILE_NUMBER); + + XIChangeDeviceProperty(dev, prop_profile_number, XA_INTEGER, 32, + PropModeReplace, 1, &profile, FALSE); + XISetDevicePropertyDeletable(dev, prop_profile_number, FALSE); + return XIRegisterPropertyHandler(dev, AccelSetProfileProperty, NULL, NULL); +} + +/** + * constant deceleration + */ +static int +AccelSetDecelProperty(DeviceIntPtr dev, Atom atom, + XIPropertyValuePtr val, BOOL checkOnly) +{ + DeviceVelocityPtr vel; + float v, *ptr = &v; + int rc; + int nelem = 1; + + if (atom != XIGetKnownProperty(ACCEL_PROP_CONSTANT_DECELERATION)) + return Success; + + vel = GetDevicePredictableAccelData(dev); + if (!vel) + return BadValue; + rc = XIPropToFloat(val, &nelem, &ptr); + + if(checkOnly) + { + if (rc) + return rc; + return (v >= 1.0f) ? Success : BadValue; + } + + if(v >= 1.0f) + vel->const_acceleration = 1/v; + + return Success; +} + +static long +AccelInitDecelProperty(DeviceIntPtr dev, DeviceVelocityPtr vel) +{ + float fval = 1.0/vel->const_acceleration; + Atom prop_const_decel = XIGetKnownProperty(ACCEL_PROP_CONSTANT_DECELERATION); + XIChangeDeviceProperty(dev, prop_const_decel, + XIGetKnownProperty(XATOM_FLOAT), 32, + PropModeReplace, 1, &fval, FALSE); + XISetDevicePropertyDeletable(dev, prop_const_decel, FALSE); + return XIRegisterPropertyHandler(dev, AccelSetDecelProperty, NULL, NULL); +} + + +/** + * adaptive deceleration + */ +static int +AccelSetAdaptDecelProperty(DeviceIntPtr dev, Atom atom, + XIPropertyValuePtr val, BOOL checkOnly) +{ + DeviceVelocityPtr veloc; + float v, *ptr = &v; + int rc; + int nelem = 1; + + if (atom != XIGetKnownProperty(ACCEL_PROP_ADAPTIVE_DECELERATION)) + return Success; + + veloc = GetDevicePredictableAccelData(dev); + if (!veloc) + return BadValue; + rc = XIPropToFloat(val, &nelem, &ptr); + + if(checkOnly) + { + if (rc) + return rc; + return (v >= 1.0f) ? Success : BadValue; + } + + if(v >= 1.0f) + veloc->min_acceleration = 1/v; + + return Success; +} + +static long +AccelInitAdaptDecelProperty(DeviceIntPtr dev, DeviceVelocityPtr vel) +{ + float fval = 1.0/vel->min_acceleration; + Atom prop_adapt_decel = XIGetKnownProperty(ACCEL_PROP_ADAPTIVE_DECELERATION); + + XIChangeDeviceProperty(dev, prop_adapt_decel, XIGetKnownProperty(XATOM_FLOAT), 32, + PropModeReplace, 1, &fval, FALSE); + XISetDevicePropertyDeletable(dev, prop_adapt_decel, FALSE); + return XIRegisterPropertyHandler(dev, AccelSetAdaptDecelProperty, NULL, NULL); +} + + +/** + * velocity scaling + */ +static int +AccelSetScaleProperty(DeviceIntPtr dev, Atom atom, + XIPropertyValuePtr val, BOOL checkOnly) +{ + DeviceVelocityPtr vel; + float v, *ptr = &v; + int rc; + int nelem = 1; + + if (atom != XIGetKnownProperty(ACCEL_PROP_VELOCITY_SCALING)) + return Success; + + vel = GetDevicePredictableAccelData(dev); + if (!vel) + return BadValue; + rc = XIPropToFloat(val, &nelem, &ptr); + + if (checkOnly) + { + if (rc) + return rc; + + return (v > 0) ? Success : BadValue; + } + + if(v > 0) + vel->corr_mul = v; + + return Success; +} + +static long +AccelInitScaleProperty(DeviceIntPtr dev, DeviceVelocityPtr vel) +{ + float fval = vel->corr_mul; + Atom prop_velo_scale = XIGetKnownProperty(ACCEL_PROP_VELOCITY_SCALING); + + XIChangeDeviceProperty(dev, prop_velo_scale, XIGetKnownProperty(XATOM_FLOAT), 32, + PropModeReplace, 1, &fval, FALSE); + XISetDevicePropertyDeletable(dev, prop_velo_scale, FALSE); + return XIRegisterPropertyHandler(dev, AccelSetScaleProperty, NULL, NULL); +} + +BOOL +InitializePredictableAccelerationProperties(DeviceIntPtr dev) +{ + DeviceVelocityPtr vel = GetDevicePredictableAccelData(dev); + + if(!vel) + return FALSE; + + vel->prop_handlers[0] = AccelInitProfileProperty(dev, vel); + vel->prop_handlers[1] = AccelInitDecelProperty(dev, vel); + vel->prop_handlers[2] = AccelInitAdaptDecelProperty(dev, vel); + vel->prop_handlers[3] = AccelInitScaleProperty(dev, vel); + + return TRUE; +} + +BOOL +DeletePredictableAccelerationProperties(DeviceIntPtr dev) +{ + DeviceVelocityPtr vel; + Atom prop; + int i; + + prop = XIGetKnownProperty(ACCEL_PROP_VELOCITY_SCALING); + XIDeleteDeviceProperty(dev, prop, FALSE); + prop = XIGetKnownProperty(ACCEL_PROP_ADAPTIVE_DECELERATION); + XIDeleteDeviceProperty(dev, prop, FALSE); + prop = XIGetKnownProperty(ACCEL_PROP_CONSTANT_DECELERATION); + XIDeleteDeviceProperty(dev, prop, FALSE); + prop = XIGetKnownProperty(ACCEL_PROP_PROFILE_NUMBER); + XIDeleteDeviceProperty(dev, prop, FALSE); + + vel = GetDevicePredictableAccelData(dev); + for (i = 0; vel && i < NPROPS_PREDICTABLE_ACCEL; i++) + if (vel->prop_handlers[i]) + XIUnregisterPropertyHandler(dev, vel->prop_handlers[i]); + + return TRUE; +} + +/********************* + * Tracking logic + ********************/ + +void +InitTrackers(DeviceVelocityPtr vel, int ntracker) +{ + if(ntracker < 1){ + ErrorF("(dix ptracc) invalid number of trackers\n"); + return; + } + free(vel->tracker); + vel->tracker = (MotionTrackerPtr)malloc(ntracker * sizeof(MotionTracker)); + memset(vel->tracker, 0, ntracker * sizeof(MotionTracker)); + vel->num_tracker = ntracker; +} + +/** + * return a bit field of possible directions. + * 0 = N, 2 = E, 4 = S, 6 = W, in-between is as you guess. + * There's no reason against widening to more precise directions (<45 degrees), + * should it not perform well. All this is needed for is sort out non-linear + * motion, so precision isn't paramount. However, one should not flag direction + * too narrow, since it would then cut the linear segment to zero size way too + * often. + */ +static int +DoGetDirection(int dx, int dy){ + float r; + int i1, i2; + /* on insignificant mickeys, flag 135 degrees */ + if(abs(dx) < 2 && abs(dy < 2)){ + /* first check diagonal cases */ + if(dx > 0 && dy > 0) + return 4+8+16; + if(dx > 0 && dy < 0) + return 1+2+4; + if(dx < 0 && dy < 0) + return 1+128+64; + if(dx < 0 && dy > 0) + return 16+32+64; + /* check axis-aligned directions */ + if(dx > 0) + return 2+4+8; /*E*/ + if(dx < 0) + return 128+64+32; /*W*/ + if(dy > 0) + return 32+16+8; /*S*/ + if(dy < 0) + return 128+1+2; /*N*/ + return 255; /* shouldn't happen */ + } + /* else, compute angle and set appropriate flags */ +#ifdef _ISOC99_SOURCE + r = atan2f(dy, dx); +#else + r = atan2(dy, dx); +#endif + /* find direction. We avoid r to become negative, + * since C has no well-defined modulo for such cases. */ + r = (r+(M_PI*2.5))/(M_PI/4); + /* this intends to flag 2 directions (90 degrees), + * except on very well-aligned mickeys. */ + i1 = (int)(r+0.1) % 8; + i2 = (int)(r+0.9) % 8; + if(i1 < 0 || i1 > 7 || i2 < 0 || i2 > 7) + return 255; /* shouldn't happen */ + return 1 << i1 | 1 << i2; +} + +#define DIRECTION_CACHE_RANGE 5 +#define DIRECTION_CACHE_SIZE (DIRECTION_CACHE_RANGE*2+1) + +/* cache DoGetDirection(). */ +static int +GetDirection(int dx, int dy){ + static int cache[DIRECTION_CACHE_SIZE][DIRECTION_CACHE_SIZE]; + int i; + if (abs(dx) <= DIRECTION_CACHE_RANGE && + abs(dy) <= DIRECTION_CACHE_RANGE) { + /* cacheable */ + i = cache[DIRECTION_CACHE_RANGE+dx][DIRECTION_CACHE_RANGE+dy]; + if(i != 0){ + return i; + }else{ + i = DoGetDirection(dx, dy); + cache[DIRECTION_CACHE_RANGE+dx][DIRECTION_CACHE_RANGE+dy] = i; + return i; + } + }else{ + /* non-cacheable */ + return DoGetDirection(dx, dy); + } +} + +#undef DIRECTION_CACHE_RANGE +#undef DIRECTION_CACHE_SIZE + + +/* convert offset (age) to array index */ +#define TRACKER_INDEX(s, d) (((s)->num_tracker + (s)->cur_tracker - (d)) % (s)->num_tracker) + +static inline void +FeedTrackers(DeviceVelocityPtr vel, int dx, int dy, int cur_t) +{ + int n; + for(n = 0; n < vel->num_tracker; n++){ + vel->tracker[n].dx += dx; + vel->tracker[n].dy += dy; + } + n = (vel->cur_tracker + 1) % vel->num_tracker; + vel->tracker[n].dx = 0; + vel->tracker[n].dy = 0; + vel->tracker[n].time = cur_t; + vel->tracker[n].dir = GetDirection(dx, dy); + DebugAccelF("(dix prtacc) motion [dx: %i dy: %i dir:%i diff: %i]\n", + dx, dy, vel->tracker[n].dir, + cur_t - vel->tracker[vel->cur_tracker].time); + vel->cur_tracker = n; +} + +/** + * calc velocity for given tracker, with + * velocity scaling. + * This assumes linear motion. + */ +static float +CalcTracker(DeviceVelocityPtr vel, int offset, int cur_t){ + int index = TRACKER_INDEX(vel, offset); + float dist = sqrt( vel->tracker[index].dx * vel->tracker[index].dx + + vel->tracker[index].dy * vel->tracker[index].dy); + int dtime = cur_t - vel->tracker[index].time; + if(dtime > 0) + return dist / dtime; + else + return 0;/* synonymous for NaN, since we're not C99 */ +} + +/* find the most plausible velocity. That is, the most distant + * (in time) tracker which isn't too old, beyond a linear partition, + * or simply too much off initial velocity. + * + * May return 0. + */ +static float +QueryTrackers(DeviceVelocityPtr vel, int cur_t){ + int n, offset, dir = 255, i = -1, age_ms; + /* initial velocity: a low-offset, valid velocity */ + float iveloc = 0, res = 0, tmp, vdiff; + float vfac = vel->corr_mul * vel->const_acceleration; /* premultiply */ + /* loop from current to older data */ + for(offset = 1; offset < vel->num_tracker; offset++){ + n = TRACKER_INDEX(vel, offset); + + age_ms = cur_t - vel->tracker[n].time; + + /* bail out if data is too old and protect from overrun */ + if (age_ms >= vel->reset_time || age_ms < 0) { + DebugAccelF("(dix prtacc) query: tracker too old\n"); + break; + } + + /* + * this heuristic avoids using the linear-motion velocity formula + * in CalcTracker() on motion that isn't exactly linear. So to get + * even more precision we could subdivide as a final step, so possible + * non-linearities are accounted for. + */ + dir &= vel->tracker[n].dir; + if(dir == 0){ + DebugAccelF("(dix prtacc) query: no longer linear\n"); + /* instead of breaking it we might also inspect the partition after, + * but actual improvement with this is probably rare. */ + break; + } + + tmp = CalcTracker(vel, offset, cur_t) * vfac; + + if ((iveloc == 0 || offset <= vel->initial_range) && tmp != 0) { + /* set initial velocity and result */ + res = iveloc = tmp; + i = offset; + } else if (iveloc != 0 && tmp != 0) { + vdiff = fabs(iveloc - tmp); + if (vdiff <= vel->max_diff || + vdiff/(iveloc + tmp) < vel->max_rel_diff) { + /* we're in range with the initial velocity, + * so this result is likely better + * (it contains more information). */ + res = tmp; + i = offset; + }else{ + /* we're not in range, quit - it won't get better. */ + DebugAccelF("(dix prtacc) query: tracker too different:" + " old %2.2f initial %2.2f diff: %2.2f\n", + tmp, iveloc, vdiff); + break; + } + } + } + if(offset == vel->num_tracker){ + DebugAccelF("(dix prtacc) query: last tracker in effect\n"); + i = vel->num_tracker-1; + } + if(i>=0){ + n = TRACKER_INDEX(vel, i); + DebugAccelF("(dix prtacc) result: offset %i [dx: %i dy: %i diff: %i]\n", + i, + vel->tracker[n].dx, + vel->tracker[n].dy, + cur_t - vel->tracker[n].time); + } + return res; +} + +#undef TRACKER_INDEX + +/** + * Perform velocity approximation based on 2D 'mickeys' (mouse motion delta). + * return true if non-visible state reset is suggested + */ +short +ProcessVelocityData2D( + DeviceVelocityPtr vel, + int dx, + int dy, + int time) +{ + float velocity; + + vel->last_velocity = vel->velocity; + + FeedTrackers(vel, dx, dy, time); + + velocity = QueryTrackers(vel, time); + + vel->velocity = velocity; + return velocity == 0; +} + +/** + * this flattens significant ( > 1) mickeys a little bit for more steady + * constant-velocity response + */ +static inline float +ApplySimpleSoftening(int od, int d) +{ + float res = d; + if (d <= 1 && d >= -1) + return res; + if (d > od) + res -= 0.5; + else if (d < od) + res += 0.5; + return res; +} + + +static void +ApplySofteningAndConstantDeceleration( + DeviceVelocityPtr vel, + int dx, + int dy, + float* fdx, + float* fdy, + short do_soften) +{ + if (do_soften && vel->use_softening) { + *fdx = ApplySimpleSoftening(vel->last_dx, dx); + *fdy = ApplySimpleSoftening(vel->last_dy, dy); + } else { + *fdx = dx; + *fdy = dy; + } + + *fdx *= vel->const_acceleration; + *fdy *= vel->const_acceleration; +} + +/* + * compute the acceleration for given velocity and enforce min_acceleartion + */ +float +BasicComputeAcceleration( + DeviceIntPtr dev, + DeviceVelocityPtr vel, + float velocity, + float threshold, + float acc){ + + float result; + result = vel->Profile(dev, vel, velocity, threshold, acc); + + /* enforce min_acceleration */ + if (result < vel->min_acceleration) + result = vel->min_acceleration; + return result; +} + +/** + * Compute acceleration. Takes into account averaging, nv-reset, etc. + */ +static float +ComputeAcceleration( + DeviceIntPtr dev, + DeviceVelocityPtr vel, + float threshold, + float acc){ + float res; + + if(vel->velocity <= 0){ + DebugAccelF("(dix ptracc) profile skipped\n"); + /* + * If we have no idea about device velocity, don't pretend it. + */ + return 1; + } + + if(vel->average_accel && vel->velocity != vel->last_velocity){ + /* use simpson's rule to average acceleration between + * current and previous velocity. + * Though being the more natural choice, it causes a minor delay + * in comparison, so it can be disabled. */ + res = BasicComputeAcceleration( + dev, vel, vel->velocity, threshold, acc); + res += BasicComputeAcceleration( + dev, vel, vel->last_velocity, threshold, acc); + res += 4.0f * BasicComputeAcceleration(dev, vel, + (vel->last_velocity + vel->velocity) / 2, + threshold, acc); + res /= 6.0f; + DebugAccelF("(dix ptracc) profile average [%.2f ... %.2f] is %.3f\n", + vel->velocity, vel->last_velocity, res); + return res; + }else{ + res = BasicComputeAcceleration(dev, vel, + vel->velocity, threshold, acc); + DebugAccelF("(dix ptracc) profile sample [%.2f] is %.3f\n", + vel->velocity, res); + return res; + } +} + + +/***************************************** + * Acceleration functions and profiles + ****************************************/ + +/** + * Polynomial function similar previous one, but with f(1) = 1 + */ +static float +PolynomialAccelerationProfile( + DeviceIntPtr dev, + DeviceVelocityPtr vel, + float velocity, + float ignored, + float acc) +{ + return pow(velocity, (acc - 1.0) * 0.5); +} + + +/** + * returns acceleration for velocity. + * This profile selects the two functions like the old scheme did + */ +static float +ClassicProfile( + DeviceIntPtr dev, + DeviceVelocityPtr vel, + float velocity, + float threshold, + float acc) +{ + if (threshold > 0) { + return SimpleSmoothProfile (dev, + vel, + velocity, + threshold, + acc); + } else { + return PolynomialAccelerationProfile (dev, + vel, + velocity, + 0, + acc); + } +} + + +/** + * Power profile + * This has a completely smooth transition curve, i.e. no jumps in the + * derivatives. + * + * This has the expense of overall response dependency on min-acceleration. + * In effect, min_acceleration mimics const_acceleration in this profile. + */ +static float +PowerProfile( + DeviceIntPtr dev, + DeviceVelocityPtr vel, + float velocity, + float threshold, + float acc) +{ + float vel_dist; + + acc = (acc-1.0) * 0.1f + 1.0; /* without this, acc of 2 is unuseable */ + + if (velocity <= threshold) + return vel->min_acceleration; + vel_dist = velocity - threshold; + return (pow(acc, vel_dist)) * vel->min_acceleration; +} + + +/** + * just a smooth function in [0..1] -> [0..1] + * - point symmetry at 0.5 + * - f'(0) = f'(1) = 0 + * - starts faster than a sinoid + * - smoothness C1 (Cinf if you dare to ignore endpoints) + */ +static inline float +CalcPenumbralGradient(float x){ + x *= 2.0f; + x -= 1.0f; + return 0.5f + (x * sqrt(1.0f - x*x) + asin(x))/M_PI; +} + + +/** + * acceleration function similar to classic accelerated/unaccelerated, + * but with smooth transition in between (and towards zero for adaptive dec.). + */ +static float +SimpleSmoothProfile( + DeviceIntPtr dev, + DeviceVelocityPtr vel, + float velocity, + float threshold, + float acc) +{ + if(velocity < 1.0f) + return CalcPenumbralGradient(0.5 + velocity*0.5) * 2.0f - 1.0f; + if(threshold < 1.0f) + threshold = 1.0f; + if (velocity <= threshold) + return 1; + velocity /= threshold; + if (velocity >= acc) + return acc; + else + return 1.0f + (CalcPenumbralGradient(velocity/acc) * (acc - 1.0f)); +} + + +/** + * This profile uses the first half of the penumbral gradient as a start + * and then scales linearly. + */ +static float +SmoothLinearProfile( + DeviceIntPtr dev, + DeviceVelocityPtr vel, + float velocity, + float threshold, + float acc) +{ + float res, nv; + + if(acc > 1.0f) + acc -= 1.0f; /*this is so acc = 1 is no acceleration */ + else + return 1.0f; + + nv = (velocity - threshold) * acc * 0.5f; + + if(nv < 0){ + res = 0; + }else if(nv < 2){ + res = CalcPenumbralGradient(nv*0.25f)*2.0f; + }else{ + nv -= 2.0f; + res = nv * 2.0f / M_PI /* steepness of gradient at 0.5 */ + + 1.0f; /* gradient crosses 2|1 */ + } + res += vel->min_acceleration; + return res; +} + + +/** + * From 0 to threshold, the response graduates smoothly from min_accel to + * acceleration. Beyond threshold it is exactly the specified acceleration. + */ +static float +SmoothLimitedProfile( + DeviceIntPtr dev, + DeviceVelocityPtr vel, + float velocity, + float threshold, + float acc) +{ + float res; + + if(velocity >= threshold || threshold == 0.0f) + return acc; + + velocity /= threshold; /* should be [0..1[ now */ + + res = CalcPenumbralGradient(velocity) * (acc - vel->min_acceleration); + + return vel->min_acceleration + res; +} + + +static float +LinearProfile( + DeviceIntPtr dev, + DeviceVelocityPtr vel, + float velocity, + float threshold, + float acc) +{ + return acc * velocity; +} + +static float +NoProfile( + DeviceIntPtr dev, + DeviceVelocityPtr vel, + float velocity, + float threshold, + float acc) +{ + return 1.0f; +} + +static PointerAccelerationProfileFunc +GetAccelerationProfile( + DeviceVelocityPtr vel, + int profile_num) +{ + switch(profile_num){ + case AccelProfileClassic: + return ClassicProfile; + case AccelProfileDeviceSpecific: + return vel->deviceSpecificProfile; + case AccelProfilePolynomial: + return PolynomialAccelerationProfile; + case AccelProfileSmoothLinear: + return SmoothLinearProfile; + case AccelProfileSimple: + return SimpleSmoothProfile; + case AccelProfilePower: + return PowerProfile; + case AccelProfileLinear: + return LinearProfile; + case AccelProfileSmoothLimited: + return SmoothLimitedProfile; + case AccelProfileNone: + return NoProfile; + default: + return NULL; + } +} + +/** + * Set the profile by number. + * Intended to make profiles exchangeable at runtime. + * If you created a profile, give it a number here and in the header to + * make it selectable. In case some profile-specific init is needed, here + * would be a good place, since FreeVelocityData() also calls this with + * PROFILE_UNINITIALIZE. + * + * returns FALSE if profile number is unavailable, TRUE otherwise. + */ +int +SetAccelerationProfile( + DeviceVelocityPtr vel, + int profile_num) +{ + PointerAccelerationProfileFunc profile; + profile = GetAccelerationProfile(vel, profile_num); + + if(profile == NULL && profile_num != PROFILE_UNINITIALIZE) + return FALSE; + + /* Here one could free old profile-private data */ + free(vel->profile_private); + vel->profile_private = NULL; + /* Here one could init profile-private data */ + vel->Profile = profile; + vel->statistics.profile_number = profile_num; + return TRUE; +} + +/********************************************** + * driver interaction + **********************************************/ + + +/** + * device-specific profile + * + * The device-specific profile is intended as a hook for a driver + * which may want to provide an own acceleration profile. + * It should not rely on profile-private data, instead + * it should do init/uninit in the driver (ie. with DEVICE_INIT and friends). + * Users may override or choose it. + */ +void +SetDeviceSpecificAccelerationProfile( + DeviceVelocityPtr vel, + PointerAccelerationProfileFunc profile) +{ + if(vel) + vel->deviceSpecificProfile = profile; +} + +/** + * Use this function to obtain a DeviceVelocityPtr for a device. Will return NULL if + * the predictable acceleration scheme is not in effect. + */ +DeviceVelocityPtr +GetDevicePredictableAccelData( + DeviceIntPtr dev) +{ + /*sanity check*/ + if(!dev){ + ErrorF("[dix] accel: DeviceIntPtr was NULL"); + return NULL; + } + if( dev->valuator && + dev->valuator->accelScheme.AccelSchemeProc == + acceleratePointerPredictable && + dev->valuator->accelScheme.accelData != NULL){ + + return (DeviceVelocityPtr)dev->valuator->accelScheme.accelData; + } + return NULL; +} + +/******************************** + * acceleration schemes + *******************************/ + +/** + * Modifies valuators in-place. + * This version employs a velocity approximation algorithm to + * enable fine-grained predictable acceleration profiles. + */ +void +acceleratePointerPredictable( + DeviceIntPtr dev, + int first_valuator, + int num_valuators, + int *valuators, + int evtime) +{ + float fdx, fdy, tmp, mult; /* no need to init */ + int dx = 0, dy = 0; + int *px = NULL, *py = NULL; + DeviceVelocityPtr velocitydata = GetDevicePredictableAccelData(dev); + Bool soften = TRUE; + + if (!num_valuators || !valuators || !velocitydata) + return; + + if (velocitydata->statistics.profile_number == AccelProfileNone && + velocitydata->const_acceleration == 1.0f) { + return; /*we're inactive anyway, so skip the whole thing.*/ + } + + if (first_valuator == 0) { + dx = valuators[0]; + px = &valuators[0]; + } + if (first_valuator <= 1 && num_valuators >= (2 - first_valuator)) { + dy = valuators[1 - first_valuator]; + py = &valuators[1 - first_valuator]; + } + + if (dx || dy){ + /* reset non-visible state? */ + if (ProcessVelocityData2D(velocitydata, dx , dy, evtime)) { + soften = FALSE; + } + + if (dev->ptrfeed && dev->ptrfeed->ctrl.num) { + /* invoke acceleration profile to determine acceleration */ + mult = ComputeAcceleration (dev, velocitydata, + dev->ptrfeed->ctrl.threshold, + (float)dev->ptrfeed->ctrl.num / + (float)dev->ptrfeed->ctrl.den); + + if(mult != 1.0f || velocitydata->const_acceleration != 1.0f) { + ApplySofteningAndConstantDeceleration( velocitydata, + dx, dy, + &fdx, &fdy, + (mult > 1.0f) && soften); + + if (dx) { + tmp = mult * fdx + dev->last.remainder[0]; + /* Since it may not be apparent: lrintf() does not offer + * strong statements about rounding; however because we + * process each axis conditionally, there's no danger + * of a toggling remainder. Its lack of guarantees likely + * makes it faster on the average target. */ + *px = lrintf(tmp); + dev->last.remainder[0] = tmp - (float)*px; + } + if (dy) { + tmp = mult * fdy + dev->last.remainder[1]; + *py = lrintf(tmp); + dev->last.remainder[1] = tmp - (float)*py; + } + DebugAccelF("pos (%i | %i) remainders x: %.3f y: %.3f delta x:%.3f y:%.3f\n", + *px, *py, dev->last.remainder[0], dev->last.remainder[1], fdx, fdy); + } + } + } + /* remember last motion delta (for softening/slow movement treatment) */ + velocitydata->last_dx = dx; + velocitydata->last_dy = dy; +} + + + +/** + * Originally a part of xf86PostMotionEvent; modifies valuators + * in-place. Retained mostly for embedded scenarios. + */ +void +acceleratePointerLightweight( + DeviceIntPtr dev, + int first_valuator, + int num_valuators, + int *valuators, + int ignored) +{ + float mult = 0.0; + int dx = 0, dy = 0; + int *px = NULL, *py = NULL; + + if (!num_valuators || !valuators) + return; + + if (first_valuator == 0) { + dx = valuators[0]; + px = &valuators[0]; + } + if (first_valuator <= 1 && num_valuators >= (2 - first_valuator)) { + dy = valuators[1 - first_valuator]; + py = &valuators[1 - first_valuator]; + } + + if (!dx && !dy) + return; + + if (dev->ptrfeed && dev->ptrfeed->ctrl.num) { + /* modeled from xf86Events.c */ + if (dev->ptrfeed->ctrl.threshold) { + if ((abs(dx) + abs(dy)) >= dev->ptrfeed->ctrl.threshold) { + dev->last.remainder[0] = ((float)dx * + (float)(dev->ptrfeed->ctrl.num)) / + (float)(dev->ptrfeed->ctrl.den) + + dev->last.remainder[0]; + if (px) { + *px = (int)dev->last.remainder[0]; + dev->last.remainder[0] = dev->last.remainder[0] - + (float)(*px); + } + + dev->last.remainder[1] = ((float)dy * + (float)(dev->ptrfeed->ctrl.num)) / + (float)(dev->ptrfeed->ctrl.den) + + dev->last.remainder[1]; + if (py) { + *py = (int)dev->last.remainder[1]; + dev->last.remainder[1] = dev->last.remainder[1] - + (float)(*py); + } + } + } + else { + mult = pow((float)dx * (float)dx + (float)dy * (float)dy, + ((float)(dev->ptrfeed->ctrl.num) / + (float)(dev->ptrfeed->ctrl.den) - 1.0) / + 2.0) / 2.0; + if (dx) { + dev->last.remainder[0] = mult * (float)dx + + dev->last.remainder[0]; + *px = (int)dev->last.remainder[0]; + dev->last.remainder[0] = dev->last.remainder[0] - + (float)(*px); + } + if (dy) { + dev->last.remainder[1] = mult * (float)dy + + dev->last.remainder[1]; + *py = (int)dev->last.remainder[1]; + dev->last.remainder[1] = dev->last.remainder[1] - + (float)(*py); + } + } + } +} diff --git a/xorg-server/dix/region.c b/xorg-server/dix/region.c index c0add6ca9..6820c1eac 100644 --- a/xorg-server/dix/region.c +++ b/xorg-server/dix/region.c @@ -1,1659 +1,1425 @@ -/***********************************************************
-
-Copyright 1987, 1988, 1989, 1998 The Open Group
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation.
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
-AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of The Open Group shall not be
-used in advertising or otherwise to promote the sale, use or other dealings
-in this Software without prior written authorization from The Open Group.
-
-
-Copyright 1987, 1988, 1989 by
-Digital Equipment Corporation, Maynard, Massachusetts.
-
- All Rights Reserved
-
-Permission 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 that
-both that copyright notice and this permission notice appear in
-supporting documentation, and that the name of Digital not be
-used in advertising or publicity pertaining to distribution of the
-software without specific, written prior permission.
-
-DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
-ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
-DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
-ANY 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 THIS
-SOFTWARE.
-
-******************************************************************/
-
-/* The panoramix components contained the following notice */
-/*****************************************************************
-
-Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software.
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING,
-BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY,
-WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
-IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of Digital Equipment Corporation
-shall not be used in advertising or otherwise to promote the sale, use or other
-dealings in this Software without prior written authorization from Digital
-Equipment Corporation.
-
-******************************************************************/
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#include "regionstr.h"
-#include <X11/Xprotostr.h>
-#include <X11/Xfuncproto.h>
-#include "gc.h"
-#include <pixman.h>
-
-#undef assert
-#ifdef REGION_DEBUG
-#define assert(expr) { \
- CARD32 *foo = NULL; \
- if (!(expr)) { \
- ErrorF("Assertion failed file %s, line %d: %s\n", \
- __FILE__, __LINE__, #expr); \
- *foo = 0xdeadbeef; /* to get a backtrace */ \
- } \
- }
-#else
-#define assert(expr)
-#endif
-
-#define good(reg) assert(RegionIsValid(reg))
-
-/*
- * The functions in this file implement the Region abstraction used extensively
- * throughout the X11 sample server. A Region is simply a set of disjoint
- * (non-overlapping) rectangles, plus an "extent" rectangle which is the
- * smallest single rectangle that contains all the non-overlapping rectangles.
- *
- * A Region is implemented as a "y-x-banded" array of rectangles. This array
- * imposes two degrees of order. First, all rectangles are sorted by top side
- * y coordinate first (y1), and then by left side x coordinate (x1).
- *
- * Furthermore, the rectangles are grouped into "bands". Each rectangle in a
- * band has the same top y coordinate (y1), and each has the same bottom y
- * coordinate (y2). Thus all rectangles in a band differ only in their left
- * and right side (x1 and x2). Bands are implicit in the array of rectangles:
- * there is no separate list of band start pointers.
- *
- * The y-x band representation does not minimize rectangles. In particular,
- * if a rectangle vertically crosses a band (the rectangle has scanlines in
- * the y1 to y2 area spanned by the band), then the rectangle may be broken
- * down into two or more smaller rectangles stacked one atop the other.
- *
- * ----------- -----------
- * | | | | band 0
- * | | -------- ----------- --------
- * | | | | in y-x banded | | | | band 1
- * | | | | form is | | | |
- * ----------- | | ----------- --------
- * | | | | band 2
- * -------- --------
- *
- * An added constraint on the rectangles is that they must cover as much
- * horizontal area as possible: no two rectangles within a band are allowed
- * to touch.
- *
- * Whenever possible, bands will be merged together to cover a greater vertical
- * distance (and thus reduce the number of rectangles). Two bands can be merged
- * only if the bottom of one touches the top of the other and they have
- * rectangles in the same places (of the same width, of course).
- *
- * Adam de Boor wrote most of the original region code. Joel McCormack
- * substantially modified or rewrote most of the core arithmetic routines,
- * and added RegionValidate in order to support several speed improvements
- * to miValidateTree. Bob Scheifler changed the representation to be more
- * compact when empty or a single rectangle, and did a bunch of gratuitous
- * reformatting.
- */
-
-/* true iff two Boxes overlap */
-#define EXTENTCHECK(r1,r2) \
- (!( ((r1)->x2 <= (r2)->x1) || \
- ((r1)->x1 >= (r2)->x2) || \
- ((r1)->y2 <= (r2)->y1) || \
- ((r1)->y1 >= (r2)->y2) ) )
-
-/* true iff (x,y) is in Box */
-#define INBOX(r,x,y) \
- ( ((r)->x2 > x) && \
- ((r)->x1 <= x) && \
- ((r)->y2 > y) && \
- ((r)->y1 <= y) )
-
-/* true iff Box r1 contains Box r2 */
-#define SUBSUMES(r1,r2) \
- ( ((r1)->x1 <= (r2)->x1) && \
- ((r1)->x2 >= (r2)->x2) && \
- ((r1)->y1 <= (r2)->y1) && \
- ((r1)->y2 >= (r2)->y2) )
-
-#define xallocData(n) malloc(RegionSizeof(n))
-#define xfreeData(reg) if ((reg)->data && (reg)->data->size) free((reg)->data)
-
-#define RECTALLOC_BAIL(pReg,n,bail) \
-if (!(pReg)->data || (((pReg)->data->numRects + (n)) > (pReg)->data->size)) \
- if (!RegionRectAlloc(pReg, n)) { goto bail; }
-
-#define RECTALLOC(pReg,n) \
-if (!(pReg)->data || (((pReg)->data->numRects + (n)) > (pReg)->data->size)) \
- if (!RegionRectAlloc(pReg, n)) { return FALSE; }
-
-#define ADDRECT(pNextRect,nx1,ny1,nx2,ny2) \
-{ \
- pNextRect->x1 = nx1; \
- pNextRect->y1 = ny1; \
- pNextRect->x2 = nx2; \
- pNextRect->y2 = ny2; \
- pNextRect++; \
-}
-
-#define NEWRECT(pReg,pNextRect,nx1,ny1,nx2,ny2) \
-{ \
- if (!(pReg)->data || ((pReg)->data->numRects == (pReg)->data->size))\
- { \
- if (!RegionRectAlloc(pReg, 1)) \
- return FALSE; \
- pNextRect = RegionTop(pReg); \
- } \
- ADDRECT(pNextRect,nx1,ny1,nx2,ny2); \
- pReg->data->numRects++; \
- assert(pReg->data->numRects<=pReg->data->size); \
-}
-
-
-#define DOWNSIZE(reg,numRects) \
-if (((numRects) < ((reg)->data->size >> 1)) && ((reg)->data->size > 50)) \
-{ \
- RegDataPtr NewData; \
- NewData = (RegDataPtr)realloc((reg)->data, RegionSizeof(numRects)); \
- if (NewData) \
- { \
- NewData->size = (numRects); \
- (reg)->data = NewData; \
- } \
-}
-
-
-BoxRec RegionEmptyBox = {0, 0, 0, 0};
-RegDataRec RegionEmptyData = {0, 0};
-
-RegDataRec RegionBrokenData = {0, 0};
-static RegionRec RegionBrokenRegion = { { 0, 0, 0, 0 }, &RegionBrokenData };
-
-void
-InitRegions (void)
-{
- pixman_region_set_static_pointers (&RegionEmptyBox, &RegionEmptyData, &RegionBrokenData);
-}
-
-/*****************************************************************
- * RegionCreate(rect, size)
- * This routine does a simple malloc to make a structure of
- * REGION of "size" number of rectangles.
- *****************************************************************/
-
-RegionPtr
-RegionCreate(BoxPtr rect, int size)
-{
- RegionPtr pReg;
-
- pReg = (RegionPtr)malloc(sizeof(RegionRec));
- if (!pReg)
- return &RegionBrokenRegion;
-
- RegionInit (pReg, rect, size);
-
- return pReg;
-}
-
-void
-RegionDestroy(RegionPtr pReg)
-{
- pixman_region_fini (pReg);
- if (pReg != &RegionBrokenRegion)
- free(pReg);
-}
-
-void
-RegionPrint(RegionPtr rgn)
-{
- int num, size;
- int i;
- BoxPtr rects;
-
- num = RegionNumRects(rgn);
- size = RegionSize(rgn);
- rects = RegionRects(rgn);
- ErrorF("[mi] num: %d size: %d\n", num, size);
- ErrorF("[mi] extents: %d %d %d %d\n",
- rgn->extents.x1, rgn->extents.y1, rgn->extents.x2, rgn->extents.y2);
- for (i = 0; i < num; i++)
- ErrorF("[mi] %d %d %d %d \n",
- rects[i].x1, rects[i].y1, rects[i].x2, rects[i].y2);
- ErrorF("[mi] \n");
-}
-
-#ifdef DEBUG
-Bool
-RegionIsValid(RegionPtr reg)
-{
- int i, numRects;
-
- if ((reg->extents.x1 > reg->extents.x2) ||
- (reg->extents.y1 > reg->extents.y2))
- return FALSE;
- numRects = RegionNumRects(reg);
- if (!numRects)
- return ((reg->extents.x1 == reg->extents.x2) &&
- (reg->extents.y1 == reg->extents.y2) &&
- (reg->data->size || (reg->data == &RegionEmptyData)));
- else if (numRects == 1)
- return !reg->data;
- else
- {
- BoxPtr pboxP, pboxN;
- BoxRec box;
-
- pboxP = RegionRects(reg);
- box = *pboxP;
- box.y2 = pboxP[numRects-1].y2;
- pboxN = pboxP + 1;
- for (i = numRects; --i > 0; pboxP++, pboxN++)
- {
- if ((pboxN->x1 >= pboxN->x2) ||
- (pboxN->y1 >= pboxN->y2))
- return FALSE;
- if (pboxN->x1 < box.x1)
- box.x1 = pboxN->x1;
- if (pboxN->x2 > box.x2)
- box.x2 = pboxN->x2;
- if ((pboxN->y1 < pboxP->y1) ||
- ((pboxN->y1 == pboxP->y1) &&
- ((pboxN->x1 < pboxP->x2) || (pboxN->y2 != pboxP->y2))))
- return FALSE;
- }
- return ((box.x1 == reg->extents.x1) &&
- (box.x2 == reg->extents.x2) &&
- (box.y1 == reg->extents.y1) &&
- (box.y2 == reg->extents.y2));
- }
-}
-#endif /* DEBUG */
-
-Bool
-RegionBreak (RegionPtr pReg)
-{
- xfreeData (pReg);
- pReg->extents = RegionEmptyBox;
- pReg->data = &RegionBrokenData;
- return FALSE;
-}
-
-Bool
-RegionRectAlloc(RegionPtr pRgn, int n)
-{
- RegDataPtr data;
-
- if (!pRgn->data)
- {
- n++;
- pRgn->data = xallocData(n);
- if (!pRgn->data)
- return RegionBreak (pRgn);
- pRgn->data->numRects = 1;
- *RegionBoxptr(pRgn) = pRgn->extents;
- }
- else if (!pRgn->data->size)
- {
- pRgn->data = xallocData(n);
- if (!pRgn->data)
- return RegionBreak (pRgn);
- pRgn->data->numRects = 0;
- }
- else
- {
- if (n == 1)
- {
- n = pRgn->data->numRects;
- if (n > 500) /* XXX pick numbers out of a hat */
- n = 250;
- }
- n += pRgn->data->numRects;
- data = (RegDataPtr)realloc(pRgn->data, RegionSizeof(n));
- if (!data)
- return RegionBreak (pRgn);
- pRgn->data = data;
- }
- pRgn->data->size = n;
- return TRUE;
-}
-
-/*======================================================================
- * Generic Region Operator
- *====================================================================*/
-
-/*-
- *-----------------------------------------------------------------------
- * RegionCoalesce --
- * Attempt to merge the boxes in the current band with those in the
- * previous one. We are guaranteed that the current band extends to
- * the end of the rects array. Used only by RegionOp.
- *
- * Results:
- * The new index for the previous band.
- *
- * Side Effects:
- * If coalescing takes place:
- * - rectangles in the previous band will have their y2 fields
- * altered.
- * - pReg->data->numRects will be decreased.
- *
- *-----------------------------------------------------------------------
- */
-_X_INLINE static int
-RegionCoalesce (
- RegionPtr pReg, /* Region to coalesce */
- int prevStart, /* Index of start of previous band */
- int curStart) /* Index of start of current band */
-{
- BoxPtr pPrevBox; /* Current box in previous band */
- BoxPtr pCurBox; /* Current box in current band */
- int numRects; /* Number rectangles in both bands */
- int y2; /* Bottom of current band */
- /*
- * Figure out how many rectangles are in the band.
- */
- numRects = curStart - prevStart;
- assert(numRects == pReg->data->numRects - curStart);
-
- if (!numRects) return curStart;
-
- /*
- * The bands may only be coalesced if the bottom of the previous
- * matches the top scanline of the current.
- */
- pPrevBox = RegionBox(pReg, prevStart);
- pCurBox = RegionBox(pReg, curStart);
- if (pPrevBox->y2 != pCurBox->y1) return curStart;
-
- /*
- * Make sure the bands have boxes in the same places. This
- * assumes that boxes have been added in such a way that they
- * cover the most area possible. I.e. two boxes in a band must
- * have some horizontal space between them.
- */
- y2 = pCurBox->y2;
-
- do {
- if ((pPrevBox->x1 != pCurBox->x1) || (pPrevBox->x2 != pCurBox->x2)) {
- return curStart;
- }
- pPrevBox++;
- pCurBox++;
- numRects--;
- } while (numRects);
-
- /*
- * The bands may be merged, so set the bottom y of each box
- * in the previous band to the bottom y of the current band.
- */
- numRects = curStart - prevStart;
- pReg->data->numRects -= numRects;
- do {
- pPrevBox--;
- pPrevBox->y2 = y2;
- numRects--;
- } while (numRects);
- return prevStart;
-}
-
-
-/* Quicky macro to avoid trivial reject procedure calls to RegionCoalesce */
-
-#define Coalesce(newReg, prevBand, curBand) \
- if (curBand - prevBand == newReg->data->numRects - curBand) { \
- prevBand = RegionCoalesce(newReg, prevBand, curBand); \
- } else { \
- prevBand = curBand; \
- }
-
-/*-
- *-----------------------------------------------------------------------
- * RegionAppendNonO --
- * Handle a non-overlapping band for the union and subtract operations.
- * Just adds the (top/bottom-clipped) rectangles into the region.
- * Doesn't have to check for subsumption or anything.
- *
- * Results:
- * None.
- *
- * Side Effects:
- * pReg->data->numRects is incremented and the rectangles overwritten
- * with the rectangles we're passed.
- *
- *-----------------------------------------------------------------------
- */
-
-_X_INLINE static Bool
-RegionAppendNonO (
- RegionPtr pReg,
- BoxPtr r,
- BoxPtr rEnd,
- int y1,
- int y2)
-{
- BoxPtr pNextRect;
- int newRects;
-
- newRects = rEnd - r;
-
- assert(y1 < y2);
- assert(newRects != 0);
-
- /* Make sure we have enough space for all rectangles to be added */
- RECTALLOC(pReg, newRects);
- pNextRect = RegionTop(pReg);
- pReg->data->numRects += newRects;
- do {
- assert(r->x1 < r->x2);
- ADDRECT(pNextRect, r->x1, y1, r->x2, y2);
- r++;
- } while (r != rEnd);
-
- return TRUE;
-}
-
-#define FindBand(r, rBandEnd, rEnd, ry1) \
-{ \
- ry1 = r->y1; \
- rBandEnd = r+1; \
- while ((rBandEnd != rEnd) && (rBandEnd->y1 == ry1)) { \
- rBandEnd++; \
- } \
-}
-
-#define AppendRegions(newReg, r, rEnd) \
-{ \
- int newRects; \
- if ((newRects = rEnd - r)) { \
- RECTALLOC(newReg, newRects); \
- memmove((char *)RegionTop(newReg),(char *)r, \
- newRects * sizeof(BoxRec)); \
- newReg->data->numRects += newRects; \
- } \
-}
-
-/*-
- *-----------------------------------------------------------------------
- * RegionOp --
- * Apply an operation to two regions. Called by RegionUnion, RegionInverse,
- * RegionSubtract, RegionIntersect.... Both regions MUST have at least one
- * rectangle, and cannot be the same object.
- *
- * Results:
- * TRUE if successful.
- *
- * Side Effects:
- * The new region is overwritten.
- * pOverlap set to TRUE if overlapFunc ever returns TRUE.
- *
- * Notes:
- * The idea behind this function is to view the two regions as sets.
- * Together they cover a rectangle of area that this function divides
- * into horizontal bands where points are covered only by one region
- * or by both. For the first case, the nonOverlapFunc is called with
- * each the band and the band's upper and lower extents. For the
- * second, the overlapFunc is called to process the entire band. It
- * is responsible for clipping the rectangles in the band, though
- * this function provides the boundaries.
- * At the end of each band, the new region is coalesced, if possible,
- * to reduce the number of rectangles in the region.
- *
- *-----------------------------------------------------------------------
- */
-
-typedef Bool (*OverlapProcPtr)(
- RegionPtr pReg,
- BoxPtr r1,
- BoxPtr r1End,
- BoxPtr r2,
- BoxPtr r2End,
- short y1,
- short y2,
- Bool *pOverlap);
-
-static Bool
-RegionOp(
- RegionPtr newReg, /* Place to store result */
- RegionPtr reg1, /* First region in operation */
- RegionPtr reg2, /* 2d region in operation */
- OverlapProcPtr overlapFunc, /* Function to call for over-
- * lapping bands */
- Bool appendNon1, /* Append non-overlapping bands */
- /* in region 1 ? */
- Bool appendNon2, /* Append non-overlapping bands */
- /* in region 2 ? */
- Bool *pOverlap)
-{
- BoxPtr r1; /* Pointer into first region */
- BoxPtr r2; /* Pointer into 2d region */
- BoxPtr r1End; /* End of 1st region */
- BoxPtr r2End; /* End of 2d region */
- short ybot; /* Bottom of intersection */
- short ytop; /* Top of intersection */
- RegDataPtr oldData; /* Old data for newReg */
- int prevBand; /* Index of start of
- * previous band in newReg */
- int curBand; /* Index of start of current
- * band in newReg */
- BoxPtr r1BandEnd; /* End of current band in r1 */
- BoxPtr r2BandEnd; /* End of current band in r2 */
- short top; /* Top of non-overlapping band */
- short bot; /* Bottom of non-overlapping band*/
- int r1y1; /* Temps for r1->y1 and r2->y1 */
- int r2y1;
- int newSize;
- int numRects;
-
- /*
- * Break any region computed from a broken region
- */
- if (RegionNar (reg1) || RegionNar(reg2))
- return RegionBreak (newReg);
-
- /*
- * Initialization:
- * set r1, r2, r1End and r2End appropriately, save the rectangles
- * of the destination region until the end in case it's one of
- * the two source regions, then mark the "new" region empty, allocating
- * another array of rectangles for it to use.
- */
-
- r1 = RegionRects(reg1);
- newSize = RegionNumRects(reg1);
- r1End = r1 + newSize;
- numRects = RegionNumRects(reg2);
- r2 = RegionRects(reg2);
- r2End = r2 + numRects;
- assert(r1 != r1End);
- assert(r2 != r2End);
-
- oldData = NULL;
- if (((newReg == reg1) && (newSize > 1)) ||
- ((newReg == reg2) && (numRects > 1)))
- {
- oldData = newReg->data;
- newReg->data = &RegionEmptyData;
- }
- /* guess at new size */
- if (numRects > newSize)
- newSize = numRects;
- newSize <<= 1;
- if (!newReg->data)
- newReg->data = &RegionEmptyData;
- else if (newReg->data->size)
- newReg->data->numRects = 0;
- if (newSize > newReg->data->size)
- if (!RegionRectAlloc(newReg, newSize))
- return FALSE;
-
- /*
- * Initialize ybot.
- * In the upcoming loop, ybot and ytop serve different functions depending
- * on whether the band being handled is an overlapping or non-overlapping
- * band.
- * In the case of a non-overlapping band (only one of the regions
- * has points in the band), ybot is the bottom of the most recent
- * intersection and thus clips the top of the rectangles in that band.
- * ytop is the top of the next intersection between the two regions and
- * serves to clip the bottom of the rectangles in the current band.
- * For an overlapping band (where the two regions intersect), ytop clips
- * the top of the rectangles of both regions and ybot clips the bottoms.
- */
-
- ybot = min(r1->y1, r2->y1);
-
- /*
- * prevBand serves to mark the start of the previous band so rectangles
- * can be coalesced into larger rectangles. qv. RegionCoalesce, above.
- * In the beginning, there is no previous band, so prevBand == curBand
- * (curBand is set later on, of course, but the first band will always
- * start at index 0). prevBand and curBand must be indices because of
- * the possible expansion, and resultant moving, of the new region's
- * array of rectangles.
- */
- prevBand = 0;
-
- do {
- /*
- * This algorithm proceeds one source-band (as opposed to a
- * destination band, which is determined by where the two regions
- * intersect) at a time. r1BandEnd and r2BandEnd serve to mark the
- * rectangle after the last one in the current band for their
- * respective regions.
- */
- assert(r1 != r1End);
- assert(r2 != r2End);
-
- FindBand(r1, r1BandEnd, r1End, r1y1);
- FindBand(r2, r2BandEnd, r2End, r2y1);
-
- /*
- * First handle the band that doesn't intersect, if any.
- *
- * Note that attention is restricted to one band in the
- * non-intersecting region at once, so if a region has n
- * bands between the current position and the next place it overlaps
- * the other, this entire loop will be passed through n times.
- */
- if (r1y1 < r2y1) {
- if (appendNon1) {
- top = max(r1y1, ybot);
- bot = min(r1->y2, r2y1);
- if (top != bot) {
- curBand = newReg->data->numRects;
- RegionAppendNonO(newReg, r1, r1BandEnd, top, bot);
- Coalesce(newReg, prevBand, curBand);
- }
- }
- ytop = r2y1;
- } else if (r2y1 < r1y1) {
- if (appendNon2) {
- top = max(r2y1, ybot);
- bot = min(r2->y2, r1y1);
- if (top != bot) {
- curBand = newReg->data->numRects;
- RegionAppendNonO(newReg, r2, r2BandEnd, top, bot);
- Coalesce(newReg, prevBand, curBand);
- }
- }
- ytop = r1y1;
- } else {
- ytop = r1y1;
- }
-
- /*
- * Now see if we've hit an intersecting band. The two bands only
- * intersect if ybot > ytop
- */
- ybot = min(r1->y2, r2->y2);
- if (ybot > ytop) {
- curBand = newReg->data->numRects;
- (* overlapFunc)(newReg, r1, r1BandEnd, r2, r2BandEnd, ytop, ybot,
- pOverlap);
- Coalesce(newReg, prevBand, curBand);
- }
-
- /*
- * If we've finished with a band (y2 == ybot) we skip forward
- * in the region to the next band.
- */
- if (r1->y2 == ybot) r1 = r1BandEnd;
- if (r2->y2 == ybot) r2 = r2BandEnd;
-
- } while (r1 != r1End && r2 != r2End);
-
- /*
- * Deal with whichever region (if any) still has rectangles left.
- *
- * We only need to worry about banding and coalescing for the very first
- * band left. After that, we can just group all remaining boxes,
- * regardless of how many bands, into one final append to the list.
- */
-
- if ((r1 != r1End) && appendNon1) {
- /* Do first nonOverlap1Func call, which may be able to coalesce */
- FindBand(r1, r1BandEnd, r1End, r1y1);
- curBand = newReg->data->numRects;
- RegionAppendNonO(newReg, r1, r1BandEnd, max(r1y1, ybot), r1->y2);
- Coalesce(newReg, prevBand, curBand);
- /* Just append the rest of the boxes */
- AppendRegions(newReg, r1BandEnd, r1End);
-
- } else if ((r2 != r2End) && appendNon2) {
- /* Do first nonOverlap2Func call, which may be able to coalesce */
- FindBand(r2, r2BandEnd, r2End, r2y1);
- curBand = newReg->data->numRects;
- RegionAppendNonO(newReg, r2, r2BandEnd, max(r2y1, ybot), r2->y2);
- Coalesce(newReg, prevBand, curBand);
- /* Append rest of boxes */
- AppendRegions(newReg, r2BandEnd, r2End);
- }
-
- free(oldData);
-
- if (!(numRects = newReg->data->numRects))
- {
- xfreeData(newReg);
- newReg->data = &RegionEmptyData;
- }
- else if (numRects == 1)
- {
- newReg->extents = *RegionBoxptr(newReg);
- xfreeData(newReg);
- newReg->data = NULL;
- }
- else
- {
- DOWNSIZE(newReg, numRects);
- }
-
- return TRUE;
-}
-
-/*-
- *-----------------------------------------------------------------------
- * RegionSetExtents --
- * Reset the extents of a region to what they should be. Called by
- * Subtract and Intersect as they can't figure it out along the
- * way or do so easily, as Union can.
- *
- * Results:
- * None.
- *
- * Side Effects:
- * The region's 'extents' structure is overwritten.
- *
- *-----------------------------------------------------------------------
- */
-static void
-RegionSetExtents (RegionPtr pReg)
-{
- BoxPtr pBox, pBoxEnd;
-
- if (!pReg->data)
- return;
- if (!pReg->data->size)
- {
- pReg->extents.x2 = pReg->extents.x1;
- pReg->extents.y2 = pReg->extents.y1;
- return;
- }
-
- pBox = RegionBoxptr(pReg);
- pBoxEnd = RegionEnd(pReg);
-
- /*
- * Since pBox is the first rectangle in the region, it must have the
- * smallest y1 and since pBoxEnd is the last rectangle in the region,
- * it must have the largest y2, because of banding. Initialize x1 and
- * x2 from pBox and pBoxEnd, resp., as good things to initialize them
- * to...
- */
- pReg->extents.x1 = pBox->x1;
- pReg->extents.y1 = pBox->y1;
- pReg->extents.x2 = pBoxEnd->x2;
- pReg->extents.y2 = pBoxEnd->y2;
-
- assert(pReg->extents.y1 < pReg->extents.y2);
- while (pBox <= pBoxEnd) {
- if (pBox->x1 < pReg->extents.x1)
- pReg->extents.x1 = pBox->x1;
- if (pBox->x2 > pReg->extents.x2)
- pReg->extents.x2 = pBox->x2;
- pBox++;
- };
-
- assert(pReg->extents.x1 < pReg->extents.x2);
-}
-
-/*======================================================================
- * Region Intersection
- *====================================================================*/
-/*-
- *-----------------------------------------------------------------------
- * RegionIntersectO --
- * Handle an overlapping band for RegionIntersect.
- *
- * Results:
- * TRUE if successful.
- *
- * Side Effects:
- * Rectangles may be added to the region.
- *
- *-----------------------------------------------------------------------
- */
-/*ARGSUSED*/
-
-#define MERGERECT(r) \
-{ \
- if (r->x1 <= x2) { \
- /* Merge with current rectangle */ \
- if (r->x1 < x2) *pOverlap = TRUE; \
- if (x2 < r->x2) x2 = r->x2; \
- } else { \
- /* Add current rectangle, start new one */ \
- NEWRECT(pReg, pNextRect, x1, y1, x2, y2); \
- x1 = r->x1; \
- x2 = r->x2; \
- } \
- r++; \
-}
-
-/*======================================================================
- * Region Union
- *====================================================================*/
-
-/*-
- *-----------------------------------------------------------------------
- * RegionUnionO --
- * Handle an overlapping band for the union operation. Picks the
- * left-most rectangle each time and merges it into the region.
- *
- * Results:
- * TRUE if successful.
- *
- * Side Effects:
- * pReg is overwritten.
- * pOverlap is set to TRUE if any boxes overlap.
- *
- *-----------------------------------------------------------------------
- */
-static Bool
-RegionUnionO (
- RegionPtr pReg,
- BoxPtr r1,
- BoxPtr r1End,
- BoxPtr r2,
- BoxPtr r2End,
- short y1,
- short y2,
- Bool *pOverlap)
-{
- BoxPtr pNextRect;
- int x1; /* left and right side of current union */
- int x2;
-
- assert (y1 < y2);
- assert(r1 != r1End && r2 != r2End);
-
- pNextRect = RegionTop(pReg);
-
- /* Start off current rectangle */
- if (r1->x1 < r2->x1)
- {
- x1 = r1->x1;
- x2 = r1->x2;
- r1++;
- }
- else
- {
- x1 = r2->x1;
- x2 = r2->x2;
- r2++;
- }
- while (r1 != r1End && r2 != r2End)
- {
- if (r1->x1 < r2->x1) MERGERECT(r1) else MERGERECT(r2);
- }
-
- /* Finish off whoever (if any) is left */
- if (r1 != r1End)
- {
- do
- {
- MERGERECT(r1);
- } while (r1 != r1End);
- }
- else if (r2 != r2End)
- {
- do
- {
- MERGERECT(r2);
- } while (r2 != r2End);
- }
-
- /* Add current rectangle */
- NEWRECT(pReg, pNextRect, x1, y1, x2, y2);
-
- return TRUE;
-}
-
-/*======================================================================
- * Batch Rectangle Union
- *====================================================================*/
-
-/*-
- *-----------------------------------------------------------------------
- * RegionAppend --
- *
- * "Append" the rgn rectangles onto the end of dstrgn, maintaining
- * knowledge of YX-banding when it's easy. Otherwise, dstrgn just
- * becomes a non-y-x-banded random collection of rectangles, and not
- * yet a true region. After a sequence of appends, the caller must
- * call RegionValidate to ensure that a valid region is constructed.
- *
- * Results:
- * TRUE if successful.
- *
- * Side Effects:
- * dstrgn is modified if rgn has rectangles.
- *
- */
-Bool
-RegionAppend(RegionPtr dstrgn, RegionPtr rgn)
-{
- int numRects, dnumRects, size;
- BoxPtr new, old;
- Bool prepend;
-
- if (RegionNar(rgn))
- return RegionBreak (dstrgn);
-
- if (!rgn->data && (dstrgn->data == &RegionEmptyData))
- {
- dstrgn->extents = rgn->extents;
- dstrgn->data = NULL;
- return TRUE;
- }
-
- numRects = RegionNumRects(rgn);
- if (!numRects)
- return TRUE;
- prepend = FALSE;
- size = numRects;
- dnumRects = RegionNumRects(dstrgn);
- if (!dnumRects && (size < 200))
- size = 200; /* XXX pick numbers out of a hat */
- RECTALLOC(dstrgn, size);
- old = RegionRects(rgn);
- if (!dnumRects)
- dstrgn->extents = rgn->extents;
- else if (dstrgn->extents.x2 > dstrgn->extents.x1)
- {
- BoxPtr first, last;
-
- first = old;
- last = RegionBoxptr(dstrgn) + (dnumRects - 1);
- if ((first->y1 > last->y2) ||
- ((first->y1 == last->y1) && (first->y2 == last->y2) &&
- (first->x1 > last->x2)))
- {
- if (rgn->extents.x1 < dstrgn->extents.x1)
- dstrgn->extents.x1 = rgn->extents.x1;
- if (rgn->extents.x2 > dstrgn->extents.x2)
- dstrgn->extents.x2 = rgn->extents.x2;
- dstrgn->extents.y2 = rgn->extents.y2;
- }
- else
- {
- first = RegionBoxptr(dstrgn);
- last = old + (numRects - 1);
- if ((first->y1 > last->y2) ||
- ((first->y1 == last->y1) && (first->y2 == last->y2) &&
- (first->x1 > last->x2)))
- {
- prepend = TRUE;
- if (rgn->extents.x1 < dstrgn->extents.x1)
- dstrgn->extents.x1 = rgn->extents.x1;
- if (rgn->extents.x2 > dstrgn->extents.x2)
- dstrgn->extents.x2 = rgn->extents.x2;
- dstrgn->extents.y1 = rgn->extents.y1;
- }
- else
- dstrgn->extents.x2 = dstrgn->extents.x1;
- }
- }
- if (prepend)
- {
- new = RegionBox(dstrgn, numRects);
- if (dnumRects == 1)
- *new = *RegionBoxptr(dstrgn);
- else
- memmove((char *)new,(char *)RegionBoxptr(dstrgn),
- dnumRects * sizeof(BoxRec));
- new = RegionBoxptr(dstrgn);
- }
- else
- new = RegionBoxptr(dstrgn) + dnumRects;
- if (numRects == 1)
- *new = *old;
- else
- memmove((char *)new, (char *)old, numRects * sizeof(BoxRec));
- dstrgn->data->numRects += numRects;
- return TRUE;
-}
-
-
-#define ExchangeRects(a, b) \
-{ \
- BoxRec t; \
- t = rects[a]; \
- rects[a] = rects[b]; \
- rects[b] = t; \
-}
-
-static void
-QuickSortRects(
- BoxRec rects[],
- int numRects)
-{
- int y1;
- int x1;
- int i, j;
- BoxPtr r;
-
- /* Always called with numRects > 1 */
-
- do
- {
- if (numRects == 2)
- {
- if (rects[0].y1 > rects[1].y1 ||
- (rects[0].y1 == rects[1].y1 && rects[0].x1 > rects[1].x1))
- ExchangeRects(0, 1);
- return;
- }
-
- /* Choose partition element, stick in location 0 */
- ExchangeRects(0, numRects >> 1);
- y1 = rects[0].y1;
- x1 = rects[0].x1;
-
- /* Partition array */
- i = 0;
- j = numRects;
- do
- {
- r = &(rects[i]);
- do
- {
- r++;
- i++;
- } while (i != numRects &&
- (r->y1 < y1 || (r->y1 == y1 && r->x1 < x1)));
- r = &(rects[j]);
- do
- {
- r--;
- j--;
- } while (y1 < r->y1 || (y1 == r->y1 && x1 < r->x1));
- if (i < j)
- ExchangeRects(i, j);
- } while (i < j);
-
- /* Move partition element back to middle */
- ExchangeRects(0, j);
-
- /* Recurse */
- if (numRects-j-1 > 1)
- QuickSortRects(&rects[j+1], numRects-j-1);
- numRects = j;
- } while (numRects > 1);
-}
-
-/*-
- *-----------------------------------------------------------------------
- * RegionValidate --
- *
- * Take a ``region'' which is a non-y-x-banded random collection of
- * rectangles, and compute a nice region which is the union of all the
- * rectangles.
- *
- * Results:
- * TRUE if successful.
- *
- * Side Effects:
- * The passed-in ``region'' may be modified.
- * pOverlap set to TRUE if any retangles overlapped, else FALSE;
- *
- * Strategy:
- * Step 1. Sort the rectangles into ascending order with primary key y1
- * and secondary key x1.
- *
- * Step 2. Split the rectangles into the minimum number of proper y-x
- * banded regions. This may require horizontally merging
- * rectangles, and vertically coalescing bands. With any luck,
- * this step in an identity tranformation (ala the Box widget),
- * or a coalescing into 1 box (ala Menus).
- *
- * Step 3. Merge the separate regions down to a single region by calling
- * Union. Maximize the work each Union call does by using
- * a binary merge.
- *
- *-----------------------------------------------------------------------
- */
-
-Bool
-RegionValidate(RegionPtr badreg, Bool *pOverlap)
-{
- /* Descriptor for regions under construction in Step 2. */
- typedef struct {
- RegionRec reg;
- int prevBand;
- int curBand;
- } RegionInfo;
-
- int numRects; /* Original numRects for badreg */
- RegionInfo *ri; /* Array of current regions */
- int numRI; /* Number of entries used in ri */
- int sizeRI; /* Number of entries available in ri */
- int i; /* Index into rects */
- int j; /* Index into ri */
- RegionInfo *rit; /* &ri[j] */
- RegionPtr reg; /* ri[j].reg */
- BoxPtr box; /* Current box in rects */
- BoxPtr riBox; /* Last box in ri[j].reg */
- RegionPtr hreg; /* ri[j_half].reg */
- Bool ret = TRUE;
-
- *pOverlap = FALSE;
- if (!badreg->data)
- {
- good(badreg);
- return TRUE;
- }
- numRects = badreg->data->numRects;
- if (!numRects)
- {
- if (RegionNar(badreg))
- return FALSE;
- good(badreg);
- return TRUE;
- }
- if (badreg->extents.x1 < badreg->extents.x2)
- {
- if ((numRects) == 1)
- {
- xfreeData(badreg);
- badreg->data = (RegDataPtr) NULL;
- }
- else
- {
- DOWNSIZE(badreg, numRects);
- }
- good(badreg);
- return TRUE;
- }
-
- /* Step 1: Sort the rects array into ascending (y1, x1) order */
- QuickSortRects(RegionBoxptr(badreg), numRects);
-
- /* Step 2: Scatter the sorted array into the minimum number of regions */
-
- /* Set up the first region to be the first rectangle in badreg */
- /* Note that step 2 code will never overflow the ri[0].reg rects array */
- ri = (RegionInfo *) malloc(4 * sizeof(RegionInfo));
- if (!ri)
- return RegionBreak (badreg);
- sizeRI = 4;
- numRI = 1;
- ri[0].prevBand = 0;
- ri[0].curBand = 0;
- ri[0].reg = *badreg;
- box = RegionBoxptr(&ri[0].reg);
- ri[0].reg.extents = *box;
- ri[0].reg.data->numRects = 1;
-
- /* Now scatter rectangles into the minimum set of valid regions. If the
- next rectangle to be added to a region would force an existing rectangle
- in the region to be split up in order to maintain y-x banding, just
- forget it. Try the next region. If it doesn't fit cleanly into any
- region, make a new one. */
-
- for (i = numRects; --i > 0;)
- {
- box++;
- /* Look for a region to append box to */
- for (j = numRI, rit = ri; --j >= 0; rit++)
- {
- reg = &rit->reg;
- riBox = RegionEnd(reg);
-
- if (box->y1 == riBox->y1 && box->y2 == riBox->y2)
- {
- /* box is in same band as riBox. Merge or append it */
- if (box->x1 <= riBox->x2)
- {
- /* Merge it with riBox */
- if (box->x1 < riBox->x2) *pOverlap = TRUE;
- if (box->x2 > riBox->x2) riBox->x2 = box->x2;
- }
- else
- {
- RECTALLOC_BAIL(reg, 1, bail);
- *RegionTop(reg) = *box;
- reg->data->numRects++;
- }
- goto NextRect; /* So sue me */
- }
- else if (box->y1 >= riBox->y2)
- {
- /* Put box into new band */
- if (reg->extents.x2 < riBox->x2) reg->extents.x2 = riBox->x2;
- if (reg->extents.x1 > box->x1) reg->extents.x1 = box->x1;
- Coalesce(reg, rit->prevBand, rit->curBand);
- rit->curBand = reg->data->numRects;
- RECTALLOC_BAIL(reg, 1, bail);
- *RegionTop(reg) = *box;
- reg->data->numRects++;
- goto NextRect;
- }
- /* Well, this region was inappropriate. Try the next one. */
- } /* for j */
-
- /* Uh-oh. No regions were appropriate. Create a new one. */
- if (sizeRI == numRI)
- {
- /* Oops, allocate space for new region information */
- sizeRI <<= 1;
- rit = (RegionInfo *) realloc(ri, sizeRI * sizeof(RegionInfo));
- if (!rit)
- goto bail;
- ri = rit;
- rit = &ri[numRI];
- }
- numRI++;
- rit->prevBand = 0;
- rit->curBand = 0;
- rit->reg.extents = *box;
- rit->reg.data = NULL;
- if (!RegionRectAlloc(&rit->reg, (i+numRI) / numRI)) /* MUST force allocation */
- goto bail;
-NextRect: ;
- } /* for i */
-
- /* Make a final pass over each region in order to Coalesce and set
- extents.x2 and extents.y2 */
-
- for (j = numRI, rit = ri; --j >= 0; rit++)
- {
- reg = &rit->reg;
- riBox = RegionEnd(reg);
- reg->extents.y2 = riBox->y2;
- if (reg->extents.x2 < riBox->x2) reg->extents.x2 = riBox->x2;
- Coalesce(reg, rit->prevBand, rit->curBand);
- if (reg->data->numRects == 1) /* keep unions happy below */
- {
- xfreeData(reg);
- reg->data = NULL;
- }
- }
-
- /* Step 3: Union all regions into a single region */
- while (numRI > 1)
- {
- int half = numRI/2;
- for (j = numRI & 1; j < (half + (numRI & 1)); j++)
- {
- reg = &ri[j].reg;
- hreg = &ri[j+half].reg;
- if (!RegionOp(reg, reg, hreg, RegionUnionO, TRUE, TRUE, pOverlap))
- ret = FALSE;
- if (hreg->extents.x1 < reg->extents.x1)
- reg->extents.x1 = hreg->extents.x1;
- if (hreg->extents.y1 < reg->extents.y1)
- reg->extents.y1 = hreg->extents.y1;
- if (hreg->extents.x2 > reg->extents.x2)
- reg->extents.x2 = hreg->extents.x2;
- if (hreg->extents.y2 > reg->extents.y2)
- reg->extents.y2 = hreg->extents.y2;
- xfreeData(hreg);
- }
- numRI -= half;
- }
- *badreg = ri[0].reg;
- free(ri);
- good(badreg);
- return ret;
-bail:
- for (i = 0; i < numRI; i++)
- xfreeData(&ri[i].reg);
- free(ri);
- return RegionBreak (badreg);
-}
-
-RegionPtr
-RegionFromRects(int nrects, xRectangle *prect, int ctype)
-{
-
- RegionPtr pRgn;
- RegDataPtr pData;
- BoxPtr pBox;
- int i;
- int x1, y1, x2, y2;
-
- pRgn = RegionCreate(NullBox, 0);
- if (RegionNar (pRgn))
- return pRgn;
- if (!nrects)
- return pRgn;
- if (nrects == 1)
- {
- x1 = prect->x;
- y1 = prect->y;
- if ((x2 = x1 + (int) prect->width) > MAXSHORT)
- x2 = MAXSHORT;
- if ((y2 = y1 + (int) prect->height) > MAXSHORT)
- y2 = MAXSHORT;
- if (x1 != x2 && y1 != y2)
- {
- pRgn->extents.x1 = x1;
- pRgn->extents.y1 = y1;
- pRgn->extents.x2 = x2;
- pRgn->extents.y2 = y2;
- pRgn->data = NULL;
- }
- return pRgn;
- }
- pData = xallocData(nrects);
- if (!pData)
- {
- RegionBreak (pRgn);
- return pRgn;
- }
- pBox = (BoxPtr) (pData + 1);
- for (i = nrects; --i >= 0; prect++)
- {
- x1 = prect->x;
- y1 = prect->y;
- if ((x2 = x1 + (int) prect->width) > MAXSHORT)
- x2 = MAXSHORT;
- if ((y2 = y1 + (int) prect->height) > MAXSHORT)
- y2 = MAXSHORT;
- if (x1 != x2 && y1 != y2)
- {
- pBox->x1 = x1;
- pBox->y1 = y1;
- pBox->x2 = x2;
- pBox->y2 = y2;
- pBox++;
- }
- }
- if (pBox != (BoxPtr) (pData + 1))
- {
- pData->size = nrects;
- pData->numRects = pBox - (BoxPtr) (pData + 1);
- pRgn->data = pData;
- if (ctype != CT_YXBANDED)
- {
- Bool overlap; /* result ignored */
- pRgn->extents.x1 = pRgn->extents.x2 = 0;
- RegionValidate(pRgn, &overlap);
- }
- else
- RegionSetExtents(pRgn);
- good(pRgn);
- }
- else
- {
- free(pData);
- }
- return pRgn;
-}
-
-#define ExchangeSpans(a, b) \
-{ \
- DDXPointRec tpt; \
- int tw; \
- \
- tpt = spans[a]; spans[a] = spans[b]; spans[b] = tpt; \
- tw = widths[a]; widths[a] = widths[b]; widths[b] = tw; \
-}
-
-/* ||| I should apply the merge sort code to rectangle sorting above, and see
- if mapping time can be improved. But right now I've been at work 12 hours,
- so forget it.
-*/
-
-static void QuickSortSpans(
- DDXPointRec spans[],
- int widths[],
- int numSpans)
-{
- int y;
- int i, j, m;
- DDXPointPtr r;
-
- /* Always called with numSpans > 1 */
- /* Sorts only by y, doesn't bother to sort by x */
-
- do
- {
- if (numSpans < 9)
- {
- /* Do insertion sort */
- int yprev;
-
- yprev = spans[0].y;
- i = 1;
- do
- { /* while i != numSpans */
- y = spans[i].y;
- if (yprev > y)
- {
- /* spans[i] is out of order. Move into proper location. */
- DDXPointRec tpt;
- int tw, k;
-
- for (j = 0; y >= spans[j].y; j++) {}
- tpt = spans[i];
- tw = widths[i];
- for (k = i; k != j; k--)
- {
- spans[k] = spans[k-1];
- widths[k] = widths[k-1];
- }
- spans[j] = tpt;
- widths[j] = tw;
- y = spans[i].y;
- } /* if out of order */
- yprev = y;
- i++;
- } while (i != numSpans);
- return;
- }
-
- /* Choose partition element, stick in location 0 */
- m = numSpans / 2;
- if (spans[m].y > spans[0].y) ExchangeSpans(m, 0);
- if (spans[m].y > spans[numSpans-1].y) ExchangeSpans(m, numSpans-1);
- if (spans[m].y > spans[0].y) ExchangeSpans(m, 0);
- y = spans[0].y;
-
- /* Partition array */
- i = 0;
- j = numSpans;
- do
- {
- r = &(spans[i]);
- do
- {
- r++;
- i++;
- } while (i != numSpans && r->y < y);
- r = &(spans[j]);
- do
- {
- r--;
- j--;
- } while (y < r->y);
- if (i < j)
- ExchangeSpans(i, j);
- } while (i < j);
-
- /* Move partition element back to middle */
- ExchangeSpans(0, j);
-
- /* Recurse */
- if (numSpans-j-1 > 1)
- QuickSortSpans(&spans[j+1], &widths[j+1], numSpans-j-1);
- numSpans = j;
- } while (numSpans > 1);
-}
-
-#define NextBand() \
-{ \
- clipy1 = pboxBandStart->y1; \
- clipy2 = pboxBandStart->y2; \
- pboxBandEnd = pboxBandStart + 1; \
- while (pboxBandEnd != pboxLast && pboxBandEnd->y1 == clipy1) { \
- pboxBandEnd++; \
- } \
- for (; ppt != pptLast && ppt->y < clipy1; ppt++, pwidth++) {} \
-}
-
-/*
- Clip a list of scanlines to a region. The caller has allocated the
- space. FSorted is non-zero if the scanline origins are in ascending
- order.
- returns the number of new, clipped scanlines.
-*/
-
-int
-RegionClipSpans(
- RegionPtr prgnDst,
- DDXPointPtr ppt,
- int *pwidth,
- int nspans,
- DDXPointPtr pptNew,
- int *pwidthNew,
- int fSorted)
-{
- DDXPointPtr pptLast;
- int *pwidthNewStart; /* the vengeance of Xerox! */
- int y, x1, x2;
- int numRects;
-
- good(prgnDst);
- pptLast = ppt + nspans;
- pwidthNewStart = pwidthNew;
-
- if (!prgnDst->data)
- {
- /* Do special fast code with clip boundaries in registers(?) */
- /* It doesn't pay much to make use of fSorted in this case,
- so we lump everything together. */
-
- int clipx1, clipx2, clipy1, clipy2;
-
- clipx1 = prgnDst->extents.x1;
- clipy1 = prgnDst->extents.y1;
- clipx2 = prgnDst->extents.x2;
- clipy2 = prgnDst->extents.y2;
-
- for (; ppt != pptLast; ppt++, pwidth++)
- {
- y = ppt->y;
- x1 = ppt->x;
- if (clipy1 <= y && y < clipy2)
- {
- x2 = x1 + *pwidth;
- if (x1 < clipx1) x1 = clipx1;
- if (x2 > clipx2) x2 = clipx2;
- if (x1 < x2)
- {
- /* part of span in clip rectangle */
- pptNew->x = x1;
- pptNew->y = y;
- *pwidthNew = x2 - x1;
- pptNew++;
- pwidthNew++;
- }
- }
- } /* end for */
-
- }
- else if ((numRects = prgnDst->data->numRects))
- {
- /* Have to clip against many boxes */
- BoxPtr pboxBandStart, pboxBandEnd;
- BoxPtr pbox;
- BoxPtr pboxLast;
- int clipy1, clipy2;
-
- /* In this case, taking advantage of sorted spans gains more than
- the sorting costs. */
- if ((! fSorted) && (nspans > 1))
- QuickSortSpans(ppt, pwidth, nspans);
-
- pboxBandStart = RegionBoxptr(prgnDst);
- pboxLast = pboxBandStart + numRects;
-
- NextBand();
-
- for (; ppt != pptLast; )
- {
- y = ppt->y;
- if (y < clipy2)
- {
- /* span is in the current band */
- pbox = pboxBandStart;
- x1 = ppt->x;
- x2 = x1 + *pwidth;
- do
- { /* For each box in band */
- int newx1, newx2;
-
- newx1 = x1;
- newx2 = x2;
- if (newx1 < pbox->x1) newx1 = pbox->x1;
- if (newx2 > pbox->x2) newx2 = pbox->x2;
- if (newx1 < newx2)
- {
- /* Part of span in clip rectangle */
- pptNew->x = newx1;
- pptNew->y = y;
- *pwidthNew = newx2 - newx1;
- pptNew++;
- pwidthNew++;
- }
- pbox++;
- } while (pbox != pboxBandEnd);
- ppt++;
- pwidth++;
- }
- else
- {
- /* Move to next band, adjust ppt as needed */
- pboxBandStart = pboxBandEnd;
- if (pboxBandStart == pboxLast)
- break; /* We're completely done */
- NextBand();
- }
- }
- }
- return pwidthNew - pwidthNewStart;
-}
+/*********************************************************** + +Copyright 1987, 1988, 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987, 1988, 1989 by +Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission 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 that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY 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 THIS +SOFTWARE. + +******************************************************************/ + +/* The panoramix components contained the following notice */ +/***************************************************************** + +Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING, +BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of Digital Equipment Corporation +shall not be used in advertising or otherwise to promote the sale, use or other +dealings in this Software without prior written authorization from Digital +Equipment Corporation. + +******************************************************************/ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include "regionstr.h" +#include <X11/Xprotostr.h> +#include <X11/Xfuncproto.h> +#include "gc.h" +#include <pixman.h> + +#undef assert +#ifdef REGION_DEBUG +#define assert(expr) { \ + CARD32 *foo = NULL; \ + if (!(expr)) { \ + ErrorF("Assertion failed file %s, line %d: %s\n", \ + __FILE__, __LINE__, #expr); \ + *foo = 0xdeadbeef; /* to get a backtrace */ \ + } \ + } +#else +#define assert(expr) +#endif + +#define good(reg) assert(RegionIsValid(reg)) + +/* + * The functions in this file implement the Region abstraction used extensively + * throughout the X11 sample server. A Region is simply a set of disjoint + * (non-overlapping) rectangles, plus an "extent" rectangle which is the + * smallest single rectangle that contains all the non-overlapping rectangles. + * + * A Region is implemented as a "y-x-banded" array of rectangles. This array + * imposes two degrees of order. First, all rectangles are sorted by top side + * y coordinate first (y1), and then by left side x coordinate (x1). + * + * Furthermore, the rectangles are grouped into "bands". Each rectangle in a + * band has the same top y coordinate (y1), and each has the same bottom y + * coordinate (y2). Thus all rectangles in a band differ only in their left + * and right side (x1 and x2). Bands are implicit in the array of rectangles: + * there is no separate list of band start pointers. + * + * The y-x band representation does not minimize rectangles. In particular, + * if a rectangle vertically crosses a band (the rectangle has scanlines in + * the y1 to y2 area spanned by the band), then the rectangle may be broken + * down into two or more smaller rectangles stacked one atop the other. + * + * ----------- ----------- + * | | | | band 0 + * | | -------- ----------- -------- + * | | | | in y-x banded | | | | band 1 + * | | | | form is | | | | + * ----------- | | ----------- -------- + * | | | | band 2 + * -------- -------- + * + * An added constraint on the rectangles is that they must cover as much + * horizontal area as possible: no two rectangles within a band are allowed + * to touch. + * + * Whenever possible, bands will be merged together to cover a greater vertical + * distance (and thus reduce the number of rectangles). Two bands can be merged + * only if the bottom of one touches the top of the other and they have + * rectangles in the same places (of the same width, of course). + * + * Adam de Boor wrote most of the original region code. Joel McCormack + * substantially modified or rewrote most of the core arithmetic routines, + * and added RegionValidate in order to support several speed improvements + * to miValidateTree. Bob Scheifler changed the representation to be more + * compact when empty or a single rectangle, and did a bunch of gratuitous + * reformatting. + */ + +/* true iff two Boxes overlap */ +#define EXTENTCHECK(r1,r2) \ + (!( ((r1)->x2 <= (r2)->x1) || \ + ((r1)->x1 >= (r2)->x2) || \ + ((r1)->y2 <= (r2)->y1) || \ + ((r1)->y1 >= (r2)->y2) ) ) + +/* true iff (x,y) is in Box */ +#define INBOX(r,x,y) \ + ( ((r)->x2 > x) && \ + ((r)->x1 <= x) && \ + ((r)->y2 > y) && \ + ((r)->y1 <= y) ) + +/* true iff Box r1 contains Box r2 */ +#define SUBSUMES(r1,r2) \ + ( ((r1)->x1 <= (r2)->x1) && \ + ((r1)->x2 >= (r2)->x2) && \ + ((r1)->y1 <= (r2)->y1) && \ + ((r1)->y2 >= (r2)->y2) ) + +#define xallocData(n) malloc(RegionSizeof(n)) +#define xfreeData(reg) if ((reg)->data && (reg)->data->size) free((reg)->data) + +#define RECTALLOC_BAIL(pReg,n,bail) \ +if (!(pReg)->data || (((pReg)->data->numRects + (n)) > (pReg)->data->size)) \ + if (!RegionRectAlloc(pReg, n)) { goto bail; } + +#define RECTALLOC(pReg,n) \ +if (!(pReg)->data || (((pReg)->data->numRects + (n)) > (pReg)->data->size)) \ + if (!RegionRectAlloc(pReg, n)) { return FALSE; } + +#define ADDRECT(pNextRect,nx1,ny1,nx2,ny2) \ +{ \ + pNextRect->x1 = nx1; \ + pNextRect->y1 = ny1; \ + pNextRect->x2 = nx2; \ + pNextRect->y2 = ny2; \ + pNextRect++; \ +} + +#define NEWRECT(pReg,pNextRect,nx1,ny1,nx2,ny2) \ +{ \ + if (!(pReg)->data || ((pReg)->data->numRects == (pReg)->data->size))\ + { \ + if (!RegionRectAlloc(pReg, 1)) \ + return FALSE; \ + pNextRect = RegionTop(pReg); \ + } \ + ADDRECT(pNextRect,nx1,ny1,nx2,ny2); \ + pReg->data->numRects++; \ + assert(pReg->data->numRects<=pReg->data->size); \ +} + + +#define DOWNSIZE(reg,numRects) \ +if (((numRects) < ((reg)->data->size >> 1)) && ((reg)->data->size > 50)) \ +{ \ + RegDataPtr NewData; \ + NewData = (RegDataPtr)realloc((reg)->data, RegionSizeof(numRects)); \ + if (NewData) \ + { \ + NewData->size = (numRects); \ + (reg)->data = NewData; \ + } \ +} + + +BoxRec RegionEmptyBox = {0, 0, 0, 0}; +RegDataRec RegionEmptyData = {0, 0}; + +RegDataRec RegionBrokenData = {0, 0}; +static RegionRec RegionBrokenRegion = { { 0, 0, 0, 0 }, &RegionBrokenData }; + +void +InitRegions (void) +{ + pixman_region_set_static_pointers (&RegionEmptyBox, &RegionEmptyData, &RegionBrokenData); +} + +/***************************************************************** + * RegionCreate(rect, size) + * This routine does a simple malloc to make a structure of + * REGION of "size" number of rectangles. + *****************************************************************/ + +RegionPtr +RegionCreate(BoxPtr rect, int size) +{ + RegionPtr pReg; + + pReg = (RegionPtr)malloc(sizeof(RegionRec)); + if (!pReg) + return &RegionBrokenRegion; + + RegionInit (pReg, rect, size); + + return pReg; +} + +void +RegionDestroy(RegionPtr pReg) +{ + pixman_region_fini (pReg); + if (pReg != &RegionBrokenRegion) + free(pReg); +} + +void +RegionPrint(RegionPtr rgn) +{ + int num, size; + int i; + BoxPtr rects; + + num = RegionNumRects(rgn); + size = RegionSize(rgn); + rects = RegionRects(rgn); + ErrorF("[mi] num: %d size: %d\n", num, size); + ErrorF("[mi] extents: %d %d %d %d\n", + rgn->extents.x1, rgn->extents.y1, rgn->extents.x2, rgn->extents.y2); + for (i = 0; i < num; i++) + ErrorF("[mi] %d %d %d %d \n", + rects[i].x1, rects[i].y1, rects[i].x2, rects[i].y2); + ErrorF("[mi] \n"); +} + +#ifdef DEBUG +Bool +RegionIsValid(RegionPtr reg) +{ + int i, numRects; + + if ((reg->extents.x1 > reg->extents.x2) || + (reg->extents.y1 > reg->extents.y2)) + return FALSE; + numRects = RegionNumRects(reg); + if (!numRects) + return ((reg->extents.x1 == reg->extents.x2) && + (reg->extents.y1 == reg->extents.y2) && + (reg->data->size || (reg->data == &RegionEmptyData))); + else if (numRects == 1) + return !reg->data; + else + { + BoxPtr pboxP, pboxN; + BoxRec box; + + pboxP = RegionRects(reg); + box = *pboxP; + box.y2 = pboxP[numRects-1].y2; + pboxN = pboxP + 1; + for (i = numRects; --i > 0; pboxP++, pboxN++) + { + if ((pboxN->x1 >= pboxN->x2) || + (pboxN->y1 >= pboxN->y2)) + return FALSE; + if (pboxN->x1 < box.x1) + box.x1 = pboxN->x1; + if (pboxN->x2 > box.x2) + box.x2 = pboxN->x2; + if ((pboxN->y1 < pboxP->y1) || + ((pboxN->y1 == pboxP->y1) && + ((pboxN->x1 < pboxP->x2) || (pboxN->y2 != pboxP->y2)))) + return FALSE; + } + return ((box.x1 == reg->extents.x1) && + (box.x2 == reg->extents.x2) && + (box.y1 == reg->extents.y1) && + (box.y2 == reg->extents.y2)); + } +} +#endif /* DEBUG */ + +Bool +RegionBreak (RegionPtr pReg) +{ + xfreeData (pReg); + pReg->extents = RegionEmptyBox; + pReg->data = &RegionBrokenData; + return FALSE; +} + +Bool +RegionRectAlloc(RegionPtr pRgn, int n) +{ + RegDataPtr data; + + if (!pRgn->data) + { + n++; + pRgn->data = xallocData(n); + if (!pRgn->data) + return RegionBreak (pRgn); + pRgn->data->numRects = 1; + *RegionBoxptr(pRgn) = pRgn->extents; + } + else if (!pRgn->data->size) + { + pRgn->data = xallocData(n); + if (!pRgn->data) + return RegionBreak (pRgn); + pRgn->data->numRects = 0; + } + else + { + if (n == 1) + { + n = pRgn->data->numRects; + if (n > 500) /* XXX pick numbers out of a hat */ + n = 250; + } + n += pRgn->data->numRects; + data = (RegDataPtr)realloc(pRgn->data, RegionSizeof(n)); + if (!data) + return RegionBreak (pRgn); + pRgn->data = data; + } + pRgn->data->size = n; + return TRUE; +} + +/*====================================================================== + * Generic Region Operator + *====================================================================*/ + +/*- + *----------------------------------------------------------------------- + * RegionCoalesce -- + * Attempt to merge the boxes in the current band with those in the + * previous one. We are guaranteed that the current band extends to + * the end of the rects array. Used only by RegionOp. + * + * Results: + * The new index for the previous band. + * + * Side Effects: + * If coalescing takes place: + * - rectangles in the previous band will have their y2 fields + * altered. + * - pReg->data->numRects will be decreased. + * + *----------------------------------------------------------------------- + */ +_X_INLINE static int +RegionCoalesce ( + RegionPtr pReg, /* Region to coalesce */ + int prevStart, /* Index of start of previous band */ + int curStart) /* Index of start of current band */ +{ + BoxPtr pPrevBox; /* Current box in previous band */ + BoxPtr pCurBox; /* Current box in current band */ + int numRects; /* Number rectangles in both bands */ + int y2; /* Bottom of current band */ + /* + * Figure out how many rectangles are in the band. + */ + numRects = curStart - prevStart; + assert(numRects == pReg->data->numRects - curStart); + + if (!numRects) return curStart; + + /* + * The bands may only be coalesced if the bottom of the previous + * matches the top scanline of the current. + */ + pPrevBox = RegionBox(pReg, prevStart); + pCurBox = RegionBox(pReg, curStart); + if (pPrevBox->y2 != pCurBox->y1) return curStart; + + /* + * Make sure the bands have boxes in the same places. This + * assumes that boxes have been added in such a way that they + * cover the most area possible. I.e. two boxes in a band must + * have some horizontal space between them. + */ + y2 = pCurBox->y2; + + do { + if ((pPrevBox->x1 != pCurBox->x1) || (pPrevBox->x2 != pCurBox->x2)) { + return curStart; + } + pPrevBox++; + pCurBox++; + numRects--; + } while (numRects); + + /* + * The bands may be merged, so set the bottom y of each box + * in the previous band to the bottom y of the current band. + */ + numRects = curStart - prevStart; + pReg->data->numRects -= numRects; + do { + pPrevBox--; + pPrevBox->y2 = y2; + numRects--; + } while (numRects); + return prevStart; +} + + +/* Quicky macro to avoid trivial reject procedure calls to RegionCoalesce */ + +#define Coalesce(newReg, prevBand, curBand) \ + if (curBand - prevBand == newReg->data->numRects - curBand) { \ + prevBand = RegionCoalesce(newReg, prevBand, curBand); \ + } else { \ + prevBand = curBand; \ + } + +/*- + *----------------------------------------------------------------------- + * RegionAppendNonO -- + * Handle a non-overlapping band for the union and subtract operations. + * Just adds the (top/bottom-clipped) rectangles into the region. + * Doesn't have to check for subsumption or anything. + * + * Results: + * None. + * + * Side Effects: + * pReg->data->numRects is incremented and the rectangles overwritten + * with the rectangles we're passed. + * + *----------------------------------------------------------------------- + */ + +_X_INLINE static Bool +RegionAppendNonO ( + RegionPtr pReg, + BoxPtr r, + BoxPtr rEnd, + int y1, + int y2) +{ + BoxPtr pNextRect; + int newRects; + + newRects = rEnd - r; + + assert(y1 < y2); + assert(newRects != 0); + + /* Make sure we have enough space for all rectangles to be added */ + RECTALLOC(pReg, newRects); + pNextRect = RegionTop(pReg); + pReg->data->numRects += newRects; + do { + assert(r->x1 < r->x2); + ADDRECT(pNextRect, r->x1, y1, r->x2, y2); + r++; + } while (r != rEnd); + + return TRUE; +} + +#define FindBand(r, rBandEnd, rEnd, ry1) \ +{ \ + ry1 = r->y1; \ + rBandEnd = r+1; \ + while ((rBandEnd != rEnd) && (rBandEnd->y1 == ry1)) { \ + rBandEnd++; \ + } \ +} + +#define AppendRegions(newReg, r, rEnd) \ +{ \ + int newRects; \ + if ((newRects = rEnd - r)) { \ + RECTALLOC(newReg, newRects); \ + memmove((char *)RegionTop(newReg),(char *)r, \ + newRects * sizeof(BoxRec)); \ + newReg->data->numRects += newRects; \ + } \ +} + +/*- + *----------------------------------------------------------------------- + * RegionOp -- + * Apply an operation to two regions. Called by RegionUnion, RegionInverse, + * RegionSubtract, RegionIntersect.... Both regions MUST have at least one + * rectangle, and cannot be the same object. + * + * Results: + * TRUE if successful. + * + * Side Effects: + * The new region is overwritten. + * pOverlap set to TRUE if overlapFunc ever returns TRUE. + * + * Notes: + * The idea behind this function is to view the two regions as sets. + * Together they cover a rectangle of area that this function divides + * into horizontal bands where points are covered only by one region + * or by both. For the first case, the nonOverlapFunc is called with + * each the band and the band's upper and lower extents. For the + * second, the overlapFunc is called to process the entire band. It + * is responsible for clipping the rectangles in the band, though + * this function provides the boundaries. + * At the end of each band, the new region is coalesced, if possible, + * to reduce the number of rectangles in the region. + * + *----------------------------------------------------------------------- + */ + +typedef Bool (*OverlapProcPtr)( + RegionPtr pReg, + BoxPtr r1, + BoxPtr r1End, + BoxPtr r2, + BoxPtr r2End, + short y1, + short y2, + Bool *pOverlap); + +static Bool +RegionOp( + RegionPtr newReg, /* Place to store result */ + RegionPtr reg1, /* First region in operation */ + RegionPtr reg2, /* 2d region in operation */ + OverlapProcPtr overlapFunc, /* Function to call for over- + * lapping bands */ + Bool appendNon1, /* Append non-overlapping bands */ + /* in region 1 ? */ + Bool appendNon2, /* Append non-overlapping bands */ + /* in region 2 ? */ + Bool *pOverlap) +{ + BoxPtr r1; /* Pointer into first region */ + BoxPtr r2; /* Pointer into 2d region */ + BoxPtr r1End; /* End of 1st region */ + BoxPtr r2End; /* End of 2d region */ + short ybot; /* Bottom of intersection */ + short ytop; /* Top of intersection */ + RegDataPtr oldData; /* Old data for newReg */ + int prevBand; /* Index of start of + * previous band in newReg */ + int curBand; /* Index of start of current + * band in newReg */ + BoxPtr r1BandEnd; /* End of current band in r1 */ + BoxPtr r2BandEnd; /* End of current band in r2 */ + short top; /* Top of non-overlapping band */ + short bot; /* Bottom of non-overlapping band*/ + int r1y1; /* Temps for r1->y1 and r2->y1 */ + int r2y1; + int newSize; + int numRects; + + /* + * Break any region computed from a broken region + */ + if (RegionNar (reg1) || RegionNar(reg2)) + return RegionBreak (newReg); + + /* + * Initialization: + * set r1, r2, r1End and r2End appropriately, save the rectangles + * of the destination region until the end in case it's one of + * the two source regions, then mark the "new" region empty, allocating + * another array of rectangles for it to use. + */ + + r1 = RegionRects(reg1); + newSize = RegionNumRects(reg1); + r1End = r1 + newSize; + numRects = RegionNumRects(reg2); + r2 = RegionRects(reg2); + r2End = r2 + numRects; + assert(r1 != r1End); + assert(r2 != r2End); + + oldData = NULL; + if (((newReg == reg1) && (newSize > 1)) || + ((newReg == reg2) && (numRects > 1))) + { + oldData = newReg->data; + newReg->data = &RegionEmptyData; + } + /* guess at new size */ + if (numRects > newSize) + newSize = numRects; + newSize <<= 1; + if (!newReg->data) + newReg->data = &RegionEmptyData; + else if (newReg->data->size) + newReg->data->numRects = 0; + if (newSize > newReg->data->size) + if (!RegionRectAlloc(newReg, newSize)) + return FALSE; + + /* + * Initialize ybot. + * In the upcoming loop, ybot and ytop serve different functions depending + * on whether the band being handled is an overlapping or non-overlapping + * band. + * In the case of a non-overlapping band (only one of the regions + * has points in the band), ybot is the bottom of the most recent + * intersection and thus clips the top of the rectangles in that band. + * ytop is the top of the next intersection between the two regions and + * serves to clip the bottom of the rectangles in the current band. + * For an overlapping band (where the two regions intersect), ytop clips + * the top of the rectangles of both regions and ybot clips the bottoms. + */ + + ybot = min(r1->y1, r2->y1); + + /* + * prevBand serves to mark the start of the previous band so rectangles + * can be coalesced into larger rectangles. qv. RegionCoalesce, above. + * In the beginning, there is no previous band, so prevBand == curBand + * (curBand is set later on, of course, but the first band will always + * start at index 0). prevBand and curBand must be indices because of + * the possible expansion, and resultant moving, of the new region's + * array of rectangles. + */ + prevBand = 0; + + do { + /* + * This algorithm proceeds one source-band (as opposed to a + * destination band, which is determined by where the two regions + * intersect) at a time. r1BandEnd and r2BandEnd serve to mark the + * rectangle after the last one in the current band for their + * respective regions. + */ + assert(r1 != r1End); + assert(r2 != r2End); + + FindBand(r1, r1BandEnd, r1End, r1y1); + FindBand(r2, r2BandEnd, r2End, r2y1); + + /* + * First handle the band that doesn't intersect, if any. + * + * Note that attention is restricted to one band in the + * non-intersecting region at once, so if a region has n + * bands between the current position and the next place it overlaps + * the other, this entire loop will be passed through n times. + */ + if (r1y1 < r2y1) { + if (appendNon1) { + top = max(r1y1, ybot); + bot = min(r1->y2, r2y1); + if (top != bot) { + curBand = newReg->data->numRects; + RegionAppendNonO(newReg, r1, r1BandEnd, top, bot); + Coalesce(newReg, prevBand, curBand); + } + } + ytop = r2y1; + } else if (r2y1 < r1y1) { + if (appendNon2) { + top = max(r2y1, ybot); + bot = min(r2->y2, r1y1); + if (top != bot) { + curBand = newReg->data->numRects; + RegionAppendNonO(newReg, r2, r2BandEnd, top, bot); + Coalesce(newReg, prevBand, curBand); + } + } + ytop = r1y1; + } else { + ytop = r1y1; + } + + /* + * Now see if we've hit an intersecting band. The two bands only + * intersect if ybot > ytop + */ + ybot = min(r1->y2, r2->y2); + if (ybot > ytop) { + curBand = newReg->data->numRects; + (* overlapFunc)(newReg, r1, r1BandEnd, r2, r2BandEnd, ytop, ybot, + pOverlap); + Coalesce(newReg, prevBand, curBand); + } + + /* + * If we've finished with a band (y2 == ybot) we skip forward + * in the region to the next band. + */ + if (r1->y2 == ybot) r1 = r1BandEnd; + if (r2->y2 == ybot) r2 = r2BandEnd; + + } while (r1 != r1End && r2 != r2End); + + /* + * Deal with whichever region (if any) still has rectangles left. + * + * We only need to worry about banding and coalescing for the very first + * band left. After that, we can just group all remaining boxes, + * regardless of how many bands, into one final append to the list. + */ + + if ((r1 != r1End) && appendNon1) { + /* Do first nonOverlap1Func call, which may be able to coalesce */ + FindBand(r1, r1BandEnd, r1End, r1y1); + curBand = newReg->data->numRects; + RegionAppendNonO(newReg, r1, r1BandEnd, max(r1y1, ybot), r1->y2); + Coalesce(newReg, prevBand, curBand); + /* Just append the rest of the boxes */ + AppendRegions(newReg, r1BandEnd, r1End); + + } else if ((r2 != r2End) && appendNon2) { + /* Do first nonOverlap2Func call, which may be able to coalesce */ + FindBand(r2, r2BandEnd, r2End, r2y1); + curBand = newReg->data->numRects; + RegionAppendNonO(newReg, r2, r2BandEnd, max(r2y1, ybot), r2->y2); + Coalesce(newReg, prevBand, curBand); + /* Append rest of boxes */ + AppendRegions(newReg, r2BandEnd, r2End); + } + + free(oldData); + + if (!(numRects = newReg->data->numRects)) + { + xfreeData(newReg); + newReg->data = &RegionEmptyData; + } + else if (numRects == 1) + { + newReg->extents = *RegionBoxptr(newReg); + xfreeData(newReg); + newReg->data = NULL; + } + else + { + DOWNSIZE(newReg, numRects); + } + + return TRUE; +} + +/*- + *----------------------------------------------------------------------- + * RegionSetExtents -- + * Reset the extents of a region to what they should be. Called by + * Subtract and Intersect as they can't figure it out along the + * way or do so easily, as Union can. + * + * Results: + * None. + * + * Side Effects: + * The region's 'extents' structure is overwritten. + * + *----------------------------------------------------------------------- + */ +static void +RegionSetExtents (RegionPtr pReg) +{ + BoxPtr pBox, pBoxEnd; + + if (!pReg->data) + return; + if (!pReg->data->size) + { + pReg->extents.x2 = pReg->extents.x1; + pReg->extents.y2 = pReg->extents.y1; + return; + } + + pBox = RegionBoxptr(pReg); + pBoxEnd = RegionEnd(pReg); + + /* + * Since pBox is the first rectangle in the region, it must have the + * smallest y1 and since pBoxEnd is the last rectangle in the region, + * it must have the largest y2, because of banding. Initialize x1 and + * x2 from pBox and pBoxEnd, resp., as good things to initialize them + * to... + */ + pReg->extents.x1 = pBox->x1; + pReg->extents.y1 = pBox->y1; + pReg->extents.x2 = pBoxEnd->x2; + pReg->extents.y2 = pBoxEnd->y2; + + assert(pReg->extents.y1 < pReg->extents.y2); + while (pBox <= pBoxEnd) { + if (pBox->x1 < pReg->extents.x1) + pReg->extents.x1 = pBox->x1; + if (pBox->x2 > pReg->extents.x2) + pReg->extents.x2 = pBox->x2; + pBox++; + }; + + assert(pReg->extents.x1 < pReg->extents.x2); +} + +/*====================================================================== + * Region Intersection + *====================================================================*/ +/*- + *----------------------------------------------------------------------- + * RegionIntersectO -- + * Handle an overlapping band for RegionIntersect. + * + * Results: + * TRUE if successful. + * + * Side Effects: + * Rectangles may be added to the region. + * + *----------------------------------------------------------------------- + */ +/*ARGSUSED*/ + +#define MERGERECT(r) \ +{ \ + if (r->x1 <= x2) { \ + /* Merge with current rectangle */ \ + if (r->x1 < x2) *pOverlap = TRUE; \ + if (x2 < r->x2) x2 = r->x2; \ + } else { \ + /* Add current rectangle, start new one */ \ + NEWRECT(pReg, pNextRect, x1, y1, x2, y2); \ + x1 = r->x1; \ + x2 = r->x2; \ + } \ + r++; \ +} + +/*====================================================================== + * Region Union + *====================================================================*/ + +/*- + *----------------------------------------------------------------------- + * RegionUnionO -- + * Handle an overlapping band for the union operation. Picks the + * left-most rectangle each time and merges it into the region. + * + * Results: + * TRUE if successful. + * + * Side Effects: + * pReg is overwritten. + * pOverlap is set to TRUE if any boxes overlap. + * + *----------------------------------------------------------------------- + */ +static Bool +RegionUnionO ( + RegionPtr pReg, + BoxPtr r1, + BoxPtr r1End, + BoxPtr r2, + BoxPtr r2End, + short y1, + short y2, + Bool *pOverlap) +{ + BoxPtr pNextRect; + int x1; /* left and right side of current union */ + int x2; + + assert (y1 < y2); + assert(r1 != r1End && r2 != r2End); + + pNextRect = RegionTop(pReg); + + /* Start off current rectangle */ + if (r1->x1 < r2->x1) + { + x1 = r1->x1; + x2 = r1->x2; + r1++; + } + else + { + x1 = r2->x1; + x2 = r2->x2; + r2++; + } + while (r1 != r1End && r2 != r2End) + { + if (r1->x1 < r2->x1) MERGERECT(r1) else MERGERECT(r2); + } + + /* Finish off whoever (if any) is left */ + if (r1 != r1End) + { + do + { + MERGERECT(r1); + } while (r1 != r1End); + } + else if (r2 != r2End) + { + do + { + MERGERECT(r2); + } while (r2 != r2End); + } + + /* Add current rectangle */ + NEWRECT(pReg, pNextRect, x1, y1, x2, y2); + + return TRUE; +} + +/*====================================================================== + * Batch Rectangle Union + *====================================================================*/ + +/*- + *----------------------------------------------------------------------- + * RegionAppend -- + * + * "Append" the rgn rectangles onto the end of dstrgn, maintaining + * knowledge of YX-banding when it's easy. Otherwise, dstrgn just + * becomes a non-y-x-banded random collection of rectangles, and not + * yet a true region. After a sequence of appends, the caller must + * call RegionValidate to ensure that a valid region is constructed. + * + * Results: + * TRUE if successful. + * + * Side Effects: + * dstrgn is modified if rgn has rectangles. + * + */ +Bool +RegionAppend(RegionPtr dstrgn, RegionPtr rgn) +{ + int numRects, dnumRects, size; + BoxPtr new, old; + Bool prepend; + + if (RegionNar(rgn)) + return RegionBreak (dstrgn); + + if (!rgn->data && (dstrgn->data == &RegionEmptyData)) + { + dstrgn->extents = rgn->extents; + dstrgn->data = NULL; + return TRUE; + } + + numRects = RegionNumRects(rgn); + if (!numRects) + return TRUE; + prepend = FALSE; + size = numRects; + dnumRects = RegionNumRects(dstrgn); + if (!dnumRects && (size < 200)) + size = 200; /* XXX pick numbers out of a hat */ + RECTALLOC(dstrgn, size); + old = RegionRects(rgn); + if (!dnumRects) + dstrgn->extents = rgn->extents; + else if (dstrgn->extents.x2 > dstrgn->extents.x1) + { + BoxPtr first, last; + + first = old; + last = RegionBoxptr(dstrgn) + (dnumRects - 1); + if ((first->y1 > last->y2) || + ((first->y1 == last->y1) && (first->y2 == last->y2) && + (first->x1 > last->x2))) + { + if (rgn->extents.x1 < dstrgn->extents.x1) + dstrgn->extents.x1 = rgn->extents.x1; + if (rgn->extents.x2 > dstrgn->extents.x2) + dstrgn->extents.x2 = rgn->extents.x2; + dstrgn->extents.y2 = rgn->extents.y2; + } + else + { + first = RegionBoxptr(dstrgn); + last = old + (numRects - 1); + if ((first->y1 > last->y2) || + ((first->y1 == last->y1) && (first->y2 == last->y2) && + (first->x1 > last->x2))) + { + prepend = TRUE; + if (rgn->extents.x1 < dstrgn->extents.x1) + dstrgn->extents.x1 = rgn->extents.x1; + if (rgn->extents.x2 > dstrgn->extents.x2) + dstrgn->extents.x2 = rgn->extents.x2; + dstrgn->extents.y1 = rgn->extents.y1; + } + else + dstrgn->extents.x2 = dstrgn->extents.x1; + } + } + if (prepend) + { + new = RegionBox(dstrgn, numRects); + if (dnumRects == 1) + *new = *RegionBoxptr(dstrgn); + else + memmove((char *)new,(char *)RegionBoxptr(dstrgn), + dnumRects * sizeof(BoxRec)); + new = RegionBoxptr(dstrgn); + } + else + new = RegionBoxptr(dstrgn) + dnumRects; + if (numRects == 1) + *new = *old; + else + memmove((char *)new, (char *)old, numRects * sizeof(BoxRec)); + dstrgn->data->numRects += numRects; + return TRUE; +} + + +#define ExchangeRects(a, b) \ +{ \ + BoxRec t; \ + t = rects[a]; \ + rects[a] = rects[b]; \ + rects[b] = t; \ +} + +static void +QuickSortRects( + BoxRec rects[], + int numRects) +{ + int y1; + int x1; + int i, j; + BoxPtr r; + + /* Always called with numRects > 1 */ + + do + { + if (numRects == 2) + { + if (rects[0].y1 > rects[1].y1 || + (rects[0].y1 == rects[1].y1 && rects[0].x1 > rects[1].x1)) + ExchangeRects(0, 1); + return; + } + + /* Choose partition element, stick in location 0 */ + ExchangeRects(0, numRects >> 1); + y1 = rects[0].y1; + x1 = rects[0].x1; + + /* Partition array */ + i = 0; + j = numRects; + do + { + r = &(rects[i]); + do + { + r++; + i++; + } while (i != numRects && + (r->y1 < y1 || (r->y1 == y1 && r->x1 < x1))); + r = &(rects[j]); + do + { + r--; + j--; + } while (y1 < r->y1 || (y1 == r->y1 && x1 < r->x1)); + if (i < j) + ExchangeRects(i, j); + } while (i < j); + + /* Move partition element back to middle */ + ExchangeRects(0, j); + + /* Recurse */ + if (numRects-j-1 > 1) + QuickSortRects(&rects[j+1], numRects-j-1); + numRects = j; + } while (numRects > 1); +} + +/*- + *----------------------------------------------------------------------- + * RegionValidate -- + * + * Take a ``region'' which is a non-y-x-banded random collection of + * rectangles, and compute a nice region which is the union of all the + * rectangles. + * + * Results: + * TRUE if successful. + * + * Side Effects: + * The passed-in ``region'' may be modified. + * pOverlap set to TRUE if any retangles overlapped, else FALSE; + * + * Strategy: + * Step 1. Sort the rectangles into ascending order with primary key y1 + * and secondary key x1. + * + * Step 2. Split the rectangles into the minimum number of proper y-x + * banded regions. This may require horizontally merging + * rectangles, and vertically coalescing bands. With any luck, + * this step in an identity tranformation (ala the Box widget), + * or a coalescing into 1 box (ala Menus). + * + * Step 3. Merge the separate regions down to a single region by calling + * Union. Maximize the work each Union call does by using + * a binary merge. + * + *----------------------------------------------------------------------- + */ + +Bool +RegionValidate(RegionPtr badreg, Bool *pOverlap) +{ + /* Descriptor for regions under construction in Step 2. */ + typedef struct { + RegionRec reg; + int prevBand; + int curBand; + } RegionInfo; + + int numRects; /* Original numRects for badreg */ + RegionInfo *ri; /* Array of current regions */ + int numRI; /* Number of entries used in ri */ + int sizeRI; /* Number of entries available in ri */ + int i; /* Index into rects */ + int j; /* Index into ri */ + RegionInfo *rit; /* &ri[j] */ + RegionPtr reg; /* ri[j].reg */ + BoxPtr box; /* Current box in rects */ + BoxPtr riBox; /* Last box in ri[j].reg */ + RegionPtr hreg; /* ri[j_half].reg */ + Bool ret = TRUE; + + *pOverlap = FALSE; + if (!badreg->data) + { + good(badreg); + return TRUE; + } + numRects = badreg->data->numRects; + if (!numRects) + { + if (RegionNar(badreg)) + return FALSE; + good(badreg); + return TRUE; + } + if (badreg->extents.x1 < badreg->extents.x2) + { + if ((numRects) == 1) + { + xfreeData(badreg); + badreg->data = (RegDataPtr) NULL; + } + else + { + DOWNSIZE(badreg, numRects); + } + good(badreg); + return TRUE; + } + + /* Step 1: Sort the rects array into ascending (y1, x1) order */ + QuickSortRects(RegionBoxptr(badreg), numRects); + + /* Step 2: Scatter the sorted array into the minimum number of regions */ + + /* Set up the first region to be the first rectangle in badreg */ + /* Note that step 2 code will never overflow the ri[0].reg rects array */ + ri = (RegionInfo *) malloc(4 * sizeof(RegionInfo)); + if (!ri) + return RegionBreak (badreg); + sizeRI = 4; + numRI = 1; + ri[0].prevBand = 0; + ri[0].curBand = 0; + ri[0].reg = *badreg; + box = RegionBoxptr(&ri[0].reg); + ri[0].reg.extents = *box; + ri[0].reg.data->numRects = 1; + + /* Now scatter rectangles into the minimum set of valid regions. If the + next rectangle to be added to a region would force an existing rectangle + in the region to be split up in order to maintain y-x banding, just + forget it. Try the next region. If it doesn't fit cleanly into any + region, make a new one. */ + + for (i = numRects; --i > 0;) + { + box++; + /* Look for a region to append box to */ + for (j = numRI, rit = ri; --j >= 0; rit++) + { + reg = &rit->reg; + riBox = RegionEnd(reg); + + if (box->y1 == riBox->y1 && box->y2 == riBox->y2) + { + /* box is in same band as riBox. Merge or append it */ + if (box->x1 <= riBox->x2) + { + /* Merge it with riBox */ + if (box->x1 < riBox->x2) *pOverlap = TRUE; + if (box->x2 > riBox->x2) riBox->x2 = box->x2; + } + else + { + RECTALLOC_BAIL(reg, 1, bail); + *RegionTop(reg) = *box; + reg->data->numRects++; + } + goto NextRect; /* So sue me */ + } + else if (box->y1 >= riBox->y2) + { + /* Put box into new band */ + if (reg->extents.x2 < riBox->x2) reg->extents.x2 = riBox->x2; + if (reg->extents.x1 > box->x1) reg->extents.x1 = box->x1; + Coalesce(reg, rit->prevBand, rit->curBand); + rit->curBand = reg->data->numRects; + RECTALLOC_BAIL(reg, 1, bail); + *RegionTop(reg) = *box; + reg->data->numRects++; + goto NextRect; + } + /* Well, this region was inappropriate. Try the next one. */ + } /* for j */ + + /* Uh-oh. No regions were appropriate. Create a new one. */ + if (sizeRI == numRI) + { + /* Oops, allocate space for new region information */ + sizeRI <<= 1; + rit = (RegionInfo *) realloc(ri, sizeRI * sizeof(RegionInfo)); + if (!rit) + goto bail; + ri = rit; + rit = &ri[numRI]; + } + numRI++; + rit->prevBand = 0; + rit->curBand = 0; + rit->reg.extents = *box; + rit->reg.data = NULL; + if (!RegionRectAlloc(&rit->reg, (i+numRI) / numRI)) /* MUST force allocation */ + goto bail; +NextRect: ; + } /* for i */ + + /* Make a final pass over each region in order to Coalesce and set + extents.x2 and extents.y2 */ + + for (j = numRI, rit = ri; --j >= 0; rit++) + { + reg = &rit->reg; + riBox = RegionEnd(reg); + reg->extents.y2 = riBox->y2; + if (reg->extents.x2 < riBox->x2) reg->extents.x2 = riBox->x2; + Coalesce(reg, rit->prevBand, rit->curBand); + if (reg->data->numRects == 1) /* keep unions happy below */ + { + xfreeData(reg); + reg->data = NULL; + } + } + + /* Step 3: Union all regions into a single region */ + while (numRI > 1) + { + int half = numRI/2; + for (j = numRI & 1; j < (half + (numRI & 1)); j++) + { + reg = &ri[j].reg; + hreg = &ri[j+half].reg; + if (!RegionOp(reg, reg, hreg, RegionUnionO, TRUE, TRUE, pOverlap)) + ret = FALSE; + if (hreg->extents.x1 < reg->extents.x1) + reg->extents.x1 = hreg->extents.x1; + if (hreg->extents.y1 < reg->extents.y1) + reg->extents.y1 = hreg->extents.y1; + if (hreg->extents.x2 > reg->extents.x2) + reg->extents.x2 = hreg->extents.x2; + if (hreg->extents.y2 > reg->extents.y2) + reg->extents.y2 = hreg->extents.y2; + xfreeData(hreg); + } + numRI -= half; + } + *badreg = ri[0].reg; + free(ri); + good(badreg); + return ret; +bail: + for (i = 0; i < numRI; i++) + xfreeData(&ri[i].reg); + free(ri); + return RegionBreak (badreg); +} + +RegionPtr +RegionFromRects(int nrects, xRectangle *prect, int ctype) +{ + + RegionPtr pRgn; + RegDataPtr pData; + BoxPtr pBox; + int i; + int x1, y1, x2, y2; + + pRgn = RegionCreate(NullBox, 0); + if (RegionNar (pRgn)) + return pRgn; + if (!nrects) + return pRgn; + if (nrects == 1) + { + x1 = prect->x; + y1 = prect->y; + if ((x2 = x1 + (int) prect->width) > MAXSHORT) + x2 = MAXSHORT; + if ((y2 = y1 + (int) prect->height) > MAXSHORT) + y2 = MAXSHORT; + if (x1 != x2 && y1 != y2) + { + pRgn->extents.x1 = x1; + pRgn->extents.y1 = y1; + pRgn->extents.x2 = x2; + pRgn->extents.y2 = y2; + pRgn->data = NULL; + } + return pRgn; + } + pData = xallocData(nrects); + if (!pData) + { + RegionBreak (pRgn); + return pRgn; + } + pBox = (BoxPtr) (pData + 1); + for (i = nrects; --i >= 0; prect++) + { + x1 = prect->x; + y1 = prect->y; + if ((x2 = x1 + (int) prect->width) > MAXSHORT) + x2 = MAXSHORT; + if ((y2 = y1 + (int) prect->height) > MAXSHORT) + y2 = MAXSHORT; + if (x1 != x2 && y1 != y2) + { + pBox->x1 = x1; + pBox->y1 = y1; + pBox->x2 = x2; + pBox->y2 = y2; + pBox++; + } + } + if (pBox != (BoxPtr) (pData + 1)) + { + pData->size = nrects; + pData->numRects = pBox - (BoxPtr) (pData + 1); + pRgn->data = pData; + if (ctype != CT_YXBANDED) + { + Bool overlap; /* result ignored */ + pRgn->extents.x1 = pRgn->extents.x2 = 0; + RegionValidate(pRgn, &overlap); + } + else + RegionSetExtents(pRgn); + good(pRgn); + } + else + { + free(pData); + } + return pRgn; +} diff --git a/xorg-server/fb/fbpict.c b/xorg-server/fb/fbpict.c index c27fb4e20..312f3df21 100644 --- a/xorg-server/fb/fbpict.c +++ b/xorg-server/fb/fbpict.c @@ -1,371 +1,373 @@ -/*
- *
- * Copyright © 2000 SuSE, Inc.
- * Copyright © 2007 Red Hat, Inc.
- *
- * Permission to use, copy, modify, distribute, and sell this software and its
- * documentation for any purpose is hereby granted without fee, provided that
- * the above copyright notice appear in all copies and that both that
- * copyright notice and this permission notice appear in supporting
- * documentation, and that the name of SuSE not be used in advertising or
- * publicity pertaining to distribution of the software without specific,
- * written prior permission. SuSE makes no representations about the
- * suitability of this software for any purpose. It is provided "as is"
- * without express or implied warranty.
- *
- * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
- * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY 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 THIS SOFTWARE.
- *
- * Author: Keith Packard, SuSE, Inc.
- */
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#include <string.h>
-
-#include "fb.h"
-
-#include "picturestr.h"
-#include "mipict.h"
-#include "fbpict.h"
-
-void
-fbComposite (CARD8 op,
- PicturePtr pSrc,
- PicturePtr pMask,
- PicturePtr pDst,
- INT16 xSrc,
- INT16 ySrc,
- INT16 xMask,
- INT16 yMask,
- INT16 xDst,
- INT16 yDst,
- CARD16 width,
- CARD16 height)
-{
- pixman_image_t *src, *mask, *dest;
- int src_xoff, src_yoff;
- int msk_xoff, msk_yoff;
- int dst_xoff, dst_yoff;
-
- miCompositeSourceValidate (pSrc, xSrc - xDst, ySrc - yDst, width, height);
- if (pMask)
- miCompositeSourceValidate (pMask, xMask - xDst, yMask - yDst, width, height);
-
- src = image_from_pict (pSrc, FALSE, &src_xoff, &src_yoff);
- mask = image_from_pict (pMask, FALSE, &msk_xoff, &msk_yoff);
- dest = image_from_pict (pDst, TRUE, &dst_xoff, &dst_yoff);
-
- if (src && dest && !(pMask && !mask))
- {
- pixman_image_composite (op, src, mask, dest,
- xSrc + src_xoff, ySrc + src_yoff,
- xMask + msk_xoff, yMask + msk_yoff,
- xDst + dst_xoff, yDst + dst_yoff,
- width, height);
- }
-
- free_pixman_pict (pSrc, src);
- free_pixman_pict (pMask, mask);
- free_pixman_pict (pDst, dest);
-}
-
-static pixman_image_t *
-create_solid_fill_image (PicturePtr pict)
-{
- PictSolidFill *solid = &pict->pSourcePict->solidFill;
- pixman_color_t color;
- CARD32 a, r, g, b;
-
- a = (solid->color & 0xff000000) >> 24;
- r = (solid->color & 0x00ff0000) >> 16;
- g = (solid->color & 0x0000ff00) >> 8;
- b = (solid->color & 0x000000ff) >> 0;
-
- color.alpha = (a << 8) | a;
- color.red = (r << 8) | r;
- color.green = (g << 8) | g;
- color.blue = (b << 8) | b;
-
- return pixman_image_create_solid_fill (&color);
-}
-
-static pixman_image_t *
-create_linear_gradient_image (PictGradient *gradient)
-{
- PictLinearGradient *linear = (PictLinearGradient *)gradient;
- pixman_point_fixed_t p1;
- pixman_point_fixed_t p2;
-
- p1.x = linear->p1.x;
- p1.y = linear->p1.y;
- p2.x = linear->p2.x;
- p2.y = linear->p2.y;
-
- return pixman_image_create_linear_gradient (
- &p1, &p2, (pixman_gradient_stop_t *)gradient->stops, gradient->nstops);
-}
-
-static pixman_image_t *
-create_radial_gradient_image (PictGradient *gradient)
-{
- PictRadialGradient *radial = (PictRadialGradient *)gradient;
- pixman_point_fixed_t c1;
- pixman_point_fixed_t c2;
-
- c1.x = radial->c1.x;
- c1.y = radial->c1.y;
- c2.x = radial->c2.x;
- c2.y = radial->c2.y;
-
- return pixman_image_create_radial_gradient (
- &c1, &c2, radial->c1.radius,
- radial->c2.radius,
- (pixman_gradient_stop_t *)gradient->stops, gradient->nstops);
-}
-
-static pixman_image_t *
-create_conical_gradient_image (PictGradient *gradient)
-{
- PictConicalGradient *conical = (PictConicalGradient *)gradient;
- pixman_point_fixed_t center;
-
- center.x = conical->center.x;
- center.y = conical->center.y;
-
- return pixman_image_create_conical_gradient (
- ¢er, conical->angle, (pixman_gradient_stop_t *)gradient->stops,
- gradient->nstops);
-}
-
-static pixman_image_t *
-create_bits_picture (PicturePtr pict,
- Bool has_clip,
- int *xoff,
- int *yoff)
-{
- PixmapPtr pixmap;
- FbBits *bits;
- FbStride stride;
- int bpp;
- pixman_image_t *image;
-
- fbGetDrawablePixmap (pict->pDrawable, pixmap, *xoff, *yoff);
- fbGetPixmapBitsData(pixmap, bits, stride, bpp);
-
- image = pixman_image_create_bits (
- pict->format,
- pixmap->drawable.width, pixmap->drawable.height,
- (uint32_t *)bits, stride * sizeof (FbStride));
-
-
-#ifdef FB_ACCESS_WRAPPER
-#if FB_SHIFT==5
-
- pixman_image_set_accessors (image,
- (pixman_read_memory_func_t)wfbReadMemory,
- (pixman_write_memory_func_t)wfbWriteMemory);
-
-#else
-
-#error The pixman library only works when FbBits is 32 bits wide
-
-#endif
-#endif
-
- /* pCompositeClip is undefined for source pictures, so
- * only set the clip region for pictures with drawables
- */
- if (has_clip)
- {
- if (pict->clientClipType != CT_NONE)
- pixman_image_set_has_client_clip (image, TRUE);
-
- if (*xoff || *yoff)
- pixman_region_translate (pict->pCompositeClip, *xoff, *yoff);
-
- pixman_image_set_clip_region (image, pict->pCompositeClip);
-
- if (*xoff || *yoff)
- pixman_region_translate (pict->pCompositeClip, -*xoff, -*yoff);
- }
-
- /* Indexed table */
- if (pict->pFormat->index.devPrivate)
- pixman_image_set_indexed (image, pict->pFormat->index.devPrivate);
-
- /* Add in drawable origin to position within the image */
- *xoff += pict->pDrawable->x;
- *yoff += pict->pDrawable->y;
-
- return image;
-}
-
-static pixman_image_t *
-image_from_pict_internal (PicturePtr pict, Bool has_clip, int *xoff, int *yoff, Bool is_alpha_map);
-
-static void
-set_image_properties (pixman_image_t *image, PicturePtr pict, Bool has_clip, int *xoff, int *yoff, Bool is_alpha_map)
-{
- pixman_repeat_t repeat;
- pixman_filter_t filter;
-
- if (pict->transform)
- {
- /* For source images, adjust the transform to account
- * for the drawable offset within the pixman image,
- * then set the offset to 0 as it will be used
- * to compute positions within the transformed image.
- */
- if (!has_clip) {
- struct pixman_transform adjusted;
-
- adjusted = *pict->transform;
- pixman_transform_translate(&adjusted,
- NULL,
- pixman_int_to_fixed(*xoff),
- pixman_int_to_fixed(*yoff));
- pixman_image_set_transform (image, &adjusted);
- *xoff = 0;
- *yoff = 0;
- } else
- pixman_image_set_transform (image, pict->transform);
- }
-
- switch (pict->repeatType)
- {
- default:
- case RepeatNone:
- repeat = PIXMAN_REPEAT_NONE;
- break;
-
- case RepeatPad:
- repeat = PIXMAN_REPEAT_PAD;
- break;
-
- case RepeatNormal:
- repeat = PIXMAN_REPEAT_NORMAL;
- break;
-
- case RepeatReflect:
- repeat = PIXMAN_REPEAT_REFLECT;
- break;
- }
-
- pixman_image_set_repeat (image, repeat);
-
- /* Fetch alpha map unless 'pict' is being used
- * as the alpha map for this operation
- */
- if (pict->alphaMap && !is_alpha_map)
- {
- int alpha_xoff, alpha_yoff;
- pixman_image_t *alpha_map = image_from_pict_internal (pict->alphaMap, FALSE, &alpha_xoff, &alpha_yoff, TRUE);
-
- pixman_image_set_alpha_map (
- image, alpha_map, pict->alphaOrigin.x, pict->alphaOrigin.y);
-
- free_pixman_pict (pict->alphaMap, alpha_map);
- }
-
- pixman_image_set_component_alpha (image, pict->componentAlpha);
-
- switch (pict->filter)
- {
- default:
- case PictFilterNearest:
- case PictFilterFast:
- filter = PIXMAN_FILTER_NEAREST;
- break;
-
- case PictFilterBilinear:
- case PictFilterGood:
- filter = PIXMAN_FILTER_BILINEAR;
- break;
-
- case PictFilterConvolution:
- filter = PIXMAN_FILTER_CONVOLUTION;
- break;
- }
-
- pixman_image_set_filter (image, filter, (pixman_fixed_t *)pict->filter_params, pict->filter_nparams);
- pixman_image_set_source_clipping (image, TRUE);
-}
-
-static pixman_image_t *
-image_from_pict_internal (PicturePtr pict, Bool has_clip, int *xoff, int *yoff, Bool is_alpha_map)
-{
- pixman_image_t *image = NULL;
-
- if (!pict)
- return NULL;
-
- if (pict->pDrawable)
- {
- image = create_bits_picture (pict, has_clip, xoff, yoff);
- }
- else if (pict->pSourcePict)
- {
- SourcePict *sp = pict->pSourcePict;
-
- if (sp->type == SourcePictTypeSolidFill)
- {
- image = create_solid_fill_image (pict);
- }
- else
- {
- PictGradient *gradient = &pict->pSourcePict->gradient;
-
- if (sp->type == SourcePictTypeLinear)
- image = create_linear_gradient_image (gradient);
- else if (sp->type == SourcePictTypeRadial)
- image = create_radial_gradient_image (gradient);
- else if (sp->type == SourcePictTypeConical)
- image = create_conical_gradient_image (gradient);
- }
- *xoff = *yoff = 0;
- }
-
- if (image)
- set_image_properties (image, pict, has_clip, xoff, yoff, is_alpha_map);
-
- return image;
-}
-
-pixman_image_t *
-image_from_pict (PicturePtr pict, Bool has_clip, int *xoff, int *yoff)
-{
- return image_from_pict_internal (pict, has_clip, xoff, yoff, FALSE);
-}
-
-void
-free_pixman_pict (PicturePtr pict, pixman_image_t *image)
-{
- if (image && pixman_image_unref (image) && pict->pDrawable)
- fbFinishAccess (pict->pDrawable);
-}
-
-Bool
-fbPictureInit (ScreenPtr pScreen, PictFormatPtr formats, int nformats)
-{
-
- PictureScreenPtr ps;
-
- if (!miPictureInit (pScreen, formats, nformats))
- return FALSE;
- ps = GetPictureScreen(pScreen);
- ps->Composite = fbComposite;
- ps->Glyphs = miGlyphs;
- ps->CompositeRects = miCompositeRects;
- ps->RasterizeTrapezoid = fbRasterizeTrapezoid;
- ps->AddTraps = fbAddTraps;
- ps->AddTriangles = fbAddTriangles;
-
- return TRUE;
-}
+/* + * + * Copyright © 2000 SuSE, Inc. + * Copyright © 2007 Red Hat, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of SuSE not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. SuSE makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY 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 THIS SOFTWARE. + * + * Author: Keith Packard, SuSE, Inc. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include <string.h> + +#include "fb.h" + +#include "picturestr.h" +#include "mipict.h" +#include "fbpict.h" + +void +fbComposite (CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, + INT16 yDst, + CARD16 width, + CARD16 height) +{ + pixman_image_t *src, *mask, *dest; + int src_xoff, src_yoff; + int msk_xoff, msk_yoff; + int dst_xoff, dst_yoff; + + miCompositeSourceValidate (pSrc, xSrc - xDst, ySrc - yDst, width, height); + if (pMask) + miCompositeSourceValidate (pMask, xMask - xDst, yMask - yDst, width, height); + + src = image_from_pict (pSrc, FALSE, &src_xoff, &src_yoff); + mask = image_from_pict (pMask, FALSE, &msk_xoff, &msk_yoff); + dest = image_from_pict (pDst, TRUE, &dst_xoff, &dst_yoff); + + if (src && dest && !(pMask && !mask)) + { + pixman_image_composite (op, src, mask, dest, + xSrc + src_xoff, ySrc + src_yoff, + xMask + msk_xoff, yMask + msk_yoff, + xDst + dst_xoff, yDst + dst_yoff, + width, height); + } + + free_pixman_pict (pSrc, src); + free_pixman_pict (pMask, mask); + free_pixman_pict (pDst, dest); +} + +static pixman_image_t * +create_solid_fill_image (PicturePtr pict) +{ + PictSolidFill *solid = &pict->pSourcePict->solidFill; + pixman_color_t color; + CARD32 a, r, g, b; + + a = (solid->color & 0xff000000) >> 24; + r = (solid->color & 0x00ff0000) >> 16; + g = (solid->color & 0x0000ff00) >> 8; + b = (solid->color & 0x000000ff) >> 0; + + color.alpha = (a << 8) | a; + color.red = (r << 8) | r; + color.green = (g << 8) | g; + color.blue = (b << 8) | b; + + return pixman_image_create_solid_fill (&color); +} + +static pixman_image_t * +create_linear_gradient_image (PictGradient *gradient) +{ + PictLinearGradient *linear = (PictLinearGradient *)gradient; + pixman_point_fixed_t p1; + pixman_point_fixed_t p2; + + p1.x = linear->p1.x; + p1.y = linear->p1.y; + p2.x = linear->p2.x; + p2.y = linear->p2.y; + + return pixman_image_create_linear_gradient ( + &p1, &p2, (pixman_gradient_stop_t *)gradient->stops, gradient->nstops); +} + +static pixman_image_t * +create_radial_gradient_image (PictGradient *gradient) +{ + PictRadialGradient *radial = (PictRadialGradient *)gradient; + pixman_point_fixed_t c1; + pixman_point_fixed_t c2; + + c1.x = radial->c1.x; + c1.y = radial->c1.y; + c2.x = radial->c2.x; + c2.y = radial->c2.y; + + return pixman_image_create_radial_gradient ( + &c1, &c2, radial->c1.radius, + radial->c2.radius, + (pixman_gradient_stop_t *)gradient->stops, gradient->nstops); +} + +static pixman_image_t * +create_conical_gradient_image (PictGradient *gradient) +{ + PictConicalGradient *conical = (PictConicalGradient *)gradient; + pixman_point_fixed_t center; + + center.x = conical->center.x; + center.y = conical->center.y; + + return pixman_image_create_conical_gradient ( + ¢er, conical->angle, (pixman_gradient_stop_t *)gradient->stops, + gradient->nstops); +} + +static pixman_image_t * +create_bits_picture (PicturePtr pict, + Bool has_clip, + int *xoff, + int *yoff) +{ + PixmapPtr pixmap; + FbBits *bits; + FbStride stride; + int bpp; + pixman_image_t *image; + + fbGetDrawablePixmap (pict->pDrawable, pixmap, *xoff, *yoff); + fbGetPixmapBitsData(pixmap, bits, stride, bpp); + + image = pixman_image_create_bits ( + pict->format, + pixmap->drawable.width, pixmap->drawable.height, + (uint32_t *)bits, stride * sizeof (FbStride)); + + +#ifdef FB_ACCESS_WRAPPER +#if FB_SHIFT==5 + + pixman_image_set_accessors (image, + (pixman_read_memory_func_t)wfbReadMemory, + (pixman_write_memory_func_t)wfbWriteMemory); + +#else + +#error The pixman library only works when FbBits is 32 bits wide + +#endif +#endif + + /* pCompositeClip is undefined for source pictures, so + * only set the clip region for pictures with drawables + */ + if (has_clip) + { + if (pict->clientClipType != CT_NONE) + pixman_image_set_has_client_clip (image, TRUE); + + if (*xoff || *yoff) + pixman_region_translate (pict->pCompositeClip, *xoff, *yoff); + + pixman_image_set_clip_region (image, pict->pCompositeClip); + + if (*xoff || *yoff) + pixman_region_translate (pict->pCompositeClip, -*xoff, -*yoff); + } + + /* Indexed table */ + if (pict->pFormat->index.devPrivate) + pixman_image_set_indexed (image, pict->pFormat->index.devPrivate); + + /* Add in drawable origin to position within the image */ + *xoff += pict->pDrawable->x; + *yoff += pict->pDrawable->y; + + return image; +} + +static pixman_image_t * +image_from_pict_internal (PicturePtr pict, Bool has_clip, int *xoff, int *yoff, Bool is_alpha_map); + +static void +set_image_properties (pixman_image_t *image, PicturePtr pict, Bool has_clip, int *xoff, int *yoff, Bool is_alpha_map) +{ + pixman_repeat_t repeat; + pixman_filter_t filter; + + if (pict->transform) + { + /* For source images, adjust the transform to account + * for the drawable offset within the pixman image, + * then set the offset to 0 as it will be used + * to compute positions within the transformed image. + */ + if (!has_clip) { + struct pixman_transform adjusted; + + adjusted = *pict->transform; + pixman_transform_translate(&adjusted, + NULL, + pixman_int_to_fixed(*xoff), + pixman_int_to_fixed(*yoff)); + pixman_image_set_transform (image, &adjusted); + *xoff = 0; + *yoff = 0; + } else + pixman_image_set_transform (image, pict->transform); + } + + switch (pict->repeatType) + { + default: + case RepeatNone: + repeat = PIXMAN_REPEAT_NONE; + break; + + case RepeatPad: + repeat = PIXMAN_REPEAT_PAD; + break; + + case RepeatNormal: + repeat = PIXMAN_REPEAT_NORMAL; + break; + + case RepeatReflect: + repeat = PIXMAN_REPEAT_REFLECT; + break; + } + + pixman_image_set_repeat (image, repeat); + + /* Fetch alpha map unless 'pict' is being used + * as the alpha map for this operation + */ + if (pict->alphaMap && !is_alpha_map) + { + int alpha_xoff, alpha_yoff; + pixman_image_t *alpha_map = image_from_pict_internal (pict->alphaMap, FALSE, &alpha_xoff, &alpha_yoff, TRUE); + + pixman_image_set_alpha_map ( + image, alpha_map, pict->alphaOrigin.x, pict->alphaOrigin.y); + + free_pixman_pict (pict->alphaMap, alpha_map); + } + + pixman_image_set_component_alpha (image, pict->componentAlpha); + + switch (pict->filter) + { + default: + case PictFilterNearest: + case PictFilterFast: + filter = PIXMAN_FILTER_NEAREST; + break; + + case PictFilterBilinear: + case PictFilterGood: + filter = PIXMAN_FILTER_BILINEAR; + break; + + case PictFilterConvolution: + filter = PIXMAN_FILTER_CONVOLUTION; + break; + } + + pixman_image_set_filter (image, filter, (pixman_fixed_t *)pict->filter_params, pict->filter_nparams); + pixman_image_set_source_clipping (image, TRUE); +} + +static pixman_image_t * +image_from_pict_internal (PicturePtr pict, Bool has_clip, int *xoff, int *yoff, Bool is_alpha_map) +{ + pixman_image_t *image = NULL; + + if (!pict) + return NULL; + + if (pict->pDrawable) + { + image = create_bits_picture (pict, has_clip, xoff, yoff); + } + else if (pict->pSourcePict) + { + SourcePict *sp = pict->pSourcePict; + + if (sp->type == SourcePictTypeSolidFill) + { + image = create_solid_fill_image (pict); + } + else + { + PictGradient *gradient = &pict->pSourcePict->gradient; + + if (sp->type == SourcePictTypeLinear) + image = create_linear_gradient_image (gradient); + else if (sp->type == SourcePictTypeRadial) + image = create_radial_gradient_image (gradient); + else if (sp->type == SourcePictTypeConical) + image = create_conical_gradient_image (gradient); + } + *xoff = *yoff = 0; + } + + if (image) + set_image_properties (image, pict, has_clip, xoff, yoff, is_alpha_map); + + return image; +} + +pixman_image_t * +image_from_pict (PicturePtr pict, Bool has_clip, int *xoff, int *yoff) +{ + return image_from_pict_internal (pict, has_clip, xoff, yoff, FALSE); +} + +void +free_pixman_pict (PicturePtr pict, pixman_image_t *image) +{ + if (image && pixman_image_unref (image) && pict->pDrawable) + fbFinishAccess (pict->pDrawable); +} + +Bool +fbPictureInit (ScreenPtr pScreen, PictFormatPtr formats, int nformats) +{ + + PictureScreenPtr ps; + + if (!miPictureInit (pScreen, formats, nformats)) + return FALSE; + ps = GetPictureScreen(pScreen); + ps->Composite = fbComposite; + ps->Glyphs = miGlyphs; + ps->CompositeRects = miCompositeRects; + ps->RasterizeTrapezoid = fbRasterizeTrapezoid; + ps->Trapezoids = fbTrapezoids; + ps->AddTraps = fbAddTraps; + ps->AddTriangles = fbAddTriangles; + ps->Triangles = fbTriangles; + + return TRUE; +} diff --git a/xorg-server/fb/fbpict.h b/xorg-server/fb/fbpict.h index e7daaa245..b880ebbe1 100644 --- a/xorg-server/fb/fbpict.h +++ b/xorg-server/fb/fbpict.h @@ -1,68 +1,88 @@ -/*
- *
- * Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc.
- *
- * Permission to use, copy, modify, distribute, and sell this software and its
- * documentation for any purpose is hereby granted without fee, provided that
- * the above copyright notice appear in all copies and that both that
- * copyright notice and this permission notice appear in supporting
- * documentation, and that the name of Keith Packard not be used in
- * advertising or publicity pertaining to distribution of the software without
- * specific, written prior permission. Keith Packard makes no
- * representations about the suitability of this software for any purpose. It
- * is provided "as is" without express or implied warranty.
- *
- * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
- * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
- * CONSEQUENTIAL DAMAGES OR ANY 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 THIS SOFTWARE.
- */
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#ifndef _FBPICT_H_
-#define _FBPICT_H_
-
-/* fbpict.c */
-extern _X_EXPORT void
-fbComposite (CARD8 op,
- PicturePtr pSrc,
- PicturePtr pMask,
- PicturePtr pDst,
- INT16 xSrc,
- INT16 ySrc,
- INT16 xMask,
- INT16 yMask,
- INT16 xDst,
- INT16 yDst,
- CARD16 width,
- CARD16 height);
-
-/* fbtrap.c */
-
-extern _X_EXPORT void
-fbAddTraps (PicturePtr pPicture,
- INT16 xOff,
- INT16 yOff,
- int ntrap,
- xTrap *traps);
-
-extern _X_EXPORT void
-fbRasterizeTrapezoid (PicturePtr alpha,
- xTrapezoid *trap,
- int x_off,
- int y_off);
-
-extern _X_EXPORT void
-fbAddTriangles (PicturePtr pPicture,
- INT16 xOff,
- INT16 yOff,
- int ntri,
- xTriangle *tris);
-
-#endif /* _FBPICT_H_ */
+/* + * + * Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY 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 THIS SOFTWARE. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#ifndef _FBPICT_H_ +#define _FBPICT_H_ + +/* fbpict.c */ +extern _X_EXPORT void +fbComposite (CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, + INT16 yDst, + CARD16 width, + CARD16 height); + +/* fbtrap.c */ + +extern _X_EXPORT void +fbAddTraps (PicturePtr pPicture, + INT16 xOff, + INT16 yOff, + int ntrap, + xTrap *traps); + +extern _X_EXPORT void +fbRasterizeTrapezoid (PicturePtr alpha, + xTrapezoid *trap, + int x_off, + int y_off); + +extern _X_EXPORT void +fbAddTriangles (PicturePtr pPicture, + INT16 xOff, + INT16 yOff, + int ntri, + xTriangle *tris); + +extern _X_EXPORT void +fbTrapezoids (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int ntrap, + xTrapezoid *traps); + +extern _X_EXPORT void +fbTriangles (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int ntris, + xTriangle *tris); + +#endif /* _FBPICT_H_ */ diff --git a/xorg-server/fb/fbtrap.c b/xorg-server/fb/fbtrap.c index e52f84cd7..2554fccbf 100644 --- a/xorg-server/fb/fbtrap.c +++ b/xorg-server/fb/fbtrap.c @@ -1,159 +1,210 @@ -/*
- * Copyright © 2004 Keith Packard
- *
- * Permission to use, copy, modify, distribute, and sell this software and its
- * documentation for any purpose is hereby granted without fee, provided that
- * the above copyright notice appear in all copies and that both that
- * copyright notice and this permission notice appear in supporting
- * documentation, and that the name of Keith Packard not be used in
- * advertising or publicity pertaining to distribution of the software without
- * specific, written prior permission. Keith Packard makes no
- * representations about the suitability of this software for any purpose. It
- * is provided "as is" without express or implied warranty.
- *
- * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
- * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
- * CONSEQUENTIAL DAMAGES OR ANY 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 THIS SOFTWARE.
- */
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#include "fb.h"
-
-#include "picturestr.h"
-#include "mipict.h"
-#include "fbpict.h"
-
-void
-fbAddTraps (PicturePtr pPicture,
- INT16 x_off,
- INT16 y_off,
- int ntrap,
- xTrap *traps)
-{
- int image_xoff, image_yoff;
- pixman_image_t *image = image_from_pict (pPicture, FALSE, &image_xoff, &image_yoff);
-
- if (!image)
- return;
-
- pixman_add_traps (image, x_off, y_off, ntrap, (pixman_trap_t *)traps);
-
- free_pixman_pict (pPicture, image);
-}
-
-void
-fbRasterizeTrapezoid (PicturePtr pPicture,
- xTrapezoid *trap,
- int x_off,
- int y_off)
-{
- int mask_xoff, mask_yoff;
- pixman_image_t *image = image_from_pict (pPicture, FALSE, &mask_xoff, &mask_yoff);
-
- if (!image)
- return;
-
- pixman_rasterize_trapezoid (image, (pixman_trapezoid_t *)trap, x_off, y_off);
-
- free_pixman_pict (pPicture, image);
-}
-
-static int
-_GreaterY (xPointFixed *a, xPointFixed *b)
-{
- if (a->y == b->y)
- return a->x > b->x;
- return a->y > b->y;
-}
-
-/*
- * Note that the definition of this function is a bit odd because
- * of the X coordinate space (y increasing downwards).
- */
-static int
-_Clockwise (xPointFixed *ref, xPointFixed *a, xPointFixed *b)
-{
- xPointFixed ad, bd;
-
- ad.x = a->x - ref->x;
- ad.y = a->y - ref->y;
- bd.x = b->x - ref->x;
- bd.y = b->y - ref->y;
-
- return ((xFixed_32_32) bd.y * ad.x - (xFixed_32_32) ad.y * bd.x) < 0;
-}
-
-/* FIXME -- this could be made more efficient */
-void
-fbAddTriangles (PicturePtr pPicture,
- INT16 x_off,
- INT16 y_off,
- int ntri,
- xTriangle *tris)
-{
- xPointFixed *top, *left, *right, *tmp;
- xTrapezoid trap;
-
- for (; ntri; ntri--, tris++)
- {
- top = &tris->p1;
- left = &tris->p2;
- right = &tris->p3;
- if (_GreaterY (top, left)) {
- tmp = left; left = top; top = tmp;
- }
- if (_GreaterY (top, right)) {
- tmp = right; right = top; top = tmp;
- }
- if (_Clockwise (top, right, left)) {
- tmp = right; right = left; left = tmp;
- }
-
- /*
- * Two cases:
- *
- * + +
- * / \ / \
- * / \ / \
- * / + + \
- * / -- -- \
- * / -- -- \
- * / --- --- \
- * +-- --+
- */
-
- trap.top = top->y;
- trap.left.p1 = *top;
- trap.left.p2 = *left;
- trap.right.p1 = *top;
- trap.right.p2 = *right;
- if (right->y < left->y)
- trap.bottom = right->y;
- else
- trap.bottom = left->y;
- fbRasterizeTrapezoid (pPicture, &trap, x_off, y_off);
- if (right->y < left->y)
- {
- trap.top = right->y;
- trap.bottom = left->y;
- trap.right.p1 = *right;
- trap.right.p2 = *left;
- }
- else
- {
- trap.top = left->y;
- trap.bottom = right->y;
- trap.left.p1 = *left;
- trap.left.p2 = *right;
- }
- fbRasterizeTrapezoid (pPicture, &trap, x_off, y_off);
- }
-}
-
+/* + * Copyright © 2004 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY 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 THIS SOFTWARE. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include "fb.h" + +#include "picturestr.h" +#include "mipict.h" +#include "fbpict.h" + +void +fbAddTraps (PicturePtr pPicture, + INT16 x_off, + INT16 y_off, + int ntrap, + xTrap *traps) +{ + int image_xoff, image_yoff; + pixman_image_t *image = image_from_pict (pPicture, FALSE, &image_xoff, &image_yoff); + + if (!image) + return; + + pixman_add_traps (image, x_off, y_off, ntrap, (pixman_trap_t *)traps); + + free_pixman_pict (pPicture, image); +} + +void +fbRasterizeTrapezoid (PicturePtr pPicture, + xTrapezoid *trap, + int x_off, + int y_off) +{ + int mask_xoff, mask_yoff; + pixman_image_t *image = image_from_pict (pPicture, FALSE, &mask_xoff, &mask_yoff); + + if (!image) + return; + + pixman_rasterize_trapezoid (image, (pixman_trapezoid_t *)trap, x_off, y_off); + + free_pixman_pict (pPicture, image); +} + +void +fbAddTriangles (PicturePtr pPicture, + INT16 x_off, + INT16 y_off, + int ntri, + xTriangle *tris) +{ + int image_xoff, image_yoff; + pixman_image_t *image = + image_from_pict (pPicture, FALSE, &image_xoff, &image_yoff); + + if (!image) + return; + + pixman_add_triangles (image, x_off, y_off, ntri, (pixman_triangle_t *)tris); + + free_pixman_pict (pPicture, image); +} + +typedef void (* CompositeShapesFunc) (pixman_op_t op, + pixman_image_t *src, + pixman_image_t *dst, + pixman_format_code_t mask_format, + int x_src, int y_src, + int x_dst, int y_dst, + int n_shapes, const uint8_t *shapes); + +static void +fbShapes (CompositeShapesFunc composite, + pixman_op_t op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + int16_t xSrc, + int16_t ySrc, + int16_t xDst, + int16_t yDst, + int nshapes, + int shape_size, + const uint8_t * shapes) +{ + pixman_image_t *src, *dst; + int src_xoff, src_yoff; + int dst_xoff, dst_yoff; + + src = image_from_pict (pSrc, FALSE, &src_xoff, &src_yoff); + dst = image_from_pict (pDst, TRUE, &dst_xoff, &dst_yoff); + + if (src && dst) + { + pixman_format_code_t format; + + if (!maskFormat) + { + int i; + + if (pDst->polyEdge == PolyEdgeSharp) + format = PIXMAN_a1; + else + format = PIXMAN_a8; + + for (i = 0; i < nshapes; ++i) + { + composite (op, src, dst, format, + xSrc + src_xoff, + ySrc + src_yoff, + xDst + dst_xoff, + yDst + dst_yoff, + 1, shapes + i * shape_size); + } + } + else + { + switch (PICT_FORMAT_A (maskFormat->format)) + { + case 1: + format = PIXMAN_a1; + break; + + case 4: + format = PIXMAN_a4; + break; + + default: + case 8: + format = PIXMAN_a8; + break; + } + + composite (op, src, dst, format, + xSrc + src_xoff, + ySrc + src_yoff, + xDst + dst_xoff, + yDst + dst_yoff, + nshapes, shapes); + } + } + + free_pixman_pict (pSrc, src); + free_pixman_pict (pDst, dst); +} + +void +fbTrapezoids (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int ntrap, + xTrapezoid *traps) +{ + int xDst, yDst; + + xDst = traps[0].left.p1.x >> 16; + yDst = traps[0].left.p1.y >> 16; + + fbShapes ((CompositeShapesFunc)pixman_composite_trapezoids, + op, pSrc, pDst, maskFormat, + xSrc, ySrc, xDst, yDst, + ntrap, sizeof (xTrapezoid), (const uint8_t *)traps); +} + +void +fbTriangles (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int ntris, + xTriangle *tris) +{ + int xDst, yDst; + + xDst = tris[0].p1.x >> 16; + yDst = tris[0].p1.y >> 16; + + fbShapes ((CompositeShapesFunc)pixman_composite_triangles, + op, pSrc, pDst, maskFormat, + xSrc, ySrc, xDst, yDst, + ntris, sizeof (xTriangle), (const uint8_t *)tris); +} diff --git a/xorg-server/hw/xfree86/common/xf86Config.c b/xorg-server/hw/xfree86/common/xf86Config.c index 4246f6d71..9602e899f 100644 --- a/xorg-server/hw/xfree86/common/xf86Config.c +++ b/xorg-server/hw/xfree86/common/xf86Config.c @@ -1,2513 +1,2515 @@ -/*
- * Loosely based on code bearing the following copyright:
- *
- * Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany.
- */
-
-/*
- * Copyright 1992-2003 by The XFree86 Project, Inc.
- * Copyright 1997 by Metro Link, Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- *
- * Except as contained in this notice, the name of the copyright holder(s)
- * and author(s) shall not be used in advertising or otherwise to promote
- * the sale, use or other dealings in this Software without prior written
- * authorization from the copyright holder(s) and author(s).
- */
-
-/*
- *
- * Authors:
- * Dirk Hohndel <hohndel@XFree86.Org>
- * David Dawes <dawes@XFree86.Org>
- * Marc La France <tsi@XFree86.Org>
- * Egbert Eich <eich@XFree86.Org>
- * ... and others
- */
-
-#ifdef HAVE_XORG_CONFIG_H
-#include <xorg-config.h>
-#endif
-
-#ifdef XF86DRI
-#include <sys/types.h>
-#include <grp.h>
-#endif
-
-#include "xf86.h"
-#include "xf86Parser.h"
-#include "xf86tokens.h"
-#include "xf86Config.h"
-#include "xf86Priv.h"
-#include "xf86_OSlib.h"
-#include "configProcs.h"
-#include "globals.h"
-#include "extension.h"
-#include "xf86pciBus.h"
-
-#include "xf86Xinput.h"
-
-#include "xkbsrv.h"
-
-#include "picture.h"
-
-/*
- * These paths define the way the config file search is done. The escape
- * sequences are documented in parser/scan.c.
- */
-#ifndef ROOT_CONFIGPATH
-#define ROOT_CONFIGPATH "%A," "%R," \
- "/etc/X11/%R," "%P/etc/X11/%R," \
- "%E," "%F," \
- "/etc/X11/%F," "%P/etc/X11/%F," \
- "/etc/X11/%X," "/etc/%X," \
- "%P/etc/X11/%X.%H," \
- "%P/etc/X11/%X," \
- "%P/lib/X11/%X.%H," \
- "%P/lib/X11/%X"
-#endif
-#ifndef USER_CONFIGPATH
-#define USER_CONFIGPATH "/etc/X11/%S," "%P/etc/X11/%S," \
- "/etc/X11/%G," "%P/etc/X11/%G," \
- "/etc/X11/%X," "/etc/%X," \
- "%P/etc/X11/%X.%H," \
- "%P/etc/X11/%X," \
- "%P/lib/X11/%X.%H," \
- "%P/lib/X11/%X"
-#endif
-#ifndef ROOT_CONFIGDIRPATH
-#define ROOT_CONFIGDIRPATH "%A," "%R," \
- "/etc/X11/%R," "%C/X11/%R," \
- "/etc/X11/%X," "%C/X11/%X"
-#endif
-#ifndef USER_CONFIGDIRPATH
-#define USER_CONFIGDIRPATH "/etc/X11/%R," "%C/X11/%R," \
- "/etc/X11/%X," "%C/X11/%X"
-#endif
-#ifndef SYS_CONFIGDIRPATH
-#define SYS_CONFIGDIRPATH "/usr/share/X11/%X," "%D/X11/%X"
-#endif
-#ifndef PROJECTROOT
-#define PROJECTROOT "/usr/X11R6"
-#endif
-
-static ModuleDefault ModuleDefaults[] = {
- {.name = "extmod", .toLoad = TRUE, .load_opt=NULL},
-#ifdef DBE
- {.name = "dbe", .toLoad = TRUE, .load_opt=NULL},
-#endif
-#ifdef GLXEXT
- {.name = "glx", .toLoad = TRUE, .load_opt=NULL},
-#endif
-#ifdef XRECORD
- {.name = "record", .toLoad = TRUE, .load_opt=NULL},
-#endif
-#ifdef XF86DRI
- {.name = "dri", .toLoad = TRUE, .load_opt=NULL},
-#endif
-#ifdef DRI2
- {.name = "dri2", .toLoad = TRUE, .load_opt=NULL},
-#endif
- {.name = NULL, .toLoad = FALSE, .load_opt=NULL}
-};
-
-
-/* Forward declarations */
-static Bool configScreen(confScreenPtr screenp, XF86ConfScreenPtr conf_screen,
- int scrnum, MessageType from);
-static Bool configMonitor(MonPtr monitorp, XF86ConfMonitorPtr conf_monitor);
-static Bool configDevice(GDevPtr devicep, XF86ConfDevicePtr conf_device,
- Bool active);
-static Bool configInput(InputInfoPtr pInfo, XF86ConfInputPtr conf_input,
- MessageType from);
-static Bool configDisplay(DispPtr displayp, XF86ConfDisplayPtr conf_display);
-static Bool addDefaultModes(MonPtr monitorp);
-#ifdef XF86DRI
-static void configDRI(XF86ConfDRIPtr drip);
-#endif
-static void configExtensions(XF86ConfExtensionsPtr conf_ext);
-
-/*
- * xf86GetPathElem --
- * Extract a single element from the font path string starting at
- * pnt. The font path element will be returned, and pnt will be
- * updated to point to the start of the next element, or set to
- * NULL if there are no more.
- */
-static char *
-xf86GetPathElem(char **pnt)
-{
- char *p1;
-
- p1 = *pnt;
- *pnt = index(*pnt, ',');
- if (*pnt != NULL) {
- **pnt = '\0';
- *pnt += 1;
- }
- return p1;
-}
-
-/*
- * xf86ValidateFontPath --
- * Validates the user-specified font path. Each element that
- * begins with a '/' is checked to make sure the directory exists.
- * If the directory exists, the existence of a file named 'fonts.dir'
- * is checked. If either check fails, an error is printed and the
- * element is removed from the font path.
- */
-
-#define DIR_FILE "/fonts.dir"
-static char *
-xf86ValidateFontPath(char *path)
-{
- char *tmp_path, *out_pnt, *path_elem, *next, *p1, *dir_elem;
- struct stat stat_buf;
- int flag;
- int dirlen;
-
- tmp_path = calloc(1,strlen(path)+1);
- out_pnt = tmp_path;
- path_elem = NULL;
- next = path;
- while (next != NULL) {
- path_elem = xf86GetPathElem(&next);
- if (*path_elem == '/') {
- dir_elem = xnfcalloc(1, strlen(path_elem) + 1);
- if ((p1 = strchr(path_elem, ':')) != 0)
- dirlen = p1 - path_elem;
- else
- dirlen = strlen(path_elem);
- strncpy(dir_elem, path_elem, dirlen);
- dir_elem[dirlen] = '\0';
- flag = stat(dir_elem, &stat_buf);
- if (flag == 0)
- if (!S_ISDIR(stat_buf.st_mode))
- flag = -1;
- if (flag != 0) {
- xf86Msg(X_WARNING, "The directory \"%s\" does not exist.\n", dir_elem);
- xf86ErrorF("\tEntry deleted from font path.\n");
- free(dir_elem);
- continue;
- }
- else {
- XNFasprintf(&p1, "%s%s", dir_elem, DIR_FILE);
- flag = stat(p1, &stat_buf);
- if (flag == 0)
- if (!S_ISREG(stat_buf.st_mode))
- flag = -1;
- free(p1);
- if (flag != 0) {
- xf86Msg(X_WARNING,
- "`fonts.dir' not found (or not valid) in \"%s\".\n",
- dir_elem);
- xf86ErrorF("\tEntry deleted from font path.\n");
- xf86ErrorF("\t(Run 'mkfontdir' on \"%s\").\n", dir_elem);
- free(dir_elem);
- continue;
- }
- }
- free(dir_elem);
- }
-
- /*
- * Either an OK directory, or a font server name. So add it to
- * the path.
- */
- if (out_pnt != tmp_path)
- *out_pnt++ = ',';
- strcat(out_pnt, path_elem);
- out_pnt += strlen(path_elem);
- }
- return tmp_path;
-}
-
-
-/*
- * use the datastructure that the parser provides and pick out the parts
- * that we need at this point
- */
-char **
-xf86ModulelistFromConfig(pointer **optlist)
-{
- int count = 0, i = 0;
- char **modulearray;
- char *ignore[] = { "GLcore", "speedo", "bitmap", "drm",
- "freetype", "type1",
- NULL };
- pointer *optarray;
- XF86LoadPtr modp;
- Bool found;
-
- /*
- * make sure the config file has been parsed and that we have a
- * ModulePath set; if no ModulePath was given, use the default
- * ModulePath
- */
- if (xf86configptr == NULL) {
- xf86Msg(X_ERROR, "Cannot access global config data structure\n");
- return NULL;
- }
-
- if (xf86configptr->conf_modules) {
- /* Walk the disable list and let people know what we've parsed to
- * not be loaded
- */
- modp = xf86configptr->conf_modules->mod_disable_lst;
- while (modp) {
- xf86Msg(X_WARNING, "\"%s\" will not be loaded unless you've specified it to be loaded elsewhere.\n", modp->load_name);
- modp = (XF86LoadPtr) modp->list.next;
- }
- /*
- * Walk the default settings table. For each module listed to be
- * loaded, make sure it's in the mod_load_lst. If it's not, make
- * sure it's not in the mod_no_load_lst. If it's not disabled,
- * append it to mod_load_lst
- */
- for (i=0 ; ModuleDefaults[i].name != NULL ; i++) {
- if (ModuleDefaults[i].toLoad == FALSE) {
- xf86Msg(X_WARNING, "\"%s\" is not to be loaded by default. Skipping.\n", ModuleDefaults[i].name);
- continue;
- }
- found = FALSE;
- modp = xf86configptr->conf_modules->mod_load_lst;
- while (modp) {
- if (strcmp(modp->load_name, ModuleDefaults[i].name) == 0) {
- xf86Msg(X_INFO, "\"%s\" will be loaded. This was enabled by default and also specified in the config file.\n", ModuleDefaults[i].name);
- found = TRUE;
- break;
- }
- modp = (XF86LoadPtr) modp->list.next;
- }
- if (found == FALSE) {
- modp = xf86configptr->conf_modules->mod_disable_lst;
- while (modp) {
- if (strcmp(modp->load_name, ModuleDefaults[i].name) == 0) {
- xf86Msg(X_INFO, "\"%s\" will be loaded even though the default is to disable it.\n", ModuleDefaults[i].name);
- found = TRUE;
- break;
- }
- modp = (XF86LoadPtr) modp->list.next;
- }
- }
- if (found == FALSE) {
- XF86LoadPtr ptr = (XF86LoadPtr)xf86configptr->conf_modules;
- ptr = xf86addNewLoadDirective(ptr, ModuleDefaults[i].name, XF86_LOAD_MODULE, ModuleDefaults[i].load_opt);
- xf86Msg(X_INFO, "\"%s\" will be loaded by default.\n", ModuleDefaults[i].name);
- }
- }
- } else {
- xf86configptr->conf_modules = xnfcalloc(1, sizeof(XF86ConfModuleRec));
- for (i=0 ; ModuleDefaults[i].name != NULL ; i++) {
- if (ModuleDefaults[i].toLoad == TRUE) {
- XF86LoadPtr ptr = (XF86LoadPtr)xf86configptr->conf_modules;
- ptr = xf86addNewLoadDirective(ptr, ModuleDefaults[i].name, XF86_LOAD_MODULE, ModuleDefaults[i].load_opt);
- }
- }
- }
-
- /*
- * Walk the list of modules in the "Module" section to determine how
- * many we have.
- */
- modp = xf86configptr->conf_modules->mod_load_lst;
- while (modp) {
- for (i = 0; ignore[i]; i++) {
- if (strcmp(modp->load_name, ignore[i]) == 0)
- modp->ignore = 1;
- }
- if (!modp->ignore)
- count++;
- modp = (XF86LoadPtr) modp->list.next;
- }
-
- /*
- * allocate the memory and walk the list again to fill in the pointers
- */
- modulearray = xnfalloc((count + 1) * sizeof(char*));
- optarray = xnfalloc((count + 1) * sizeof(pointer));
- count = 0;
- if (xf86configptr->conf_modules) {
- modp = xf86configptr->conf_modules->mod_load_lst;
- while (modp) {
- if (!modp->ignore) {
- modulearray[count] = modp->load_name;
- optarray[count] = modp->load_opt;
- count++;
- }
- modp = (XF86LoadPtr) modp->list.next;
- }
- }
- modulearray[count] = NULL;
- optarray[count] = NULL;
- if (optlist)
- *optlist = optarray;
- else
- free(optarray);
- return modulearray;
-}
-
-
-char **
-xf86DriverlistFromConfig(void)
-{
- int count = 0;
- int j;
- char **modulearray;
- screenLayoutPtr slp;
-
- /*
- * make sure the config file has been parsed and that we have a
- * ModulePath set; if no ModulePath was given, use the default
- * ModulePath
- */
- if (xf86configptr == NULL) {
- xf86Msg(X_ERROR, "Cannot access global config data structure\n");
- return NULL;
- }
-
- /*
- * Walk the list of driver lines in active "Device" sections to
- * determine now many implicitly loaded modules there are.
- *
- */
- if (xf86ConfigLayout.screens) {
- slp = xf86ConfigLayout.screens;
- while ((slp++)->screen) {
- count++;
- }
- }
-
- /*
- * Handle the set of inactive "Device" sections.
- */
- j = 0;
- while (xf86ConfigLayout.inactives[j++].identifier)
- count++;
-
- if (count == 0)
- return NULL;
-
- /*
- * allocate the memory and walk the list again to fill in the pointers
- */
- modulearray = xnfalloc((count + 1) * sizeof(char*));
- count = 0;
- slp = xf86ConfigLayout.screens;
- while (slp->screen) {
- modulearray[count] = slp->screen->device->driver;
- count++;
- slp++;
- }
-
- j = 0;
-
- while (xf86ConfigLayout.inactives[j].identifier)
- modulearray[count++] = xf86ConfigLayout.inactives[j++].driver;
-
- modulearray[count] = NULL;
-
- /* Remove duplicates */
- for (count = 0; modulearray[count] != NULL; count++) {
- int i;
-
- for (i = 0; i < count; i++)
- if (xf86NameCmp(modulearray[i], modulearray[count]) == 0) {
- modulearray[count] = "";
- break;
- }
- }
- return modulearray;
-}
-
-char **
-xf86InputDriverlistFromConfig(void)
-{
- int count = 0;
- char **modulearray;
- InputInfoPtr *idp;
-
- /*
- * make sure the config file has been parsed and that we have a
- * ModulePath set; if no ModulePath was given, use the default
- * ModulePath
- */
- if (xf86configptr == NULL) {
- xf86Msg(X_ERROR, "Cannot access global config data structure\n");
- return NULL;
- }
-
- /*
- * Walk the list of driver lines in active "InputDevice" sections to
- * determine now many implicitly loaded modules there are.
- */
- if (xf86ConfigLayout.inputs) {
- idp = xf86ConfigLayout.inputs;
- while (*idp) {
- count++;
- idp++;
- }
- }
-
- if (count == 0)
- return NULL;
-
- /*
- * allocate the memory and walk the list again to fill in the pointers
- */
- modulearray = xnfalloc((count + 1) * sizeof(char*));
- count = 0;
- idp = xf86ConfigLayout.inputs;
- while (idp && *idp) {
- modulearray[count] = (*idp)->driver;
- count++;
- idp++;
- }
- modulearray[count] = NULL;
-
- /* Remove duplicates */
- for (count = 0; modulearray[count] != NULL; count++) {
- int i;
-
- for (i = 0; i < count; i++)
- if (xf86NameCmp(modulearray[i], modulearray[count]) == 0) {
- modulearray[count] = "";
- break;
- }
- }
- return modulearray;
-}
-
-static void
-fixup_video_driver_list(char **drivers)
-{
- static const char *fallback[4] = { "vesa", "fbdev", "wsfb", NULL };
- char **end, **drv;
- char *x;
- int i;
-
- /* walk to the end of the list */
- for (end = drivers; *end && **end; end++) ;
- end--;
-
- /*
- * for each of the fallback drivers, if we find it in the list,
- * swap it with the last available non-fallback driver.
- */
- for (i = 0; fallback[i]; i++) {
- for (drv = drivers; drv != end; drv++) {
- if (strstr(*drv, fallback[i])) {
- x = *drv; *drv = *end; *end = x;
- end--;
- break;
- }
- }
- }
-}
-
-static char **
-GenerateDriverlist(char * dirname)
-{
- char **ret;
- const char *subdirs[] = { dirname, NULL };
- static const char *patlist[] = {"(.*)_drv\\.so", NULL};
- ret = LoaderListDirs(subdirs, patlist);
-
- /* fix up the probe order for video drivers */
- if (strstr(dirname, "drivers") && ret != NULL)
- fixup_video_driver_list(ret);
-
- return ret;
-}
-
-char **
-xf86DriverlistFromCompile(void)
-{
- static char **driverlist = NULL;
-
- if (!driverlist)
- driverlist = GenerateDriverlist("drivers");
-
- return driverlist;
-}
-
-/*
- * xf86ConfigError --
- * Print a READABLE ErrorMessage!!! All information that is
- * available is printed.
- */
-static void
-xf86ConfigError(char *msg, ...)
-{
- va_list ap;
-
- ErrorF("\nConfig Error:\n");
- va_start(ap, msg);
- VErrorF(msg, ap);
- va_end(ap);
- ErrorF("\n");
- return;
-}
-
-static void
-configFiles(XF86ConfFilesPtr fileconf)
-{
- MessageType pathFrom;
- Bool must_copy;
- int size, countDirs;
- char *temp_path, *log_buf, *start, *end;
-
- /* FontPath */
- must_copy = TRUE;
-
- temp_path = defaultFontPath ? defaultFontPath : "";
- if (xf86fpFlag)
- pathFrom = X_CMDLINE;
- else if (fileconf && fileconf->file_fontpath) {
- pathFrom = X_CONFIG;
- if (xf86Info.useDefaultFontPath) {
- if (asprintf(&defaultFontPath, "%s%s%s", fileconf->file_fontpath,
- *temp_path ? "," : "", temp_path) == -1)
- defaultFontPath = NULL;
- else
- must_copy = FALSE;
- }
- else
- defaultFontPath = fileconf->file_fontpath;
- }
- else
- pathFrom = X_DEFAULT;
- temp_path = defaultFontPath ? defaultFontPath : "";
-
- /* xf86ValidateFontPath modifies its argument, but returns a copy of it. */
- temp_path = must_copy ? xnfstrdup(defaultFontPath) : defaultFontPath;
- defaultFontPath = xf86ValidateFontPath(temp_path);
- free(temp_path);
-
- /* make fontpath more readable in the logfiles */
- countDirs = 1;
- temp_path = defaultFontPath;
- while ((temp_path = index(temp_path, ',')) != NULL) {
- countDirs++;
- temp_path++;
- }
-
- log_buf = xnfalloc(strlen(defaultFontPath) + (2 * countDirs) + 1);
- temp_path = log_buf;
- start = defaultFontPath;
- while((end = index(start, ',')) != NULL) {
- size = (end - start) + 1;
- *(temp_path++) = '\t';
- strncpy(temp_path, start, size);
- temp_path += size;
- *(temp_path++) = '\n';
- start += size;
- }
- /* copy last entry */
- *(temp_path++) = '\t';
- strcpy(temp_path, start);
- xf86Msg(pathFrom, "FontPath set to:\n%s\n", log_buf);
- free(log_buf);
-
- /* ModulePath */
-
- if (fileconf) {
- if (xf86ModPathFrom != X_CMDLINE && fileconf->file_modulepath) {
- xf86ModulePath = fileconf->file_modulepath;
- xf86ModPathFrom = X_CONFIG;
- }
- }
-
- xf86Msg(xf86ModPathFrom, "ModulePath set to \"%s\"\n", xf86ModulePath);
-
- if (!xf86xkbdirFlag && fileconf && fileconf->file_xkbdir) {
- XkbBaseDirectory = fileconf->file_xkbdir;
- xf86Msg(X_CONFIG, "XKB base directory set to \"%s\"\n",
- XkbBaseDirectory);
- }
-#if 0
- /* LogFile */
- /*
- * XXX The problem with this is that the log file is already open.
- * One option might be to copy the exiting contents to the new location.
- * and re-open it. The down side is that the default location would
- * already have been overwritten. Another option would be to start with
- * unique temporary location, then copy it once the correct name is known.
- * A problem with this is what happens if the server exits before that
- * happens.
- */
- if (xf86LogFileFrom == X_DEFAULT && fileconf->file_logfile) {
- xf86LogFile = fileconf->file_logfile;
- xf86LogFileFrom = X_CONFIG;
- }
-#endif
-
- return;
-}
-
-typedef enum {
- FLAG_NOTRAPSIGNALS,
- FLAG_DONTVTSWITCH,
- FLAG_DONTZAP,
- FLAG_DONTZOOM,
- FLAG_DISABLEVIDMODE,
- FLAG_ALLOWNONLOCAL,
- FLAG_ALLOWMOUSEOPENFAIL,
- FLAG_VTSYSREQ,
- FLAG_SAVER_BLANKTIME,
- FLAG_DPMS_STANDBYTIME,
- FLAG_DPMS_SUSPENDTIME,
- FLAG_DPMS_OFFTIME,
- FLAG_PIXMAP,
- FLAG_PC98,
- FLAG_NOPM,
- FLAG_XINERAMA,
- FLAG_LOG,
- FLAG_RENDER_COLORMAP_MODE,
- FLAG_RANDR,
- FLAG_AIGLX,
- FLAG_IGNORE_ABI,
- FLAG_ALLOW_EMPTY_INPUT,
- FLAG_USE_DEFAULT_FONT_PATH,
- FLAG_AUTO_ADD_DEVICES,
- FLAG_AUTO_ENABLE_DEVICES,
- FLAG_GLX_VISUALS,
- FLAG_DRI2,
- FLAG_USE_SIGIO
-} FlagValues;
-
-/**
- * NOTE: the last value for each entry is NOT the default. It is set to TRUE
- * if the parser found the option in the config file.
- */
-static OptionInfoRec FlagOptions[] = {
- { FLAG_NOTRAPSIGNALS, "NoTrapSignals", OPTV_BOOLEAN,
- {0}, FALSE },
- { FLAG_DONTVTSWITCH, "DontVTSwitch", OPTV_BOOLEAN,
- {0}, FALSE },
- { FLAG_DONTZAP, "DontZap", OPTV_BOOLEAN,
- {0}, FALSE },
- { FLAG_DONTZOOM, "DontZoom", OPTV_BOOLEAN,
- {0}, FALSE },
- { FLAG_DISABLEVIDMODE, "DisableVidModeExtension", OPTV_BOOLEAN,
- {0}, FALSE },
- { FLAG_ALLOWNONLOCAL, "AllowNonLocalXvidtune", OPTV_BOOLEAN,
- {0}, FALSE },
- { FLAG_ALLOWMOUSEOPENFAIL, "AllowMouseOpenFail", OPTV_BOOLEAN,
- {0}, FALSE },
- { FLAG_VTSYSREQ, "VTSysReq", OPTV_BOOLEAN,
- {0}, FALSE },
- { FLAG_SAVER_BLANKTIME, "BlankTime" , OPTV_INTEGER,
- {0}, FALSE },
- { FLAG_DPMS_STANDBYTIME, "StandbyTime", OPTV_INTEGER,
- {0}, FALSE },
- { FLAG_DPMS_SUSPENDTIME, "SuspendTime", OPTV_INTEGER,
- {0}, FALSE },
- { FLAG_DPMS_OFFTIME, "OffTime", OPTV_INTEGER,
- {0}, FALSE },
- { FLAG_PIXMAP, "Pixmap", OPTV_INTEGER,
- {0}, FALSE },
- { FLAG_PC98, "PC98", OPTV_BOOLEAN,
- {0}, FALSE },
- { FLAG_NOPM, "NoPM", OPTV_BOOLEAN,
- {0}, FALSE },
- { FLAG_XINERAMA, "Xinerama", OPTV_BOOLEAN,
- {0}, FALSE },
- { FLAG_LOG, "Log", OPTV_STRING,
- {0}, FALSE },
- { FLAG_RENDER_COLORMAP_MODE, "RenderColormapMode", OPTV_STRING,
- {0}, FALSE },
- { FLAG_RANDR, "RandR", OPTV_BOOLEAN,
- {0}, FALSE },
- { FLAG_AIGLX, "AIGLX", OPTV_BOOLEAN,
- {0}, FALSE },
- { FLAG_IGNORE_ABI, "IgnoreABI", OPTV_BOOLEAN,
- {0}, FALSE },
- { FLAG_USE_DEFAULT_FONT_PATH, "UseDefaultFontPath", OPTV_BOOLEAN,
- {0}, FALSE },
- { FLAG_AUTO_ADD_DEVICES, "AutoAddDevices", OPTV_BOOLEAN,
- {0}, FALSE },
- { FLAG_AUTO_ENABLE_DEVICES, "AutoEnableDevices", OPTV_BOOLEAN,
- {0}, FALSE },
- { FLAG_GLX_VISUALS, "GlxVisuals", OPTV_STRING,
- {0}, FALSE },
- { FLAG_DRI2, "DRI2", OPTV_BOOLEAN,
- {0}, FALSE },
- { FLAG_USE_SIGIO, "UseSIGIO", OPTV_BOOLEAN,
- {0}, FALSE },
- { -1, NULL, OPTV_NONE,
- {0}, FALSE },
-};
-
-#ifdef SUPPORT_PC98
-static Bool
-detectPC98(void)
-{
- unsigned char buf[2];
-
- if (xf86ReadBIOS(0xf8000, 0xe80, buf, 2) != 2)
- return FALSE;
- if ((buf[0] == 0x98) && (buf[1] == 0x21))
- return TRUE;
- else
- return FALSE;
-}
-#endif
-
-static Bool
-configServerFlags(XF86ConfFlagsPtr flagsconf, XF86OptionPtr layoutopts)
-{
- XF86OptionPtr optp, tmp;
- int i;
- Pix24Flags pix24 = Pix24DontCare;
- Bool value;
- MessageType from;
- const char *s;
- XkbRMLVOSet set;
- /* Default options. */
- set.rules = "base";
- set.model = "pc105";
- set.layout = "us";
- set.variant = NULL;
- set.options = NULL;
-
- /*
- * Merge the ServerLayout and ServerFlags options. The former have
- * precedence over the latter.
- */
- optp = NULL;
- if (flagsconf && flagsconf->flg_option_lst)
- optp = xf86optionListDup(flagsconf->flg_option_lst);
- if (layoutopts) {
- tmp = xf86optionListDup(layoutopts);
- if (optp)
- optp = xf86optionListMerge(optp, tmp);
- else
- optp = tmp;
- }
-
- xf86ProcessOptions(-1, optp, FlagOptions);
-
- xf86GetOptValBool(FlagOptions, FLAG_NOTRAPSIGNALS, &xf86Info.notrapSignals);
- xf86GetOptValBool(FlagOptions, FLAG_DONTVTSWITCH, &xf86Info.dontVTSwitch);
- xf86GetOptValBool(FlagOptions, FLAG_DONTZAP, &xf86Info.dontZap);
- xf86GetOptValBool(FlagOptions, FLAG_DONTZOOM, &xf86Info.dontZoom);
-
- xf86GetOptValBool(FlagOptions, FLAG_IGNORE_ABI, &xf86Info.ignoreABI);
- if (xf86Info.ignoreABI) {
- xf86Msg(X_CONFIG, "Ignoring ABI Version\n");
- }
-
- if (xf86SIGIOSupported()) {
- xf86Info.useSIGIO = xf86ReturnOptValBool(FlagOptions, FLAG_USE_SIGIO, USE_SIGIO_BY_DEFAULT);
- if (xf86IsOptionSet(FlagOptions, FLAG_USE_SIGIO)) {
- from = X_CONFIG;
- } else {
- from = X_DEFAULT;
- }
- if (!xf86Info.useSIGIO) {
- xf86Msg(from, "Disabling SIGIO handlers for input devices\n");
- } else if (from == X_CONFIG) {
- xf86Msg(from, "Enabling SIGIO handlers for input devices\n");
- }
- } else {
- xf86Info.useSIGIO = FALSE;
- }
-
- if (xf86IsOptionSet(FlagOptions, FLAG_AUTO_ADD_DEVICES)) {
- xf86GetOptValBool(FlagOptions, FLAG_AUTO_ADD_DEVICES,
- &xf86Info.autoAddDevices);
- from = X_CONFIG;
- }
- else {
- from = X_DEFAULT;
- }
- xf86Msg(from, "%sutomatically adding devices\n",
- xf86Info.autoAddDevices ? "A" : "Not a");
-
- if (xf86IsOptionSet(FlagOptions, FLAG_AUTO_ENABLE_DEVICES)) {
- xf86GetOptValBool(FlagOptions, FLAG_AUTO_ENABLE_DEVICES,
- &xf86Info.autoEnableDevices);
- from = X_CONFIG;
- }
- else {
- from = X_DEFAULT;
- }
- xf86Msg(from, "%sutomatically enabling devices\n",
- xf86Info.autoEnableDevices ? "A" : "Not a");
-
- /*
- * Set things up based on the config file information. Some of these
- * settings may be overridden later when the command line options are
- * checked.
- */
-#ifdef XF86VIDMODE
- if (xf86GetOptValBool(FlagOptions, FLAG_DISABLEVIDMODE, &value))
- xf86Info.vidModeEnabled = !value;
- if (xf86GetOptValBool(FlagOptions, FLAG_ALLOWNONLOCAL, &value))
- xf86Info.vidModeAllowNonLocal = value;
-#endif
-
- if (xf86GetOptValBool(FlagOptions, FLAG_ALLOWMOUSEOPENFAIL, &value))
- xf86Info.allowMouseOpenFail = value;
-
- if (xf86GetOptValBool(FlagOptions, FLAG_VTSYSREQ, &value)) {
-#ifdef USE_VT_SYSREQ
- xf86Info.vtSysreq = value;
- xf86Msg(X_CONFIG, "VTSysReq %s\n", value ? "enabled" : "disabled");
-#else
- if (value)
- xf86Msg(X_WARNING, "VTSysReq is not supported on this OS\n");
-#endif
- }
-
- xf86Info.pmFlag = TRUE;
- if (xf86GetOptValBool(FlagOptions, FLAG_NOPM, &value))
- xf86Info.pmFlag = !value;
- {
- if ((s = xf86GetOptValString(FlagOptions, FLAG_LOG))) {
- if (!xf86NameCmp(s,"flush")) {
- xf86Msg(X_CONFIG, "Flushing logfile enabled\n");
- xf86Info.log = LogFlush;
- LogSetParameter(XLOG_FLUSH, TRUE);
- } else if (!xf86NameCmp(s,"sync")) {
- xf86Msg(X_CONFIG, "Syncing logfile enabled\n");
- xf86Info.log = LogSync;
- LogSetParameter(XLOG_FLUSH, TRUE);
- LogSetParameter(XLOG_SYNC, TRUE);
- } else {
- xf86Msg(X_WARNING,"Unknown Log option\n");
- }
- }
- }
-
- {
- if ((s = xf86GetOptValString(FlagOptions, FLAG_RENDER_COLORMAP_MODE))){
- int policy = PictureParseCmapPolicy (s);
- if (policy == PictureCmapPolicyInvalid)
- xf86Msg(X_WARNING, "Unknown colormap policy \"%s\"\n", s);
- else
- {
- xf86Msg(X_CONFIG, "Render colormap policy set to %s\n", s);
- PictureCmapPolicy = policy;
- }
- }
- }
-
-#ifdef RANDR
- xf86Info.disableRandR = FALSE;
- xf86Info.randRFrom = X_DEFAULT;
- if (xf86GetOptValBool(FlagOptions, FLAG_RANDR, &value)) {
- xf86Info.disableRandR = !value;
- xf86Info.randRFrom = X_CONFIG;
- }
-#endif
-
- xf86Info.aiglx = TRUE;
- xf86Info.aiglxFrom = X_DEFAULT;
- if (xf86GetOptValBool(FlagOptions, FLAG_AIGLX, &value)) {
- xf86Info.aiglx = value;
- xf86Info.aiglxFrom = X_CONFIG;
- }
-
-#ifdef GLXEXT
- xf86Info.glxVisuals = XF86_GlxVisualsTypical;
- xf86Info.glxVisualsFrom = X_DEFAULT;
- if ((s = xf86GetOptValString(FlagOptions, FLAG_GLX_VISUALS))) {
- if (!xf86NameCmp(s, "minimal")) {
- xf86Info.glxVisuals = XF86_GlxVisualsMinimal;
- } else if (!xf86NameCmp(s, "typical")) {
- xf86Info.glxVisuals = XF86_GlxVisualsTypical;
- } else if (!xf86NameCmp(s, "all")) {
- xf86Info.glxVisuals = XF86_GlxVisualsAll;
- } else {
- xf86Msg(X_WARNING,"Unknown GlxVisuals option\n");
- }
- }
-
- if (xf86GetOptValBool(FlagOptions, FLAG_AIGLX, &value)) {
- xf86Info.aiglx = value;
- xf86Info.aiglxFrom = X_CONFIG;
- }
-#endif
-
- /* if we're not hotplugging, force some input devices to exist */
- xf86Info.forceInputDevices = !(xf86Info.autoAddDevices && xf86Info.autoEnableDevices);
-
- /* when forcing input devices, we use kbd. otherwise evdev, so use the
- * evdev rules set. */
-#if defined(linux)
- if (!xf86Info.forceInputDevices)
- set.rules = "evdev";
-#endif
- XkbSetRulesDflts(&set);
-
- xf86Info.useDefaultFontPath = TRUE;
- xf86Info.useDefaultFontPathFrom = X_DEFAULT;
- if (xf86GetOptValBool(FlagOptions, FLAG_USE_DEFAULT_FONT_PATH, &value)) {
- xf86Info.useDefaultFontPath = value;
- xf86Info.useDefaultFontPathFrom = X_CONFIG;
- }
-
-/* Make sure that timers don't overflow CARD32's after multiplying */
-#define MAX_TIME_IN_MIN (0x7fffffff / MILLI_PER_MIN)
-
- i = -1;
- xf86GetOptValInteger(FlagOptions, FLAG_SAVER_BLANKTIME, &i);
- if ((i >= 0) && (i < MAX_TIME_IN_MIN))
- ScreenSaverTime = defaultScreenSaverTime = i * MILLI_PER_MIN;
- else if (i != -1)
- xf86ConfigError("BlankTime value %d outside legal range of 0 - %d minutes",
- i, MAX_TIME_IN_MIN);
-
-#ifdef DPMSExtension
- i = -1;
- xf86GetOptValInteger(FlagOptions, FLAG_DPMS_STANDBYTIME, &i);
- if ((i >= 0) && (i < MAX_TIME_IN_MIN))
- DPMSStandbyTime = i * MILLI_PER_MIN;
- else if (i != -1)
- xf86ConfigError("StandbyTime value %d outside legal range of 0 - %d minutes",
- i, MAX_TIME_IN_MIN);
- i = -1;
- xf86GetOptValInteger(FlagOptions, FLAG_DPMS_SUSPENDTIME, &i);
- if ((i >= 0) && (i < MAX_TIME_IN_MIN))
- DPMSSuspendTime = i * MILLI_PER_MIN;
- else if (i != -1)
- xf86ConfigError("SuspendTime value %d outside legal range of 0 - %d minutes",
- i, MAX_TIME_IN_MIN);
- i = -1;
- xf86GetOptValInteger(FlagOptions, FLAG_DPMS_OFFTIME, &i);
- if ((i >= 0) && (i < MAX_TIME_IN_MIN))
- DPMSOffTime = i * MILLI_PER_MIN;
- else if (i != -1)
- xf86ConfigError("OffTime value %d outside legal range of 0 - %d minutes",
- i, MAX_TIME_IN_MIN);
-#endif
-
- i = -1;
- xf86GetOptValInteger(FlagOptions, FLAG_PIXMAP, &i);
- switch (i) {
- case 24:
- pix24 = Pix24Use24;
- break;
- case 32:
- pix24 = Pix24Use32;
- break;
- case -1:
- break;
- default:
- xf86ConfigError("Pixmap option's value (%d) must be 24 or 32\n", i);
- return FALSE;
- }
- if (xf86Pix24 != Pix24DontCare) {
- xf86Info.pixmap24 = xf86Pix24;
- xf86Info.pix24From = X_CMDLINE;
- } else if (pix24 != Pix24DontCare) {
- xf86Info.pixmap24 = pix24;
- xf86Info.pix24From = X_CONFIG;
- } else {
- xf86Info.pixmap24 = Pix24DontCare;
- xf86Info.pix24From = X_DEFAULT;
- }
-#ifdef SUPPORT_PC98
- if (xf86GetOptValBool(FlagOptions, FLAG_PC98, &value)) {
- xf86Info.pc98 = value;
- if (value) {
- xf86Msg(X_CONFIG, "Japanese PC98 architecture\n");
- }
- } else
- if (detectPC98()) {
- xf86Info.pc98 = TRUE;
- xf86Msg(X_PROBED, "Japanese PC98 architecture\n");
- }
-#endif
-
-#ifdef PANORAMIX
- from = X_DEFAULT;
- if (!noPanoramiXExtension)
- from = X_CMDLINE;
- else if (xf86GetOptValBool(FlagOptions, FLAG_XINERAMA, &value)) {
- noPanoramiXExtension = !value;
- from = X_CONFIG;
- }
- if (!noPanoramiXExtension)
- xf86Msg(from, "Xinerama: enabled\n");
-#endif
-
-#ifdef DRI2
- xf86Info.dri2 = FALSE;
- xf86Info.dri2From = X_DEFAULT;
- if (xf86GetOptValBool(FlagOptions, FLAG_DRI2, &value)) {
- xf86Info.dri2 = value;
- xf86Info.dri2From = X_CONFIG;
- }
-#endif
-
- return TRUE;
-}
-
-Bool xf86DRI2Enabled(void)
-{
- return xf86Info.dri2;
-}
-
-/*
- * Locate the core input devices. These can be specified/located in
- * the following ways, in order of priority:
- *
- * 1. The InputDevices named by the -pointer and -keyboard command line
- * options.
- * 2. The "CorePointer" and "CoreKeyboard" InputDevices referred to by
- * the active ServerLayout.
- * 3. The first InputDevices marked as "CorePointer" and "CoreKeyboard".
- * 4. The first InputDevices that use 'keyboard' or 'kbd' and a valid mouse
- * driver (mouse, synaptics, evdev, vmmouse, void)
- * 5. Default devices with an empty (default) configuration. These defaults
- * will reference the 'mouse' and 'keyboard' drivers.
- */
-
-static Bool
-checkCoreInputDevices(serverLayoutPtr servlayoutp, Bool implicitLayout)
-{
- InputInfoPtr corePointer = NULL, coreKeyboard = NULL;
- Bool foundPointer = FALSE, foundKeyboard = FALSE;
- const char *pointerMsg = NULL, *keyboardMsg = NULL;
- InputInfoPtr *devs, /* iterator */
- indp;
- InputInfoRec Pointer = {}, Keyboard = {};
- XF86ConfInputPtr confInput;
- XF86ConfInputRec defPtr, defKbd;
- int count = 0;
- MessageType from = X_DEFAULT;
- int found = 0;
- const char *mousedrivers[] = { "mouse", "synaptics", "evdev", "vmmouse",
- "void", NULL };
-
- /*
- * First check if a core pointer or core keyboard have been specified
- * in the active ServerLayout. If more than one is specified for either,
- * remove the core attribute from the later ones.
- */
- for (devs = servlayoutp->inputs; devs && *devs; devs++) {
- indp = *devs;
- if (indp->options &&
- xf86CheckBoolOption(indp->options, "CorePointer", FALSE)) {
- if (!corePointer) {
- corePointer = indp;
- } else {
- xf86ReplaceBoolOption(indp->options, "CorePointer", FALSE);
- xf86Msg(X_WARNING, "Duplicate core pointer devices. "
- "Removing core pointer attribute from \"%s\"\n",
- indp->name);
- }
- }
- if (indp->options &&
- xf86CheckBoolOption(indp->options, "CoreKeyboard", FALSE)) {
- if (!coreKeyboard) {
- coreKeyboard = indp;
- } else {
- xf86ReplaceBoolOption(indp->options, "CoreKeyboard", FALSE);
- xf86Msg(X_WARNING, "Duplicate core keyboard devices. "
- "Removing core keyboard attribute from \"%s\"\n",
- indp->name);
- }
- }
- count++;
- }
-
- confInput = NULL;
-
- /* 1. Check for the -pointer command line option. */
- if (xf86PointerName) {
- confInput = xf86findInput(xf86PointerName,
- xf86configptr->conf_input_lst);
- if (!confInput) {
- xf86Msg(X_ERROR, "No InputDevice section called \"%s\"\n",
- xf86PointerName);
- return FALSE;
- }
- from = X_CMDLINE;
- /*
- * If one was already specified in the ServerLayout, it needs to be
- * removed.
- */
- if (corePointer) {
- for (devs = servlayoutp->inputs; devs && *devs; devs++)
- if (*devs == corePointer)
- {
- free(*devs);
- *devs = (InputInfoPtr)0x1; /* ensure we dont skip next loop*/
- break;
- }
- for (; devs && *devs; devs++)
- devs[0] = devs[1];
- count--;
- }
- corePointer = NULL;
- foundPointer = TRUE;
- }
-
- /* 2. ServerLayout-specified core pointer. */
- if (corePointer) {
- foundPointer = TRUE;
- from = X_CONFIG;
- }
-
- /* 3. First core pointer device. */
- if (!foundPointer && (xf86Info.forceInputDevices || implicitLayout)) {
- XF86ConfInputPtr p;
-
- for (p = xf86configptr->conf_input_lst; p; p = p->list.next) {
- if (p->inp_option_lst &&
- xf86CheckBoolOption(p->inp_option_lst, "CorePointer", FALSE)) {
- confInput = p;
- foundPointer = TRUE;
- from = X_DEFAULT;
- pointerMsg = "first core pointer device";
- break;
- }
- }
- }
-
- /* 4. First pointer with an allowed mouse driver. */
- if (!foundPointer && xf86Info.forceInputDevices) {
- const char **driver = mousedrivers;
- confInput = xf86findInput(CONF_IMPLICIT_POINTER,
- xf86configptr->conf_input_lst);
- while (*driver && !confInput) {
- confInput = xf86findInputByDriver(*driver,
- xf86configptr->conf_input_lst);
- driver++;
- }
- if (confInput) {
- foundPointer = TRUE;
- from = X_DEFAULT;
- pointerMsg = "first mouse device";
- }
- }
-
- /* 5. Built-in default. */
- if (!foundPointer && xf86Info.forceInputDevices) {
- memset(&defPtr, 0, sizeof(defPtr));
- defPtr.inp_identifier = strdup("<default pointer>");
- defPtr.inp_driver = strdup("mouse");
- confInput = &defPtr;
- foundPointer = TRUE;
- from = X_DEFAULT;
- pointerMsg = "default mouse configuration";
- }
-
- /* Add the core pointer device to the layout, and set it to Core. */
- if (foundPointer && confInput) {
- foundPointer = configInput(&Pointer, confInput, from);
- if (foundPointer) {
- count++;
- devs = xnfrealloc(servlayoutp->inputs,
- (count + 1) * sizeof(InputInfoPtr));
- devs[count - 1] = xnfalloc(sizeof(InputInfoRec));
- *devs[count - 1] = Pointer;
- devs[count - 1]->options =
- xf86addNewOption(NULL, xnfstrdup("CorePointer"), NULL);
- devs[count] = NULL;
- servlayoutp->inputs = devs;
- }
- }
-
- if (!foundPointer && xf86Info.forceInputDevices) {
- /* This shouldn't happen. */
- xf86Msg(X_ERROR, "Cannot locate a core pointer device.\n");
- return FALSE;
- }
-
- /*
- * always synthesize a 'mouse' section configured to send core
- * events, unless a 'void' section is found, in which case the user
- * probably wants to run footless.
- *
- * If you're using an evdev keyboard and expect a default mouse
- * section ... deal.
- */
- for (devs = servlayoutp->inputs; devs && *devs; devs++) {
- const char **driver = mousedrivers;
- while(*driver) {
- if (!strcmp((*devs)->driver, *driver)) {
- found = 1;
- break;
- }
- driver++;
- }
- }
- if (!found && xf86Info.forceInputDevices) {
- xf86Msg(X_INFO, "No default mouse found, adding one\n");
- memset(&defPtr, 0, sizeof(defPtr));
- defPtr.inp_identifier = strdup("<default pointer>");
- defPtr.inp_driver = strdup("mouse");
- confInput = &defPtr;
- foundPointer = configInput(&Pointer, confInput, from);
- if (foundPointer) {
- count++;
- devs = xnfrealloc(servlayoutp->inputs,
- (count + 1) * sizeof(InputInfoPtr));
- devs[count - 1] = xnfalloc(sizeof(InputInfoRec));
- *devs[count - 1] = Pointer;
- devs[count - 1]->options =
- xf86addNewOption(NULL, xnfstrdup("AlwaysCore"), NULL);
- devs[count] = NULL;
- servlayoutp->inputs = devs;
- }
- }
-
- confInput = NULL;
-
- /* 1. Check for the -keyboard command line option. */
- if (xf86KeyboardName) {
- confInput = xf86findInput(xf86KeyboardName,
- xf86configptr->conf_input_lst);
- if (!confInput) {
- xf86Msg(X_ERROR, "No InputDevice section called \"%s\"\n",
- xf86KeyboardName);
- return FALSE;
- }
- from = X_CMDLINE;
- /*
- * If one was already specified in the ServerLayout, it needs to be
- * removed.
- */
- if (coreKeyboard) {
- for (devs = servlayoutp->inputs; devs && *devs; devs++)
- if (*devs == coreKeyboard)
- {
- free(*devs);
- *devs = (InputInfoPtr)0x1; /* ensure we dont skip next loop */
- break;
- }
- for (; devs && *devs; devs++)
- devs[0] = devs[1];
- count--;
- }
- coreKeyboard = NULL;
- foundKeyboard = TRUE;
- }
-
- /* 2. ServerLayout-specified core keyboard. */
- if (coreKeyboard) {
- foundKeyboard = TRUE;
- from = X_CONFIG;
- }
-
- /* 3. First core keyboard device. */
- if (!foundKeyboard && (xf86Info.forceInputDevices || implicitLayout)) {
- XF86ConfInputPtr p;
-
- for (p = xf86configptr->conf_input_lst; p; p = p->list.next) {
- if (p->inp_option_lst &&
- xf86CheckBoolOption(p->inp_option_lst, "CoreKeyboard", FALSE)) {
- confInput = p;
- foundKeyboard = TRUE;
- from = X_DEFAULT;
- keyboardMsg = "first core keyboard device";
- break;
- }
- }
- }
-
- /* 4. First keyboard with 'keyboard' or 'kbd' as the driver. */
- if (!foundKeyboard && xf86Info.forceInputDevices) {
- confInput = xf86findInput(CONF_IMPLICIT_KEYBOARD,
- xf86configptr->conf_input_lst);
- if (!confInput) {
- confInput = xf86findInputByDriver("kbd",
- xf86configptr->conf_input_lst);
- }
- if (confInput) {
- foundKeyboard = TRUE;
- from = X_DEFAULT;
- keyboardMsg = "first keyboard device";
- }
- }
-
- /* 5. Built-in default. */
- if (!foundKeyboard && xf86Info.forceInputDevices) {
- memset(&defKbd, 0, sizeof(defKbd));
- defKbd.inp_identifier = strdup("<default keyboard>");
- defKbd.inp_driver = strdup("kbd");
- confInput = &defKbd;
- foundKeyboard = TRUE;
- keyboardMsg = "default keyboard configuration";
- from = X_DEFAULT;
- }
-
- /* Add the core keyboard device to the layout, and set it to Core. */
- if (foundKeyboard && confInput) {
- foundKeyboard = configInput(&Keyboard, confInput, from);
- if (foundKeyboard) {
- count++;
- devs = xnfrealloc(servlayoutp->inputs,
- (count + 1) * sizeof(InputInfoPtr));
- devs[count - 1] = xnfalloc(sizeof(InputInfoRec));
- *devs[count - 1] = Keyboard;
- devs[count - 1]->options =
- xf86addNewOption(NULL, xnfstrdup("CoreKeyboard"), NULL);
- devs[count] = NULL;
- servlayoutp->inputs = devs;
- }
- }
-
- if (!foundKeyboard && xf86Info.forceInputDevices) {
- /* This shouldn't happen. */
- xf86Msg(X_ERROR, "Cannot locate a core keyboard device.\n");
- return FALSE;
- }
-
- if (pointerMsg) {
- if (implicitLayout)
- xf86Msg(X_DEFAULT, "No Layout section. Using the %s.\n",
- pointerMsg);
- else
- xf86Msg(X_DEFAULT, "The core pointer device wasn't specified "
- "explicitly in the layout.\n"
- "\tUsing the %s.\n", pointerMsg);
- }
-
- if (keyboardMsg) {
- if (implicitLayout)
- xf86Msg(X_DEFAULT, "No Layout section. Using the %s.\n",
- keyboardMsg);
- else
- xf86Msg(X_DEFAULT, "The core keyboard device wasn't specified "
- "explicitly in the layout.\n"
- "\tUsing the %s.\n", keyboardMsg);
- }
-
- if (!xf86Info.forceInputDevices && !(foundPointer && foundKeyboard)) {
-#if defined(CONFIG_HAL) || defined(CONFIG_UDEV)
- const char *config_backend;
-#if defined(CONFIG_HAL)
- config_backend = "HAL";
-#else
- config_backend = "udev";
-#endif
- xf86Msg(X_INFO, "The server relies on %s to provide the list of "
- "input devices.\n\tIf no devices become available, "
- "reconfigure %s or disable AutoAddDevices.\n",
- config_backend, config_backend);
-#else
- xf86Msg(X_WARNING, "Hotplugging requested but the server was "
- "compiled without a config backend. "
- "No input devices were configured, the server "
- "will start without any input devices.\n");
-#endif
- }
-
- return TRUE;
-}
-
-typedef enum {
- LAYOUT_ISOLATEDEVICE,
- LAYOUT_SINGLECARD
-} LayoutValues;
-
-static OptionInfoRec LayoutOptions[] = {
- { LAYOUT_ISOLATEDEVICE, "IsolateDevice", OPTV_STRING,
- {0}, FALSE },
- { LAYOUT_SINGLECARD, "SingleCard", OPTV_BOOLEAN,
- {0}, FALSE },
- { -1, NULL, OPTV_NONE,
- {0}, FALSE },
-};
-
-static Bool
-configInputDevices(XF86ConfLayoutPtr layout, serverLayoutPtr servlayoutp)
-{
- XF86ConfInputrefPtr irp;
- InputInfoPtr *indp;
- int count = 0;
-
- /*
- * Count the number of input devices.
- */
- irp = layout->lay_input_lst;
- while (irp) {
- count++;
- irp = (XF86ConfInputrefPtr)irp->list.next;
- }
- DebugF("Found %d input devices in the layout section %s\n",
- count, layout->lay_identifier);
- indp = xnfcalloc((count + 1), sizeof(InputInfoPtr));
- indp[count] = NULL;
- irp = layout->lay_input_lst;
- count = 0;
- while (irp) {
- indp[count] = xf86AllocateInput();
- if (!configInput(indp[count], irp->iref_inputdev, X_CONFIG)) {
- while(count--)
- free(indp[count]);
- free(indp);
- return FALSE;
- }
- indp[count]->options = xf86OptionListMerge(indp[count]->options,
- irp->iref_option_lst);
- count++;
- irp = (XF86ConfInputrefPtr)irp->list.next;
- }
- servlayoutp->inputs = indp;
-
- return TRUE;
-}
-
-
-/*
- * figure out which layout is active, which screens are used in that layout,
- * which drivers and monitors are used in these screens
- */
-static Bool
-configLayout(serverLayoutPtr servlayoutp, XF86ConfLayoutPtr conf_layout,
- char *default_layout)
-{
- XF86ConfAdjacencyPtr adjp;
- XF86ConfInactivePtr idp;
- int count = 0;
- int scrnum;
- XF86ConfLayoutPtr l;
- MessageType from;
- screenLayoutPtr slp;
- GDevPtr gdp;
- int i = 0, j;
-
- if (!servlayoutp)
- return FALSE;
-
- /*
- * which layout section is the active one?
- *
- * If there is a -layout command line option, use that one, otherwise
- * pick the first one.
- */
- from = X_DEFAULT;
- if (xf86LayoutName != NULL)
- from = X_CMDLINE;
- else if (default_layout) {
- xf86LayoutName = default_layout;
- from = X_CONFIG;
- }
- if (xf86LayoutName != NULL) {
- if ((l = xf86findLayout(xf86LayoutName, conf_layout)) == NULL) {
- xf86Msg(X_ERROR, "No ServerLayout section called \"%s\"\n",
- xf86LayoutName);
- return FALSE;
- }
- conf_layout = l;
- }
- xf86Msg(from, "ServerLayout \"%s\"\n", conf_layout->lay_identifier);
- adjp = conf_layout->lay_adjacency_lst;
-
- /*
- * we know that each screen is referenced exactly once on the left side
- * of a layout statement in the Layout section. So to allocate the right
- * size for the array we do a quick walk of the list to figure out how
- * many sections we have
- */
- while (adjp) {
- count++;
- adjp = (XF86ConfAdjacencyPtr)adjp->list.next;
- }
-
- DebugF("Found %d screens in the layout section %s",
- count, conf_layout->lay_identifier);
- if (!count) /* alloc enough storage even if no screen is specified */
- count = 1;
-
- slp = xnfcalloc(1, (count + 1) * sizeof(screenLayoutRec));
- slp[count].screen = NULL;
- /*
- * now that we have storage, loop over the list again and fill in our
- * data structure; at this point we do not fill in the adjacency
- * information as it is not clear if we need it at all
- */
- adjp = conf_layout->lay_adjacency_lst;
- count = 0;
- while (adjp) {
- slp[count].screen = xnfcalloc(1, sizeof(confScreenRec));
- if (adjp->adj_scrnum < 0)
- scrnum = count;
- else
- scrnum = adjp->adj_scrnum;
- if (!configScreen(slp[count].screen, adjp->adj_screen, scrnum,
- X_CONFIG)) {
- free(slp);
- return FALSE;
- }
- slp[count].x = adjp->adj_x;
- slp[count].y = adjp->adj_y;
- slp[count].refname = adjp->adj_refscreen;
- switch (adjp->adj_where) {
- case CONF_ADJ_OBSOLETE:
- slp[count].where = PosObsolete;
- slp[count].topname = adjp->adj_top_str;
- slp[count].bottomname = adjp->adj_bottom_str;
- slp[count].leftname = adjp->adj_left_str;
- slp[count].rightname = adjp->adj_right_str;
- break;
- case CONF_ADJ_ABSOLUTE:
- slp[count].where = PosAbsolute;
- break;
- case CONF_ADJ_RIGHTOF:
- slp[count].where = PosRightOf;
- break;
- case CONF_ADJ_LEFTOF:
- slp[count].where = PosLeftOf;
- break;
- case CONF_ADJ_ABOVE:
- slp[count].where = PosAbove;
- break;
- case CONF_ADJ_BELOW:
- slp[count].where = PosBelow;
- break;
- case CONF_ADJ_RELATIVE:
- slp[count].where = PosRelative;
- break;
- }
- count++;
- adjp = (XF86ConfAdjacencyPtr)adjp->list.next;
- }
-
- /* No screen was specified in the layout. take the first one from the
- * config file, or - if it is NULL - configScreen autogenerates one for
- * us */
- if (!count)
- {
- slp[0].screen = xnfcalloc(1, sizeof(confScreenRec));
- if (!configScreen(slp[0].screen, xf86configptr->conf_screen_lst,
- 0, X_CONFIG)) {
- free(slp[0].screen);
- free(slp);
- return FALSE;
- }
- }
-
- /* XXX Need to tie down the upper left screen. */
-
- /* Fill in the refscreen and top/bottom/left/right values */
- for (i = 0; i < count; i++) {
- for (j = 0; j < count; j++) {
- if (slp[i].refname &&
- strcmp(slp[i].refname, slp[j].screen->id) == 0) {
- slp[i].refscreen = slp[j].screen;
- }
- if (slp[i].topname &&
- strcmp(slp[i].topname, slp[j].screen->id) == 0) {
- slp[i].top = slp[j].screen;
- }
- if (slp[i].bottomname &&
- strcmp(slp[i].bottomname, slp[j].screen->id) == 0) {
- slp[i].bottom = slp[j].screen;
- }
- if (slp[i].leftname &&
- strcmp(slp[i].leftname, slp[j].screen->id) == 0) {
- slp[i].left = slp[j].screen;
- }
- if (slp[i].rightname &&
- strcmp(slp[i].rightname, slp[j].screen->id) == 0) {
- slp[i].right = slp[j].screen;
- }
- }
- if (slp[i].where != PosObsolete
- && slp[i].where != PosAbsolute
- && !slp[i].refscreen) {
- xf86Msg(X_ERROR,"Screen %s doesn't exist: deleting placement\n",
- slp[i].refname);
- slp[i].where = PosAbsolute;
- slp[i].x = 0;
- slp[i].y = 0;
- }
- }
-
- /*
- * Count the number of inactive devices.
- */
- count = 0;
- idp = conf_layout->lay_inactive_lst;
- while (idp) {
- count++;
- idp = (XF86ConfInactivePtr)idp->list.next;
- }
- DebugF("Found %d inactive devices in the layout section %s\n",
- count, conf_layout->lay_identifier);
- gdp = xnfalloc((count + 1) * sizeof(GDevRec));
- gdp[count].identifier = NULL;
- idp = conf_layout->lay_inactive_lst;
- count = 0;
- while (idp) {
- if (!configDevice(&gdp[count], idp->inactive_device, FALSE)) {
- free(gdp);
- return FALSE;
- }
- count++;
- idp = (XF86ConfInactivePtr)idp->list.next;
- }
-
- if (!configInputDevices(conf_layout, servlayoutp))
- return FALSE;
-
- servlayoutp->id = conf_layout->lay_identifier;
- servlayoutp->screens = slp;
- servlayoutp->inactives = gdp;
- servlayoutp->options = conf_layout->lay_option_lst;
- from = X_DEFAULT;
-
- return TRUE;
-}
-
-/*
- * No layout section, so find the first Screen section and set that up as
- * the only active screen.
- */
-static Bool
-configImpliedLayout(serverLayoutPtr servlayoutp, XF86ConfScreenPtr conf_screen,
- XF86ConfigPtr xf86configptr)
-{
- MessageType from;
- XF86ConfScreenPtr s;
- screenLayoutPtr slp;
- InputInfoPtr *indp;
- XF86ConfLayoutRec layout;
-
- if (!servlayoutp)
- return FALSE;
-
- /*
- * which screen section is the active one?
- *
- * If there is a -screen option, use that one, otherwise use the first
- * one.
- */
-
- from = X_CONFIG;
- if (xf86ScreenName != NULL) {
- if ((s = xf86findScreen(xf86ScreenName, conf_screen)) == NULL) {
- xf86Msg(X_ERROR, "No Screen section called \"%s\"\n",
- xf86ScreenName);
- return FALSE;
- }
- conf_screen = s;
- from = X_CMDLINE;
- }
-
- /* We have exactly one screen */
-
- slp = xnfcalloc(1, 2 * sizeof(screenLayoutRec));
- slp[0].screen = xnfcalloc(1, sizeof(confScreenRec));
- slp[1].screen = NULL;
- if (!configScreen(slp[0].screen, conf_screen, 0, from)) {
- free(slp);
- return FALSE;
- }
- servlayoutp->id = "(implicit)";
- servlayoutp->screens = slp;
- servlayoutp->inactives = xnfcalloc(1, sizeof(GDevRec));
- servlayoutp->options = NULL;
-
- memset(&layout, 0, sizeof(layout));
- layout.lay_identifier = servlayoutp->id;
- if (xf86layoutAddInputDevices(xf86configptr, &layout) > 0) {
- if (!configInputDevices(&layout, servlayoutp))
- return FALSE;
- from = X_DEFAULT;
- } else {
- /* Set up an empty input device list, then look for some core devices. */
- indp = xnfalloc(sizeof(InputInfoPtr));
- *indp = NULL;
- servlayoutp->inputs = indp;
- }
-
- return TRUE;
-}
-
-static Bool
-configXvAdaptor(confXvAdaptorPtr adaptor, XF86ConfVideoAdaptorPtr conf_adaptor)
-{
- int count = 0;
- XF86ConfVideoPortPtr conf_port;
-
- xf86Msg(X_CONFIG, "| |-->VideoAdaptor \"%s\"\n",
- conf_adaptor->va_identifier);
- adaptor->identifier = conf_adaptor->va_identifier;
- adaptor->options = conf_adaptor->va_option_lst;
- if (conf_adaptor->va_busid || conf_adaptor->va_driver) {
- xf86Msg(X_CONFIG, "| | Unsupported device type, skipping entry\n");
- return FALSE;
- }
-
- /*
- * figure out how many videoport subsections there are and fill them in
- */
- conf_port = conf_adaptor->va_port_lst;
- while(conf_port) {
- count++;
- conf_port = (XF86ConfVideoPortPtr)conf_port->list.next;
- }
- adaptor->ports = xnfalloc((count) * sizeof(confXvPortRec));
- adaptor->numports = count;
- count = 0;
- conf_port = conf_adaptor->va_port_lst;
- while(conf_port) {
- adaptor->ports[count].identifier = conf_port->vp_identifier;
- adaptor->ports[count].options = conf_port->vp_option_lst;
- count++;
- conf_port = (XF86ConfVideoPortPtr)conf_port->list.next;
- }
-
- return TRUE;
-}
-
-static Bool
-configScreen(confScreenPtr screenp, XF86ConfScreenPtr conf_screen, int scrnum,
- MessageType from)
-{
- int count = 0;
- XF86ConfDisplayPtr dispptr;
- XF86ConfAdaptorLinkPtr conf_adaptor;
- Bool defaultMonitor = FALSE;
-
- if (!conf_screen) {
- conf_screen = xnfcalloc(1, sizeof(XF86ConfScreenRec));
- conf_screen->scrn_identifier = "Default Screen Section";
- xf86Msg(X_DEFAULT, "No screen section available. Using defaults.\n");
- }
-
- xf86Msg(from, "|-->Screen \"%s\" (%d)\n", conf_screen->scrn_identifier,
- scrnum);
- /*
- * now we fill in the elements of the screen
- */
- screenp->id = conf_screen->scrn_identifier;
- screenp->screennum = scrnum;
- screenp->defaultdepth = conf_screen->scrn_defaultdepth;
- screenp->defaultbpp = conf_screen->scrn_defaultbpp;
- screenp->defaultfbbpp = conf_screen->scrn_defaultfbbpp;
- screenp->monitor = xnfcalloc(1, sizeof(MonRec));
- /* If no monitor is specified, create a default one. */
- if (!conf_screen->scrn_monitor) {
- XF86ConfMonitorRec defMon;
-
- memset(&defMon, 0, sizeof(defMon));
- defMon.mon_identifier = "<default monitor>";
- if (!configMonitor(screenp->monitor, &defMon))
- return FALSE;
- defaultMonitor = TRUE;
- } else {
- if (!configMonitor(screenp->monitor,conf_screen->scrn_monitor))
- return FALSE;
- }
- /* Configure the device. If there isn't one configured, attach to the
- * first inactive one that we can configure. If there's none that work,
- * set it to NULL so that the section can be autoconfigured later */
- screenp->device = xnfcalloc(1, sizeof(GDevRec));
- if ((!conf_screen->scrn_device) && (xf86configptr->conf_device_lst)) {
- conf_screen->scrn_device = xf86configptr->conf_device_lst;
- xf86Msg(X_DEFAULT, "No device specified for screen \"%s\".\n"
- "\tUsing the first device section listed.\n", screenp->id);
- }
- if (configDevice(screenp->device,conf_screen->scrn_device, TRUE)) {
- screenp->device->myScreenSection = screenp;
- } else {
- screenp->device = NULL;
- }
- screenp->options = conf_screen->scrn_option_lst;
-
- /*
- * figure out how many display subsections there are and fill them in
- */
- dispptr = conf_screen->scrn_display_lst;
- while(dispptr) {
- count++;
- dispptr = (XF86ConfDisplayPtr)dispptr->list.next;
- }
- screenp->displays = xnfalloc((count) * sizeof(DispRec));
- screenp->numdisplays = count;
-
- /* Fill in the default Virtual size, if any */
- if (conf_screen->scrn_virtualX && conf_screen->scrn_virtualY) {
- for (count = 0, dispptr = conf_screen->scrn_display_lst;
- dispptr;
- dispptr = (XF86ConfDisplayPtr)dispptr->list.next, count++) {
- screenp->displays[count].virtualX = conf_screen->scrn_virtualX;
- screenp->displays[count].virtualY = conf_screen->scrn_virtualY;
- }
- }
-
- /* Now do the per-Display Virtual sizes */
- count = 0;
- dispptr = conf_screen->scrn_display_lst;
- while(dispptr) {
- configDisplay(&(screenp->displays[count]),dispptr);
- count++;
- dispptr = (XF86ConfDisplayPtr)dispptr->list.next;
- }
-
- /*
- * figure out how many videoadaptor references there are and fill them in
- */
- conf_adaptor = conf_screen->scrn_adaptor_lst;
- while(conf_adaptor) {
- count++;
- conf_adaptor = (XF86ConfAdaptorLinkPtr)conf_adaptor->list.next;
- }
- screenp->xvadaptors = xnfalloc((count) * sizeof(confXvAdaptorRec));
- screenp->numxvadaptors = 0;
- conf_adaptor = conf_screen->scrn_adaptor_lst;
- while(conf_adaptor) {
- if (configXvAdaptor(&(screenp->xvadaptors[screenp->numxvadaptors]),
- conf_adaptor->al_adaptor))
- screenp->numxvadaptors++;
- conf_adaptor = (XF86ConfAdaptorLinkPtr)conf_adaptor->list.next;
- }
-
- if (defaultMonitor) {
- xf86Msg(X_DEFAULT, "No monitor specified for screen \"%s\".\n"
- "\tUsing a default monitor configuration.\n", screenp->id);
- }
- return TRUE;
-}
-
-typedef enum {
- MON_REDUCEDBLANKING,
- MON_MAX_PIX_CLOCK,
-} MonitorValues;
-
-static OptionInfoRec MonitorOptions[] = {
- { MON_REDUCEDBLANKING, "ReducedBlanking", OPTV_BOOLEAN,
- {0}, FALSE },
- { MON_MAX_PIX_CLOCK, "MaxPixClock", OPTV_FREQ,
- {0}, FALSE },
- { -1, NULL, OPTV_NONE,
- {0}, FALSE },
-};
-
-static Bool
-configMonitor(MonPtr monitorp, XF86ConfMonitorPtr conf_monitor)
-{
- int count;
- DisplayModePtr mode,last = NULL;
- XF86ConfModeLinePtr cmodep;
- XF86ConfModesPtr modes;
- XF86ConfModesLinkPtr modeslnk = conf_monitor->mon_modes_sect_lst;
- Gamma zeros = {0.0, 0.0, 0.0};
- float badgamma = 0.0;
- double maxPixClock;
-
- xf86Msg(X_CONFIG, "| |-->Monitor \"%s\"\n",
- conf_monitor->mon_identifier);
- monitorp->id = conf_monitor->mon_identifier;
- monitorp->vendor = conf_monitor->mon_vendor;
- monitorp->model = conf_monitor->mon_modelname;
- monitorp->Modes = NULL;
- monitorp->Last = NULL;
- monitorp->gamma = zeros;
- monitorp->widthmm = conf_monitor->mon_width;
- monitorp->heightmm = conf_monitor->mon_height;
- monitorp->reducedblanking = FALSE;
- monitorp->maxPixClock = 0;
- monitorp->options = conf_monitor->mon_option_lst;
-
- /*
- * fill in the monitor structure
- */
- for( count = 0 ;
- count < conf_monitor->mon_n_hsync && count < MAX_HSYNC;
- count++) {
- monitorp->hsync[count].hi = conf_monitor->mon_hsync[count].hi;
- monitorp->hsync[count].lo = conf_monitor->mon_hsync[count].lo;
- }
- monitorp->nHsync = count;
- for( count = 0 ;
- count < conf_monitor->mon_n_vrefresh && count < MAX_VREFRESH;
- count++) {
- monitorp->vrefresh[count].hi = conf_monitor->mon_vrefresh[count].hi;
- monitorp->vrefresh[count].lo = conf_monitor->mon_vrefresh[count].lo;
- }
- monitorp->nVrefresh = count;
-
- /*
- * first we collect the mode lines from the UseModes directive
- */
- while(modeslnk)
- {
- modes = xf86findModes (modeslnk->ml_modes_str,
- xf86configptr->conf_modes_lst);
- modeslnk->ml_modes = modes;
-
-
- /* now add the modes found in the modes
- section to the list of modes for this
- monitor unless it has been added before
- because we are reusing the same section
- for another screen */
- if (xf86itemNotSublist(
- (GenericListPtr)conf_monitor->mon_modeline_lst,
- (GenericListPtr)modes->mon_modeline_lst)) {
- conf_monitor->mon_modeline_lst = (XF86ConfModeLinePtr)
- xf86addListItem(
- (GenericListPtr)conf_monitor->mon_modeline_lst,
- (GenericListPtr)modes->mon_modeline_lst);
- }
- modeslnk = modeslnk->list.next;
- }
-
- /*
- * we need to hook in the mode lines now
- * here both data structures use lists, only our internal one
- * is double linked
- */
- cmodep = conf_monitor->mon_modeline_lst;
- while( cmodep ) {
- mode = xnfcalloc(1, sizeof(DisplayModeRec));
- mode->type = 0;
- mode->Clock = cmodep->ml_clock;
- mode->HDisplay = cmodep->ml_hdisplay;
- mode->HSyncStart = cmodep->ml_hsyncstart;
- mode->HSyncEnd = cmodep->ml_hsyncend;
- mode->HTotal = cmodep->ml_htotal;
- mode->VDisplay = cmodep->ml_vdisplay;
- mode->VSyncStart = cmodep->ml_vsyncstart;
- mode->VSyncEnd = cmodep->ml_vsyncend;
- mode->VTotal = cmodep->ml_vtotal;
- mode->Flags = cmodep->ml_flags;
- mode->HSkew = cmodep->ml_hskew;
- mode->VScan = cmodep->ml_vscan;
- mode->name = xnfstrdup(cmodep->ml_identifier);
- if( last ) {
- mode->prev = last;
- last->next = mode;
- }
- else {
- /*
- * this is the first mode
- */
- monitorp->Modes = mode;
- mode->prev = NULL;
- }
- last = mode;
- cmodep = (XF86ConfModeLinePtr)cmodep->list.next;
- }
- if(last){
- last->next = NULL;
- }
- monitorp->Last = last;
-
- /* add the (VESA) default modes */
- if (! addDefaultModes(monitorp) )
- return FALSE;
-
- if (conf_monitor->mon_gamma_red > GAMMA_ZERO)
- monitorp->gamma.red = conf_monitor->mon_gamma_red;
- if (conf_monitor->mon_gamma_green > GAMMA_ZERO)
- monitorp->gamma.green = conf_monitor->mon_gamma_green;
- if (conf_monitor->mon_gamma_blue > GAMMA_ZERO)
- monitorp->gamma.blue = conf_monitor->mon_gamma_blue;
-
- /* Check that the gamma values are within range */
- if (monitorp->gamma.red > GAMMA_ZERO &&
- (monitorp->gamma.red < GAMMA_MIN ||
- monitorp->gamma.red > GAMMA_MAX)) {
- badgamma = monitorp->gamma.red;
- } else if (monitorp->gamma.green > GAMMA_ZERO &&
- (monitorp->gamma.green < GAMMA_MIN ||
- monitorp->gamma.green > GAMMA_MAX)) {
- badgamma = monitorp->gamma.green;
- } else if (monitorp->gamma.blue > GAMMA_ZERO &&
- (monitorp->gamma.blue < GAMMA_MIN ||
- monitorp->gamma.blue > GAMMA_MAX)) {
- badgamma = monitorp->gamma.blue;
- }
- if (badgamma > GAMMA_ZERO) {
- xf86ConfigError("Gamma value %.f is out of range (%.2f - %.1f)\n",
- badgamma, GAMMA_MIN, GAMMA_MAX);
- return FALSE;
- }
-
- xf86ProcessOptions(-1, monitorp->options, MonitorOptions);
- xf86GetOptValBool(MonitorOptions, MON_REDUCEDBLANKING,
- &monitorp->reducedblanking);
- if (xf86GetOptValFreq(MonitorOptions, MON_MAX_PIX_CLOCK, OPTUNITS_KHZ,
- &maxPixClock) == TRUE) {
- monitorp->maxPixClock = (int) maxPixClock;
- }
-
- return TRUE;
-}
-
-static int
-lookupVisual(const char *visname)
-{
- int i;
-
- if (!visname || !*visname)
- return -1;
-
- for (i = 0; i <= DirectColor; i++) {
- if (!xf86nameCompare(visname, xf86VisualNames[i]))
- break;
- }
-
- if (i <= DirectColor)
- return i;
-
- return -1;
-}
-
-
-static Bool
-configDisplay(DispPtr displayp, XF86ConfDisplayPtr conf_display)
-{
- int count = 0;
- XF86ModePtr modep;
-
- displayp->frameX0 = conf_display->disp_frameX0;
- displayp->frameY0 = conf_display->disp_frameY0;
- displayp->virtualX = conf_display->disp_virtualX;
- displayp->virtualY = conf_display->disp_virtualY;
- displayp->depth = conf_display->disp_depth;
- displayp->fbbpp = conf_display->disp_bpp;
- displayp->weight.red = conf_display->disp_weight.red;
- displayp->weight.green = conf_display->disp_weight.green;
- displayp->weight.blue = conf_display->disp_weight.blue;
- displayp->blackColour.red = conf_display->disp_black.red;
- displayp->blackColour.green = conf_display->disp_black.green;
- displayp->blackColour.blue = conf_display->disp_black.blue;
- displayp->whiteColour.red = conf_display->disp_white.red;
- displayp->whiteColour.green = conf_display->disp_white.green;
- displayp->whiteColour.blue = conf_display->disp_white.blue;
- displayp->options = conf_display->disp_option_lst;
- if (conf_display->disp_visual) {
- displayp->defaultVisual = lookupVisual(conf_display->disp_visual);
- if (displayp->defaultVisual == -1) {
- xf86ConfigError("Invalid visual name: \"%s\"",
- conf_display->disp_visual);
- return FALSE;
- }
- } else {
- displayp->defaultVisual = -1;
- }
-
- /*
- * now hook in the modes
- */
- modep = conf_display->disp_mode_lst;
- while(modep) {
- count++;
- modep = (XF86ModePtr)modep->list.next;
- }
- displayp->modes = xnfalloc((count+1) * sizeof(char*));
- modep = conf_display->disp_mode_lst;
- count = 0;
- while(modep) {
- displayp->modes[count] = modep->mode_name;
- count++;
- modep = (XF86ModePtr)modep->list.next;
- }
- displayp->modes[count] = NULL;
-
- return TRUE;
-}
-
-static Bool
-configDevice(GDevPtr devicep, XF86ConfDevicePtr conf_device, Bool active)
-{
- int i;
-
- if (!conf_device) {
- return FALSE;
- }
-
- if (active)
- xf86Msg(X_CONFIG, "| |-->Device \"%s\"\n",
- conf_device->dev_identifier);
- else
- xf86Msg(X_CONFIG, "|-->Inactive Device \"%s\"\n",
- conf_device->dev_identifier);
-
- devicep->identifier = conf_device->dev_identifier;
- devicep->vendor = conf_device->dev_vendor;
- devicep->board = conf_device->dev_board;
- devicep->chipset = conf_device->dev_chipset;
- devicep->ramdac = conf_device->dev_ramdac;
- devicep->driver = conf_device->dev_driver;
- devicep->active = active;
- devicep->videoRam = conf_device->dev_videoram;
- devicep->BiosBase = conf_device->dev_bios_base;
- devicep->MemBase = conf_device->dev_mem_base;
- devicep->IOBase = conf_device->dev_io_base;
- devicep->clockchip = conf_device->dev_clockchip;
- devicep->busID = conf_device->dev_busid;
- devicep->textClockFreq = conf_device->dev_textclockfreq;
- devicep->chipID = conf_device->dev_chipid;
- devicep->chipRev = conf_device->dev_chiprev;
- devicep->options = conf_device->dev_option_lst;
- devicep->irq = conf_device->dev_irq;
- devicep->screen = conf_device->dev_screen;
-
- for (i = 0; i < MAXDACSPEEDS; i++) {
- if (i < CONF_MAXDACSPEEDS)
- devicep->dacSpeeds[i] = conf_device->dev_dacSpeeds[i];
- else
- devicep->dacSpeeds[i] = 0;
- }
- devicep->numclocks = conf_device->dev_clocks;
- if (devicep->numclocks > MAXCLOCKS)
- devicep->numclocks = MAXCLOCKS;
- for (i = 0; i < devicep->numclocks; i++) {
- devicep->clock[i] = conf_device->dev_clock[i];
- }
- devicep->claimed = FALSE;
-
- return TRUE;
-}
-
-#ifdef XF86DRI
-static void
-configDRI(XF86ConfDRIPtr drip)
-{
- struct group *grp;
-
- xf86ConfigDRI.group = -1;
- xf86ConfigDRI.mode = 0;
-
- if (drip) {
- if (drip->dri_group_name) {
- if ((grp = getgrnam(drip->dri_group_name)))
- xf86ConfigDRI.group = grp->gr_gid;
- } else {
- if (drip->dri_group >= 0)
- xf86ConfigDRI.group = drip->dri_group;
- }
- xf86ConfigDRI.mode = drip->dri_mode;
- }
-}
-#endif
-
-static void
-configExtensions(XF86ConfExtensionsPtr conf_ext)
-{
- XF86OptionPtr o;
-
- if (conf_ext && conf_ext->ext_option_lst) {
- for (o = conf_ext->ext_option_lst; o; o = xf86NextOption(o)) {
- char *name = xf86OptionName(o);
- char *val = xf86OptionValue(o);
- char *n;
- Bool enable = TRUE;
-
- /* Handle "No<ExtensionName>" */
- n = xf86NormalizeName(name);
- if (strncmp(n, "no", 2) == 0) {
- name += 2;
- enable = FALSE;
- }
-
- if (!val ||
- xf86NameCmp(val, "enable") == 0 ||
- xf86NameCmp(val, "enabled") == 0 ||
- xf86NameCmp(val, "on") == 0 ||
- xf86NameCmp(val, "1") == 0 ||
- xf86NameCmp(val, "yes") == 0 ||
- xf86NameCmp(val, "true") == 0) {
- /* NOTHING NEEDED -- enabling is handled below */
- } else if (xf86NameCmp(val, "disable") == 0 ||
- xf86NameCmp(val, "disabled") == 0 ||
- xf86NameCmp(val, "off") == 0 ||
- xf86NameCmp(val, "0") == 0 ||
- xf86NameCmp(val, "no") == 0 ||
- xf86NameCmp(val, "false") == 0) {
- enable = !enable;
- } else {
- xf86Msg(X_WARNING, "Ignoring unrecognized value \"%s\"\n", val);
- free(n);
- continue;
- }
-
- if (EnableDisableExtension(name, enable)) {
- xf86Msg(X_CONFIG, "Extension \"%s\" is %s\n",
- name, enable ? "enabled" : "disabled");
- } else {
- xf86Msg(X_WARNING, "Ignoring unrecognized extension \"%s\"\n",
- name);
- }
- free(n);
- }
- }
-}
-
-static Bool
-configInput(InputInfoPtr inputp, XF86ConfInputPtr conf_input, MessageType from)
-{
- xf86Msg(from, "|-->Input Device \"%s\"\n", conf_input->inp_identifier);
- inputp->name = conf_input->inp_identifier;
- inputp->driver = conf_input->inp_driver;
- inputp->options = conf_input->inp_option_lst;
- inputp->attrs = NULL;
-
- return TRUE;
-}
-
-static Bool
-modeIsPresent(DisplayModePtr mode, MonPtr monitorp)
-{
- DisplayModePtr knownmodes = monitorp->Modes;
-
- /* all I can think of is a linear search... */
- while(knownmodes != NULL)
- {
- if(!strcmp(mode->name, knownmodes->name) &&
- !(knownmodes->type & M_T_DEFAULT))
- return TRUE;
- knownmodes = knownmodes->next;
- }
- return FALSE;
-}
-
-static Bool
-addDefaultModes(MonPtr monitorp)
-{
- DisplayModePtr mode;
- DisplayModePtr last = monitorp->Last;
- int i = 0;
-
- for (i = 0; i < xf86NumDefaultModes; i++)
- {
- mode = xf86DuplicateMode(&xf86DefaultModes[i]);
- if (!modeIsPresent(mode, monitorp))
- {
- monitorp->Modes = xf86ModesAdd(monitorp->Modes, mode);
- last = mode;
- } else {
- free(mode);
- }
- }
- monitorp->Last = last;
-
- return TRUE;
-}
-
-static void
-checkInput(serverLayoutPtr layout, Bool implicit_layout) {
- checkCoreInputDevices(layout, implicit_layout);
-
- /* Unless we're forcing input devices, disable mouse/kbd devices in the
- * config. Otherwise the same physical device is added multiple times,
- * leading to duplicate events.
- */
- if (!xf86Info.forceInputDevices && layout->inputs)
- {
- InputInfoPtr *dev = layout->inputs;
- BOOL warned = FALSE;
-
- while(*dev)
- {
- if (strcmp((*dev)->driver, "kbd") == 0 ||
- strcmp((*dev)->driver, "mouse") == 0 ||
- strcmp((*dev)->driver, "vmmouse") == 0)
- {
- InputInfoPtr *current;
- if (!warned)
- {
- xf86Msg(X_WARNING, "Hotplugging is on, devices using "
- "drivers 'kbd', 'mouse' or 'vmmouse' will be disabled.\n");
- warned = TRUE;
- }
-
- xf86Msg(X_WARNING, "Disabling %s\n", (*dev)->name);
-
- current = dev;
- free(*dev);
-
- do {
- *current = *(current + 1);
- current++;
- } while(*current);
- } else
- dev++;
- }
- }
-}
-
-/*
- * load the config file and fill the global data structure
- */
-ConfigStatus
-xf86HandleConfigFile(Bool autoconfig)
-{
- const char *filename, *dirname, *sysdirname;
- char *filesearch, *dirsearch;
- MessageType filefrom = X_DEFAULT;
- MessageType dirfrom = X_DEFAULT;
- char *scanptr;
- Bool singlecard = 0;
- Bool implicit_layout = FALSE;
-
- if (!autoconfig) {
- if (getuid() == 0) {
- filesearch = ROOT_CONFIGPATH;
- dirsearch = ROOT_CONFIGDIRPATH;
- } else {
- filesearch = USER_CONFIGPATH;
- dirsearch = USER_CONFIGDIRPATH;
- }
-
- if (xf86ConfigFile)
- filefrom = X_CMDLINE;
- if (xf86ConfigDir)
- dirfrom = X_CMDLINE;
-
- xf86initConfigFiles();
- sysdirname = xf86openConfigDirFiles(SYS_CONFIGDIRPATH, NULL,
- PROJECTROOT);
- dirname = xf86openConfigDirFiles(dirsearch, xf86ConfigDir, PROJECTROOT);
- filename = xf86openConfigFile(filesearch, xf86ConfigFile, PROJECTROOT);
- if (filename) {
- xf86MsgVerb(filefrom, 0, "Using config file: \"%s\"\n", filename);
- xf86ConfigFile = xnfstrdup(filename);
- } else {
- if (xf86ConfigFile)
- xf86Msg(X_ERROR, "Unable to locate/open config file: \"%s\"\n",
- xf86ConfigFile);
- }
- if (dirname) {
- xf86MsgVerb(dirfrom, 0, "Using config directory: \"%s\"\n",
- dirname);
- xf86ConfigDir = xnfstrdup(dirname);
- } else {
- if (xf86ConfigDir)
- xf86Msg(X_ERROR,
- "Unable to locate/open config directory: \"%s\"\n",
- xf86ConfigDir);
- }
- if (sysdirname)
- xf86MsgVerb(X_DEFAULT, 0, "Using system config directory \"%s\"\n",
- sysdirname);
- if (!filename && !dirname && !sysdirname)
- return CONFIG_NOFILE;
- }
-
- if ((xf86configptr = xf86readConfigFile ()) == NULL) {
- xf86Msg(X_ERROR, "Problem parsing the config file\n");
- return CONFIG_PARSE_ERROR;
- }
- xf86closeConfigFile ();
-
- /* Initialise a few things. */
-
- /*
- * now we convert part of the information contained in the parser
- * structures into our own structures.
- * The important part here is to figure out which Screen Sections
- * in the XF86Config file are active so that we can piece together
- * the modes that we need later down the road.
- * And while we are at it, we'll decode the rest of the stuff as well
- */
-
- /* First check if a layout section is present, and if it is valid. */
-
- if (xf86configptr->conf_layout_lst == NULL || xf86ScreenName != NULL) {
- if (xf86ScreenName == NULL) {
- xf86Msg(X_DEFAULT,
- "No Layout section. Using the first Screen section.\n");
- }
- if (!configImpliedLayout(&xf86ConfigLayout,
- xf86configptr->conf_screen_lst,
- xf86configptr)) {
- xf86Msg(X_ERROR, "Unable to determine the screen layout\n");
- return CONFIG_PARSE_ERROR;
- }
- implicit_layout = TRUE;
- } else {
- if (xf86configptr->conf_flags != NULL) {
- char *dfltlayout = NULL;
- pointer optlist = xf86configptr->conf_flags->flg_option_lst;
-
- if (optlist && xf86FindOption(optlist, "defaultserverlayout"))
- dfltlayout = xf86SetStrOption(optlist, "defaultserverlayout", NULL);
- if (!configLayout(&xf86ConfigLayout, xf86configptr->conf_layout_lst,
- dfltlayout)) {
- xf86Msg(X_ERROR, "Unable to determine the screen layout\n");
- return CONFIG_PARSE_ERROR;
- }
- } else {
- if (!configLayout(&xf86ConfigLayout, xf86configptr->conf_layout_lst,
- NULL)) {
- xf86Msg(X_ERROR, "Unable to determine the screen layout\n");
- return CONFIG_PARSE_ERROR;
- }
- }
- }
-
- xf86ProcessOptions(-1, xf86ConfigLayout.options, LayoutOptions);
-
- if ((scanptr = xf86GetOptValString(LayoutOptions, LAYOUT_ISOLATEDEVICE))) {
- ; /* IsolateDevice specified; overrides SingleCard */
- } else {
- xf86GetOptValBool(LayoutOptions, LAYOUT_SINGLECARD, &singlecard);
- if (singlecard)
- scanptr = xf86ConfigLayout.screens->screen->device->busID;
- }
- if (scanptr) {
- if (strncmp(scanptr, "PCI:", 4) != 0) {
- xf86Msg(X_WARNING, "Bus types other than PCI not yet isolable.\n"
- "\tIgnoring IsolateDevice option.\n");
- } else
- xf86PciIsolateDevice(scanptr);
- }
-
- /* Now process everything else */
- if (!configServerFlags(xf86configptr->conf_flags,xf86ConfigLayout.options)){
- ErrorF ("Problem when converting the config data structures\n");
- return CONFIG_PARSE_ERROR;
- }
-
- configFiles(xf86configptr->conf_files);
- configExtensions(xf86configptr->conf_extensions);
-#ifdef XF86DRI
- configDRI(xf86configptr->conf_dri);
-#endif
-
- checkInput(&xf86ConfigLayout, implicit_layout);
-
- /*
- * Handle some command line options that can override some of the
- * ServerFlags settings.
- */
-#ifdef XF86VIDMODE
- if (xf86VidModeDisabled)
- xf86Info.vidModeEnabled = FALSE;
- if (xf86VidModeAllowNonLocal)
- xf86Info.vidModeAllowNonLocal = TRUE;
-#endif
-
- if (xf86AllowMouseOpenFail)
- xf86Info.allowMouseOpenFail = TRUE;
-
- return CONFIG_OK;
-}
-
-Bool
-xf86PathIsSafe(const char *path)
-{
- return (xf86pathIsSafe(path) != 0);
-}
+/* + * Loosely based on code bearing the following copyright: + * + * Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany. + */ + +/* + * Copyright 1992-2003 by The XFree86 Project, Inc. + * Copyright 1997 by Metro Link, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the copyright holder(s) + * and author(s) shall not be used in advertising or otherwise to promote + * the sale, use or other dealings in this Software without prior written + * authorization from the copyright holder(s) and author(s). + */ + +/* + * + * Authors: + * Dirk Hohndel <hohndel@XFree86.Org> + * David Dawes <dawes@XFree86.Org> + * Marc La France <tsi@XFree86.Org> + * Egbert Eich <eich@XFree86.Org> + * ... and others + */ + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#ifdef XF86DRI +#include <sys/types.h> +#include <grp.h> +#endif + +#include "xf86.h" +#include "xf86Parser.h" +#include "xf86tokens.h" +#include "xf86Config.h" +#include "xf86Priv.h" +#include "xf86_OSlib.h" +#include "configProcs.h" +#include "globals.h" +#include "extension.h" +#include "xf86pciBus.h" + +#include "xf86Xinput.h" + +#include "xkbsrv.h" + +#include "picture.h" + +/* + * These paths define the way the config file search is done. The escape + * sequences are documented in parser/scan.c. + */ +#ifndef ROOT_CONFIGPATH +#define ROOT_CONFIGPATH "%A," "%R," \ + "/etc/X11/%R," "%P/etc/X11/%R," \ + "%E," "%F," \ + "/etc/X11/%F," "%P/etc/X11/%F," \ + "/etc/X11/%X," "/etc/%X," \ + "%P/etc/X11/%X.%H," \ + "%P/etc/X11/%X," \ + "%P/lib/X11/%X.%H," \ + "%P/lib/X11/%X" +#endif +#ifndef USER_CONFIGPATH +#define USER_CONFIGPATH "/etc/X11/%S," "%P/etc/X11/%S," \ + "/etc/X11/%G," "%P/etc/X11/%G," \ + "/etc/X11/%X," "/etc/%X," \ + "%P/etc/X11/%X.%H," \ + "%P/etc/X11/%X," \ + "%P/lib/X11/%X.%H," \ + "%P/lib/X11/%X" +#endif +#ifndef ROOT_CONFIGDIRPATH +#define ROOT_CONFIGDIRPATH "%A," "%R," \ + "/etc/X11/%R," "%C/X11/%R," \ + "/etc/X11/%X," "%C/X11/%X" +#endif +#ifndef USER_CONFIGDIRPATH +#define USER_CONFIGDIRPATH "/etc/X11/%R," "%C/X11/%R," \ + "/etc/X11/%X," "%C/X11/%X" +#endif +#ifndef SYS_CONFIGDIRPATH +#define SYS_CONFIGDIRPATH "/usr/share/X11/%X," "%D/X11/%X" +#endif +#ifndef PROJECTROOT +#define PROJECTROOT "/usr/X11R6" +#endif + +static ModuleDefault ModuleDefaults[] = { + {.name = "extmod", .toLoad = TRUE, .load_opt=NULL}, +#ifdef DBE + {.name = "dbe", .toLoad = TRUE, .load_opt=NULL}, +#endif +#ifdef GLXEXT + {.name = "glx", .toLoad = TRUE, .load_opt=NULL}, +#endif +#ifdef XRECORD + {.name = "record", .toLoad = TRUE, .load_opt=NULL}, +#endif +#ifdef XF86DRI + {.name = "dri", .toLoad = TRUE, .load_opt=NULL}, +#endif +#ifdef DRI2 + {.name = "dri2", .toLoad = TRUE, .load_opt=NULL}, +#endif + {.name = NULL, .toLoad = FALSE, .load_opt=NULL} +}; + + +/* Forward declarations */ +static Bool configScreen(confScreenPtr screenp, XF86ConfScreenPtr conf_screen, + int scrnum, MessageType from); +static Bool configMonitor(MonPtr monitorp, XF86ConfMonitorPtr conf_monitor); +static Bool configDevice(GDevPtr devicep, XF86ConfDevicePtr conf_device, + Bool active); +static Bool configInput(InputInfoPtr pInfo, XF86ConfInputPtr conf_input, + MessageType from); +static Bool configDisplay(DispPtr displayp, XF86ConfDisplayPtr conf_display); +static Bool addDefaultModes(MonPtr monitorp); +#ifdef XF86DRI +static void configDRI(XF86ConfDRIPtr drip); +#endif +static void configExtensions(XF86ConfExtensionsPtr conf_ext); + +/* + * xf86GetPathElem -- + * Extract a single element from the font path string starting at + * pnt. The font path element will be returned, and pnt will be + * updated to point to the start of the next element, or set to + * NULL if there are no more. + */ +static char * +xf86GetPathElem(char **pnt) +{ + char *p1; + + p1 = *pnt; + *pnt = index(*pnt, ','); + if (*pnt != NULL) { + **pnt = '\0'; + *pnt += 1; + } + return p1; +} + +/* + * xf86ValidateFontPath -- + * Validates the user-specified font path. Each element that + * begins with a '/' is checked to make sure the directory exists. + * If the directory exists, the existence of a file named 'fonts.dir' + * is checked. If either check fails, an error is printed and the + * element is removed from the font path. + */ + +#define DIR_FILE "/fonts.dir" +static char * +xf86ValidateFontPath(char *path) +{ + char *tmp_path, *out_pnt, *path_elem, *next, *p1, *dir_elem; + struct stat stat_buf; + int flag; + int dirlen; + + tmp_path = calloc(1,strlen(path)+1); + out_pnt = tmp_path; + path_elem = NULL; + next = path; + while (next != NULL) { + path_elem = xf86GetPathElem(&next); + if (*path_elem == '/') { + dir_elem = xnfcalloc(1, strlen(path_elem) + 1); + if ((p1 = strchr(path_elem, ':')) != 0) + dirlen = p1 - path_elem; + else + dirlen = strlen(path_elem); + strncpy(dir_elem, path_elem, dirlen); + dir_elem[dirlen] = '\0'; + flag = stat(dir_elem, &stat_buf); + if (flag == 0) + if (!S_ISDIR(stat_buf.st_mode)) + flag = -1; + if (flag != 0) { + xf86Msg(X_WARNING, "The directory \"%s\" does not exist.\n", dir_elem); + xf86ErrorF("\tEntry deleted from font path.\n"); + free(dir_elem); + continue; + } + else { + XNFasprintf(&p1, "%s%s", dir_elem, DIR_FILE); + flag = stat(p1, &stat_buf); + if (flag == 0) + if (!S_ISREG(stat_buf.st_mode)) + flag = -1; + free(p1); + if (flag != 0) { + xf86Msg(X_WARNING, + "`fonts.dir' not found (or not valid) in \"%s\".\n", + dir_elem); + xf86ErrorF("\tEntry deleted from font path.\n"); + xf86ErrorF("\t(Run 'mkfontdir' on \"%s\").\n", dir_elem); + free(dir_elem); + continue; + } + } + free(dir_elem); + } + + /* + * Either an OK directory, or a font server name. So add it to + * the path. + */ + if (out_pnt != tmp_path) + *out_pnt++ = ','; + strcat(out_pnt, path_elem); + out_pnt += strlen(path_elem); + } + return tmp_path; +} + + +/* + * use the datastructure that the parser provides and pick out the parts + * that we need at this point + */ +char ** +xf86ModulelistFromConfig(pointer **optlist) +{ + int count = 0, i = 0; + char **modulearray; + char *ignore[] = { "GLcore", "speedo", "bitmap", "drm", + "freetype", "type1", + NULL }; + pointer *optarray; + XF86LoadPtr modp; + Bool found; + + /* + * make sure the config file has been parsed and that we have a + * ModulePath set; if no ModulePath was given, use the default + * ModulePath + */ + if (xf86configptr == NULL) { + xf86Msg(X_ERROR, "Cannot access global config data structure\n"); + return NULL; + } + + if (xf86configptr->conf_modules) { + /* Walk the disable list and let people know what we've parsed to + * not be loaded + */ + modp = xf86configptr->conf_modules->mod_disable_lst; + while (modp) { + xf86Msg(X_WARNING, "\"%s\" will not be loaded unless you've specified it to be loaded elsewhere.\n", modp->load_name); + modp = (XF86LoadPtr) modp->list.next; + } + /* + * Walk the default settings table. For each module listed to be + * loaded, make sure it's in the mod_load_lst. If it's not, make + * sure it's not in the mod_no_load_lst. If it's not disabled, + * append it to mod_load_lst + */ + for (i=0 ; ModuleDefaults[i].name != NULL ; i++) { + if (ModuleDefaults[i].toLoad == FALSE) { + xf86Msg(X_WARNING, "\"%s\" is not to be loaded by default. Skipping.\n", ModuleDefaults[i].name); + continue; + } + found = FALSE; + modp = xf86configptr->conf_modules->mod_load_lst; + while (modp) { + if (strcmp(modp->load_name, ModuleDefaults[i].name) == 0) { + xf86Msg(X_INFO, "\"%s\" will be loaded. This was enabled by default and also specified in the config file.\n", ModuleDefaults[i].name); + found = TRUE; + break; + } + modp = (XF86LoadPtr) modp->list.next; + } + if (found == FALSE) { + modp = xf86configptr->conf_modules->mod_disable_lst; + while (modp) { + if (strcmp(modp->load_name, ModuleDefaults[i].name) == 0) { + xf86Msg(X_INFO, "\"%s\" will be loaded even though the default is to disable it.\n", ModuleDefaults[i].name); + found = TRUE; + break; + } + modp = (XF86LoadPtr) modp->list.next; + } + } + if (found == FALSE) { + XF86LoadPtr ptr = (XF86LoadPtr)xf86configptr->conf_modules; + ptr = xf86addNewLoadDirective(ptr, ModuleDefaults[i].name, XF86_LOAD_MODULE, ModuleDefaults[i].load_opt); + xf86Msg(X_INFO, "\"%s\" will be loaded by default.\n", ModuleDefaults[i].name); + } + } + } else { + xf86configptr->conf_modules = xnfcalloc(1, sizeof(XF86ConfModuleRec)); + for (i=0 ; ModuleDefaults[i].name != NULL ; i++) { + if (ModuleDefaults[i].toLoad == TRUE) { + XF86LoadPtr ptr = (XF86LoadPtr)xf86configptr->conf_modules; + ptr = xf86addNewLoadDirective(ptr, ModuleDefaults[i].name, XF86_LOAD_MODULE, ModuleDefaults[i].load_opt); + } + } + } + + /* + * Walk the list of modules in the "Module" section to determine how + * many we have. + */ + modp = xf86configptr->conf_modules->mod_load_lst; + while (modp) { + for (i = 0; ignore[i]; i++) { + if (strcmp(modp->load_name, ignore[i]) == 0) + modp->ignore = 1; + } + if (!modp->ignore) + count++; + modp = (XF86LoadPtr) modp->list.next; + } + + /* + * allocate the memory and walk the list again to fill in the pointers + */ + modulearray = xnfalloc((count + 1) * sizeof(char*)); + optarray = xnfalloc((count + 1) * sizeof(pointer)); + count = 0; + if (xf86configptr->conf_modules) { + modp = xf86configptr->conf_modules->mod_load_lst; + while (modp) { + if (!modp->ignore) { + modulearray[count] = modp->load_name; + optarray[count] = modp->load_opt; + count++; + } + modp = (XF86LoadPtr) modp->list.next; + } + } + modulearray[count] = NULL; + optarray[count] = NULL; + if (optlist) + *optlist = optarray; + else + free(optarray); + return modulearray; +} + + +char ** +xf86DriverlistFromConfig(void) +{ + int count = 0; + int j; + char **modulearray; + screenLayoutPtr slp; + + /* + * make sure the config file has been parsed and that we have a + * ModulePath set; if no ModulePath was given, use the default + * ModulePath + */ + if (xf86configptr == NULL) { + xf86Msg(X_ERROR, "Cannot access global config data structure\n"); + return NULL; + } + + /* + * Walk the list of driver lines in active "Device" sections to + * determine now many implicitly loaded modules there are. + * + */ + if (xf86ConfigLayout.screens) { + slp = xf86ConfigLayout.screens; + while ((slp++)->screen) { + count++; + } + } + + /* + * Handle the set of inactive "Device" sections. + */ + j = 0; + while (xf86ConfigLayout.inactives[j++].identifier) + count++; + + if (count == 0) + return NULL; + + /* + * allocate the memory and walk the list again to fill in the pointers + */ + modulearray = xnfalloc((count + 1) * sizeof(char*)); + count = 0; + slp = xf86ConfigLayout.screens; + while (slp->screen) { + modulearray[count] = slp->screen->device->driver; + count++; + slp++; + } + + j = 0; + + while (xf86ConfigLayout.inactives[j].identifier) + modulearray[count++] = xf86ConfigLayout.inactives[j++].driver; + + modulearray[count] = NULL; + + /* Remove duplicates */ + for (count = 0; modulearray[count] != NULL; count++) { + int i; + + for (i = 0; i < count; i++) + if (xf86NameCmp(modulearray[i], modulearray[count]) == 0) { + modulearray[count] = ""; + break; + } + } + return modulearray; +} + +char ** +xf86InputDriverlistFromConfig(void) +{ + int count = 0; + char **modulearray; + InputInfoPtr *idp; + + /* + * make sure the config file has been parsed and that we have a + * ModulePath set; if no ModulePath was given, use the default + * ModulePath + */ + if (xf86configptr == NULL) { + xf86Msg(X_ERROR, "Cannot access global config data structure\n"); + return NULL; + } + + /* + * Walk the list of driver lines in active "InputDevice" sections to + * determine now many implicitly loaded modules there are. + */ + if (xf86ConfigLayout.inputs) { + idp = xf86ConfigLayout.inputs; + while (*idp) { + count++; + idp++; + } + } + + if (count == 0) + return NULL; + + /* + * allocate the memory and walk the list again to fill in the pointers + */ + modulearray = xnfalloc((count + 1) * sizeof(char*)); + count = 0; + idp = xf86ConfigLayout.inputs; + while (idp && *idp) { + modulearray[count] = (*idp)->driver; + count++; + idp++; + } + modulearray[count] = NULL; + + /* Remove duplicates */ + for (count = 0; modulearray[count] != NULL; count++) { + int i; + + for (i = 0; i < count; i++) + if (xf86NameCmp(modulearray[i], modulearray[count]) == 0) { + modulearray[count] = ""; + break; + } + } + return modulearray; +} + +static void +fixup_video_driver_list(char **drivers) +{ + static const char *fallback[4] = { "vesa", "fbdev", "wsfb", NULL }; + char **end, **drv; + char *x; + int i; + + /* walk to the end of the list */ + for (end = drivers; *end && **end; end++) ; + end--; + + /* + * for each of the fallback drivers, if we find it in the list, + * swap it with the last available non-fallback driver. + */ + for (i = 0; fallback[i]; i++) { + for (drv = drivers; drv != end; drv++) { + if (strstr(*drv, fallback[i])) { + x = *drv; *drv = *end; *end = x; + end--; + break; + } + } + } +} + +static char ** +GenerateDriverlist(char * dirname) +{ + char **ret; + const char *subdirs[] = { dirname, NULL }; + static const char *patlist[] = {"(.*)_drv\\.so", NULL}; + ret = LoaderListDirs(subdirs, patlist); + + /* fix up the probe order for video drivers */ + if (strstr(dirname, "drivers") && ret != NULL) + fixup_video_driver_list(ret); + + return ret; +} + +char ** +xf86DriverlistFromCompile(void) +{ + static char **driverlist = NULL; + + if (!driverlist) + driverlist = GenerateDriverlist("drivers"); + + return driverlist; +} + +/* + * xf86ConfigError -- + * Print a READABLE ErrorMessage!!! All information that is + * available is printed. + */ +static void +xf86ConfigError(char *msg, ...) +{ + va_list ap; + + ErrorF("\nConfig Error:\n"); + va_start(ap, msg); + VErrorF(msg, ap); + va_end(ap); + ErrorF("\n"); + return; +} + +static void +configFiles(XF86ConfFilesPtr fileconf) +{ + MessageType pathFrom; + Bool must_copy; + int size, countDirs; + char *temp_path, *log_buf, *start, *end; + + /* FontPath */ + must_copy = TRUE; + + temp_path = defaultFontPath ? defaultFontPath : ""; + if (xf86fpFlag) + pathFrom = X_CMDLINE; + else if (fileconf && fileconf->file_fontpath) { + pathFrom = X_CONFIG; + if (xf86Info.useDefaultFontPath) { + if (asprintf(&defaultFontPath, "%s%s%s", fileconf->file_fontpath, + *temp_path ? "," : "", temp_path) == -1) + defaultFontPath = NULL; + else + must_copy = FALSE; + } + else + defaultFontPath = fileconf->file_fontpath; + } + else + pathFrom = X_DEFAULT; + temp_path = defaultFontPath ? defaultFontPath : ""; + + /* xf86ValidateFontPath modifies its argument, but returns a copy of it. */ + temp_path = must_copy ? xnfstrdup(defaultFontPath) : defaultFontPath; + defaultFontPath = xf86ValidateFontPath(temp_path); + free(temp_path); + + /* make fontpath more readable in the logfiles */ + countDirs = 1; + temp_path = defaultFontPath; + while ((temp_path = index(temp_path, ',')) != NULL) { + countDirs++; + temp_path++; + } + + log_buf = xnfalloc(strlen(defaultFontPath) + (2 * countDirs) + 1); + temp_path = log_buf; + start = defaultFontPath; + while((end = index(start, ',')) != NULL) { + size = (end - start) + 1; + *(temp_path++) = '\t'; + strncpy(temp_path, start, size); + temp_path += size; + *(temp_path++) = '\n'; + start += size; + } + /* copy last entry */ + *(temp_path++) = '\t'; + strcpy(temp_path, start); + xf86Msg(pathFrom, "FontPath set to:\n%s\n", log_buf); + free(log_buf); + + /* ModulePath */ + + if (fileconf) { + if (xf86ModPathFrom != X_CMDLINE && fileconf->file_modulepath) { + xf86ModulePath = fileconf->file_modulepath; + xf86ModPathFrom = X_CONFIG; + } + } + + xf86Msg(xf86ModPathFrom, "ModulePath set to \"%s\"\n", xf86ModulePath); + + if (!xf86xkbdirFlag && fileconf && fileconf->file_xkbdir) { + XkbBaseDirectory = fileconf->file_xkbdir; + xf86Msg(X_CONFIG, "XKB base directory set to \"%s\"\n", + XkbBaseDirectory); + } +#if 0 + /* LogFile */ + /* + * XXX The problem with this is that the log file is already open. + * One option might be to copy the exiting contents to the new location. + * and re-open it. The down side is that the default location would + * already have been overwritten. Another option would be to start with + * unique temporary location, then copy it once the correct name is known. + * A problem with this is what happens if the server exits before that + * happens. + */ + if (xf86LogFileFrom == X_DEFAULT && fileconf->file_logfile) { + xf86LogFile = fileconf->file_logfile; + xf86LogFileFrom = X_CONFIG; + } +#endif + + return; +} + +typedef enum { + FLAG_NOTRAPSIGNALS, + FLAG_DONTVTSWITCH, + FLAG_DONTZAP, + FLAG_DONTZOOM, + FLAG_DISABLEVIDMODE, + FLAG_ALLOWNONLOCAL, + FLAG_ALLOWMOUSEOPENFAIL, + FLAG_VTSYSREQ, + FLAG_SAVER_BLANKTIME, + FLAG_DPMS_STANDBYTIME, + FLAG_DPMS_SUSPENDTIME, + FLAG_DPMS_OFFTIME, + FLAG_PIXMAP, + FLAG_PC98, + FLAG_NOPM, + FLAG_XINERAMA, + FLAG_LOG, + FLAG_RENDER_COLORMAP_MODE, + FLAG_RANDR, + FLAG_AIGLX, + FLAG_IGNORE_ABI, + FLAG_ALLOW_EMPTY_INPUT, + FLAG_USE_DEFAULT_FONT_PATH, + FLAG_AUTO_ADD_DEVICES, + FLAG_AUTO_ENABLE_DEVICES, + FLAG_GLX_VISUALS, + FLAG_DRI2, + FLAG_USE_SIGIO +} FlagValues; + +/** + * NOTE: the last value for each entry is NOT the default. It is set to TRUE + * if the parser found the option in the config file. + */ +static OptionInfoRec FlagOptions[] = { + { FLAG_NOTRAPSIGNALS, "NoTrapSignals", OPTV_BOOLEAN, + {0}, FALSE }, + { FLAG_DONTVTSWITCH, "DontVTSwitch", OPTV_BOOLEAN, + {0}, FALSE }, + { FLAG_DONTZAP, "DontZap", OPTV_BOOLEAN, + {0}, FALSE }, + { FLAG_DONTZOOM, "DontZoom", OPTV_BOOLEAN, + {0}, FALSE }, + { FLAG_DISABLEVIDMODE, "DisableVidModeExtension", OPTV_BOOLEAN, + {0}, FALSE }, + { FLAG_ALLOWNONLOCAL, "AllowNonLocalXvidtune", OPTV_BOOLEAN, + {0}, FALSE }, + { FLAG_ALLOWMOUSEOPENFAIL, "AllowMouseOpenFail", OPTV_BOOLEAN, + {0}, FALSE }, + { FLAG_VTSYSREQ, "VTSysReq", OPTV_BOOLEAN, + {0}, FALSE }, + { FLAG_SAVER_BLANKTIME, "BlankTime" , OPTV_INTEGER, + {0}, FALSE }, + { FLAG_DPMS_STANDBYTIME, "StandbyTime", OPTV_INTEGER, + {0}, FALSE }, + { FLAG_DPMS_SUSPENDTIME, "SuspendTime", OPTV_INTEGER, + {0}, FALSE }, + { FLAG_DPMS_OFFTIME, "OffTime", OPTV_INTEGER, + {0}, FALSE }, + { FLAG_PIXMAP, "Pixmap", OPTV_INTEGER, + {0}, FALSE }, + { FLAG_PC98, "PC98", OPTV_BOOLEAN, + {0}, FALSE }, + { FLAG_NOPM, "NoPM", OPTV_BOOLEAN, + {0}, FALSE }, + { FLAG_XINERAMA, "Xinerama", OPTV_BOOLEAN, + {0}, FALSE }, + { FLAG_LOG, "Log", OPTV_STRING, + {0}, FALSE }, + { FLAG_RENDER_COLORMAP_MODE, "RenderColormapMode", OPTV_STRING, + {0}, FALSE }, + { FLAG_RANDR, "RandR", OPTV_BOOLEAN, + {0}, FALSE }, + { FLAG_AIGLX, "AIGLX", OPTV_BOOLEAN, + {0}, FALSE }, + { FLAG_IGNORE_ABI, "IgnoreABI", OPTV_BOOLEAN, + {0}, FALSE }, + { FLAG_USE_DEFAULT_FONT_PATH, "UseDefaultFontPath", OPTV_BOOLEAN, + {0}, FALSE }, + { FLAG_AUTO_ADD_DEVICES, "AutoAddDevices", OPTV_BOOLEAN, + {0}, FALSE }, + { FLAG_AUTO_ENABLE_DEVICES, "AutoEnableDevices", OPTV_BOOLEAN, + {0}, FALSE }, + { FLAG_GLX_VISUALS, "GlxVisuals", OPTV_STRING, + {0}, FALSE }, + { FLAG_DRI2, "DRI2", OPTV_BOOLEAN, + {0}, FALSE }, + { FLAG_USE_SIGIO, "UseSIGIO", OPTV_BOOLEAN, + {0}, FALSE }, + { -1, NULL, OPTV_NONE, + {0}, FALSE }, +}; + +#ifdef SUPPORT_PC98 +static Bool +detectPC98(void) +{ + unsigned char buf[2]; + + if (xf86ReadBIOS(0xf8000, 0xe80, buf, 2) != 2) + return FALSE; + if ((buf[0] == 0x98) && (buf[1] == 0x21)) + return TRUE; + else + return FALSE; +} +#endif + +static Bool +configServerFlags(XF86ConfFlagsPtr flagsconf, XF86OptionPtr layoutopts) +{ + XF86OptionPtr optp, tmp; + int i; + Pix24Flags pix24 = Pix24DontCare; + Bool value; + MessageType from; + const char *s; + XkbRMLVOSet set; + /* Default options. */ + set.rules = "base"; + set.model = "pc105"; + set.layout = "us"; + set.variant = NULL; + set.options = NULL; + + /* + * Merge the ServerLayout and ServerFlags options. The former have + * precedence over the latter. + */ + optp = NULL; + if (flagsconf && flagsconf->flg_option_lst) + optp = xf86optionListDup(flagsconf->flg_option_lst); + if (layoutopts) { + tmp = xf86optionListDup(layoutopts); + if (optp) + optp = xf86optionListMerge(optp, tmp); + else + optp = tmp; + } + + xf86ProcessOptions(-1, optp, FlagOptions); + + xf86GetOptValBool(FlagOptions, FLAG_NOTRAPSIGNALS, &xf86Info.notrapSignals); + xf86GetOptValBool(FlagOptions, FLAG_DONTVTSWITCH, &xf86Info.dontVTSwitch); + xf86GetOptValBool(FlagOptions, FLAG_DONTZAP, &xf86Info.dontZap); + xf86GetOptValBool(FlagOptions, FLAG_DONTZOOM, &xf86Info.dontZoom); + + xf86GetOptValBool(FlagOptions, FLAG_IGNORE_ABI, &xf86Info.ignoreABI); + if (xf86Info.ignoreABI) { + xf86Msg(X_CONFIG, "Ignoring ABI Version\n"); + } + + if (xf86SIGIOSupported()) { + xf86Info.useSIGIO = xf86ReturnOptValBool(FlagOptions, FLAG_USE_SIGIO, USE_SIGIO_BY_DEFAULT); + if (xf86IsOptionSet(FlagOptions, FLAG_USE_SIGIO)) { + from = X_CONFIG; + } else { + from = X_DEFAULT; + } + if (!xf86Info.useSIGIO) { + xf86Msg(from, "Disabling SIGIO handlers for input devices\n"); + } else if (from == X_CONFIG) { + xf86Msg(from, "Enabling SIGIO handlers for input devices\n"); + } + } else { + xf86Info.useSIGIO = FALSE; + } + + if (xf86IsOptionSet(FlagOptions, FLAG_AUTO_ADD_DEVICES)) { + xf86GetOptValBool(FlagOptions, FLAG_AUTO_ADD_DEVICES, + &xf86Info.autoAddDevices); + from = X_CONFIG; + } + else { + from = X_DEFAULT; + } + xf86Msg(from, "%sutomatically adding devices\n", + xf86Info.autoAddDevices ? "A" : "Not a"); + + if (xf86IsOptionSet(FlagOptions, FLAG_AUTO_ENABLE_DEVICES)) { + xf86GetOptValBool(FlagOptions, FLAG_AUTO_ENABLE_DEVICES, + &xf86Info.autoEnableDevices); + from = X_CONFIG; + } + else { + from = X_DEFAULT; + } + xf86Msg(from, "%sutomatically enabling devices\n", + xf86Info.autoEnableDevices ? "A" : "Not a"); + + /* + * Set things up based on the config file information. Some of these + * settings may be overridden later when the command line options are + * checked. + */ +#ifdef XF86VIDMODE + if (xf86GetOptValBool(FlagOptions, FLAG_DISABLEVIDMODE, &value)) + xf86Info.vidModeEnabled = !value; + if (xf86GetOptValBool(FlagOptions, FLAG_ALLOWNONLOCAL, &value)) + xf86Info.vidModeAllowNonLocal = value; +#endif + + if (xf86GetOptValBool(FlagOptions, FLAG_ALLOWMOUSEOPENFAIL, &value)) + xf86Info.allowMouseOpenFail = value; + + if (xf86GetOptValBool(FlagOptions, FLAG_VTSYSREQ, &value)) { +#ifdef USE_VT_SYSREQ + xf86Info.vtSysreq = value; + xf86Msg(X_CONFIG, "VTSysReq %s\n", value ? "enabled" : "disabled"); +#else + if (value) + xf86Msg(X_WARNING, "VTSysReq is not supported on this OS\n"); +#endif + } + + xf86Info.pmFlag = TRUE; + if (xf86GetOptValBool(FlagOptions, FLAG_NOPM, &value)) + xf86Info.pmFlag = !value; + { + if ((s = xf86GetOptValString(FlagOptions, FLAG_LOG))) { + if (!xf86NameCmp(s,"flush")) { + xf86Msg(X_CONFIG, "Flushing logfile enabled\n"); + xf86Info.log = LogFlush; + LogSetParameter(XLOG_FLUSH, TRUE); + } else if (!xf86NameCmp(s,"sync")) { + xf86Msg(X_CONFIG, "Syncing logfile enabled\n"); + xf86Info.log = LogSync; + LogSetParameter(XLOG_FLUSH, TRUE); + LogSetParameter(XLOG_SYNC, TRUE); + } else { + xf86Msg(X_WARNING,"Unknown Log option\n"); + } + } + } + + { + if ((s = xf86GetOptValString(FlagOptions, FLAG_RENDER_COLORMAP_MODE))){ + int policy = PictureParseCmapPolicy (s); + if (policy == PictureCmapPolicyInvalid) + xf86Msg(X_WARNING, "Unknown colormap policy \"%s\"\n", s); + else + { + xf86Msg(X_CONFIG, "Render colormap policy set to %s\n", s); + PictureCmapPolicy = policy; + } + } + } + +#ifdef RANDR + xf86Info.disableRandR = FALSE; + xf86Info.randRFrom = X_DEFAULT; + if (xf86GetOptValBool(FlagOptions, FLAG_RANDR, &value)) { + xf86Info.disableRandR = !value; + xf86Info.randRFrom = X_CONFIG; + } +#endif + + xf86Info.aiglx = TRUE; + xf86Info.aiglxFrom = X_DEFAULT; + if (xf86GetOptValBool(FlagOptions, FLAG_AIGLX, &value)) { + xf86Info.aiglx = value; + xf86Info.aiglxFrom = X_CONFIG; + } + +#ifdef GLXEXT + xf86Info.glxVisuals = XF86_GlxVisualsTypical; + xf86Info.glxVisualsFrom = X_DEFAULT; + if ((s = xf86GetOptValString(FlagOptions, FLAG_GLX_VISUALS))) { + if (!xf86NameCmp(s, "minimal")) { + xf86Info.glxVisuals = XF86_GlxVisualsMinimal; + } else if (!xf86NameCmp(s, "typical")) { + xf86Info.glxVisuals = XF86_GlxVisualsTypical; + } else if (!xf86NameCmp(s, "all")) { + xf86Info.glxVisuals = XF86_GlxVisualsAll; + } else { + xf86Msg(X_WARNING,"Unknown GlxVisuals option\n"); + } + } + + if (xf86GetOptValBool(FlagOptions, FLAG_AIGLX, &value)) { + xf86Info.aiglx = value; + xf86Info.aiglxFrom = X_CONFIG; + } +#endif + + /* if we're not hotplugging, force some input devices to exist */ + xf86Info.forceInputDevices = !(xf86Info.autoAddDevices && xf86Info.autoEnableDevices); + + /* when forcing input devices, we use kbd. otherwise evdev, so use the + * evdev rules set. */ +#if defined(linux) + if (!xf86Info.forceInputDevices) + set.rules = "evdev"; +#endif + XkbSetRulesDflts(&set); + + xf86Info.useDefaultFontPath = TRUE; + xf86Info.useDefaultFontPathFrom = X_DEFAULT; + if (xf86GetOptValBool(FlagOptions, FLAG_USE_DEFAULT_FONT_PATH, &value)) { + xf86Info.useDefaultFontPath = value; + xf86Info.useDefaultFontPathFrom = X_CONFIG; + } + +/* Make sure that timers don't overflow CARD32's after multiplying */ +#define MAX_TIME_IN_MIN (0x7fffffff / MILLI_PER_MIN) + + i = -1; + xf86GetOptValInteger(FlagOptions, FLAG_SAVER_BLANKTIME, &i); + if ((i >= 0) && (i < MAX_TIME_IN_MIN)) + ScreenSaverTime = defaultScreenSaverTime = i * MILLI_PER_MIN; + else if (i != -1) + xf86ConfigError("BlankTime value %d outside legal range of 0 - %d minutes", + i, MAX_TIME_IN_MIN); + +#ifdef DPMSExtension + i = -1; + xf86GetOptValInteger(FlagOptions, FLAG_DPMS_STANDBYTIME, &i); + if ((i >= 0) && (i < MAX_TIME_IN_MIN)) + DPMSStandbyTime = i * MILLI_PER_MIN; + else if (i != -1) + xf86ConfigError("StandbyTime value %d outside legal range of 0 - %d minutes", + i, MAX_TIME_IN_MIN); + i = -1; + xf86GetOptValInteger(FlagOptions, FLAG_DPMS_SUSPENDTIME, &i); + if ((i >= 0) && (i < MAX_TIME_IN_MIN)) + DPMSSuspendTime = i * MILLI_PER_MIN; + else if (i != -1) + xf86ConfigError("SuspendTime value %d outside legal range of 0 - %d minutes", + i, MAX_TIME_IN_MIN); + i = -1; + xf86GetOptValInteger(FlagOptions, FLAG_DPMS_OFFTIME, &i); + if ((i >= 0) && (i < MAX_TIME_IN_MIN)) + DPMSOffTime = i * MILLI_PER_MIN; + else if (i != -1) + xf86ConfigError("OffTime value %d outside legal range of 0 - %d minutes", + i, MAX_TIME_IN_MIN); +#endif + + i = -1; + xf86GetOptValInteger(FlagOptions, FLAG_PIXMAP, &i); + switch (i) { + case 24: + pix24 = Pix24Use24; + break; + case 32: + pix24 = Pix24Use32; + break; + case -1: + break; + default: + xf86ConfigError("Pixmap option's value (%d) must be 24 or 32\n", i); + return FALSE; + } + if (xf86Pix24 != Pix24DontCare) { + xf86Info.pixmap24 = xf86Pix24; + xf86Info.pix24From = X_CMDLINE; + } else if (pix24 != Pix24DontCare) { + xf86Info.pixmap24 = pix24; + xf86Info.pix24From = X_CONFIG; + } else { + xf86Info.pixmap24 = Pix24DontCare; + xf86Info.pix24From = X_DEFAULT; + } +#ifdef SUPPORT_PC98 + if (xf86GetOptValBool(FlagOptions, FLAG_PC98, &value)) { + xf86Info.pc98 = value; + if (value) { + xf86Msg(X_CONFIG, "Japanese PC98 architecture\n"); + } + } else + if (detectPC98()) { + xf86Info.pc98 = TRUE; + xf86Msg(X_PROBED, "Japanese PC98 architecture\n"); + } +#endif + +#ifdef PANORAMIX + from = X_DEFAULT; + if (!noPanoramiXExtension) + from = X_CMDLINE; + else if (xf86GetOptValBool(FlagOptions, FLAG_XINERAMA, &value)) { + noPanoramiXExtension = !value; + from = X_CONFIG; + } + if (!noPanoramiXExtension) + xf86Msg(from, "Xinerama: enabled\n"); +#endif + +#ifdef DRI2 + xf86Info.dri2 = FALSE; + xf86Info.dri2From = X_DEFAULT; + if (xf86GetOptValBool(FlagOptions, FLAG_DRI2, &value)) { + xf86Info.dri2 = value; + xf86Info.dri2From = X_CONFIG; + } +#endif + + return TRUE; +} + +Bool xf86DRI2Enabled(void) +{ + return xf86Info.dri2; +} + +/* + * Locate the core input devices. These can be specified/located in + * the following ways, in order of priority: + * + * 1. The InputDevices named by the -pointer and -keyboard command line + * options. + * 2. The "CorePointer" and "CoreKeyboard" InputDevices referred to by + * the active ServerLayout. + * 3. The first InputDevices marked as "CorePointer" and "CoreKeyboard". + * 4. The first InputDevices that use 'keyboard' or 'kbd' and a valid mouse + * driver (mouse, synaptics, evdev, vmmouse, void) + * 5. Default devices with an empty (default) configuration. These defaults + * will reference the 'mouse' and 'keyboard' drivers. + */ + +static Bool +checkCoreInputDevices(serverLayoutPtr servlayoutp, Bool implicitLayout) +{ + InputInfoPtr corePointer = NULL, coreKeyboard = NULL; + Bool foundPointer = FALSE, foundKeyboard = FALSE; + const char *pointerMsg = NULL, *keyboardMsg = NULL; + InputInfoPtr *devs, /* iterator */ + indp; + InputInfoRec Pointer = {}, Keyboard = {}; + XF86ConfInputPtr confInput; + XF86ConfInputRec defPtr, defKbd; + int count = 0; + MessageType from = X_DEFAULT; + int found = 0; + const char *mousedrivers[] = { "mouse", "synaptics", "evdev", "vmmouse", + "void", NULL }; + + /* + * First check if a core pointer or core keyboard have been specified + * in the active ServerLayout. If more than one is specified for either, + * remove the core attribute from the later ones. + */ + for (devs = servlayoutp->inputs; devs && *devs; devs++) { + indp = *devs; + if (indp->options && + xf86CheckBoolOption(indp->options, "CorePointer", FALSE)) { + if (!corePointer) { + corePointer = indp; + } else { + xf86ReplaceBoolOption(indp->options, "CorePointer", FALSE); + xf86Msg(X_WARNING, "Duplicate core pointer devices. " + "Removing core pointer attribute from \"%s\"\n", + indp->name); + } + } + if (indp->options && + xf86CheckBoolOption(indp->options, "CoreKeyboard", FALSE)) { + if (!coreKeyboard) { + coreKeyboard = indp; + } else { + xf86ReplaceBoolOption(indp->options, "CoreKeyboard", FALSE); + xf86Msg(X_WARNING, "Duplicate core keyboard devices. " + "Removing core keyboard attribute from \"%s\"\n", + indp->name); + } + } + count++; + } + + confInput = NULL; + + /* 1. Check for the -pointer command line option. */ + if (xf86PointerName) { + confInput = xf86findInput(xf86PointerName, + xf86configptr->conf_input_lst); + if (!confInput) { + xf86Msg(X_ERROR, "No InputDevice section called \"%s\"\n", + xf86PointerName); + return FALSE; + } + from = X_CMDLINE; + /* + * If one was already specified in the ServerLayout, it needs to be + * removed. + */ + if (corePointer) { + for (devs = servlayoutp->inputs; devs && *devs; devs++) + if (*devs == corePointer) + { + free(*devs); + *devs = (InputInfoPtr)0x1; /* ensure we dont skip next loop*/ + break; + } + for (; devs && *devs; devs++) + devs[0] = devs[1]; + count--; + } + corePointer = NULL; + foundPointer = TRUE; + } + + /* 2. ServerLayout-specified core pointer. */ + if (corePointer) { + foundPointer = TRUE; + from = X_CONFIG; + } + + /* 3. First core pointer device. */ + if (!foundPointer && (xf86Info.forceInputDevices || implicitLayout)) { + XF86ConfInputPtr p; + + for (p = xf86configptr->conf_input_lst; p; p = p->list.next) { + if (p->inp_option_lst && + xf86CheckBoolOption(p->inp_option_lst, "CorePointer", FALSE)) { + confInput = p; + foundPointer = TRUE; + from = X_DEFAULT; + pointerMsg = "first core pointer device"; + break; + } + } + } + + /* 4. First pointer with an allowed mouse driver. */ + if (!foundPointer && xf86Info.forceInputDevices) { + const char **driver = mousedrivers; + confInput = xf86findInput(CONF_IMPLICIT_POINTER, + xf86configptr->conf_input_lst); + while (*driver && !confInput) { + confInput = xf86findInputByDriver(*driver, + xf86configptr->conf_input_lst); + driver++; + } + if (confInput) { + foundPointer = TRUE; + from = X_DEFAULT; + pointerMsg = "first mouse device"; + } + } + + /* 5. Built-in default. */ + if (!foundPointer && xf86Info.forceInputDevices) { + memset(&defPtr, 0, sizeof(defPtr)); + defPtr.inp_identifier = strdup("<default pointer>"); + defPtr.inp_driver = strdup("mouse"); + confInput = &defPtr; + foundPointer = TRUE; + from = X_DEFAULT; + pointerMsg = "default mouse configuration"; + } + + /* Add the core pointer device to the layout, and set it to Core. */ + if (foundPointer && confInput) { + foundPointer = configInput(&Pointer, confInput, from); + if (foundPointer) { + count++; + devs = xnfrealloc(servlayoutp->inputs, + (count + 1) * sizeof(InputInfoPtr)); + devs[count - 1] = xnfalloc(sizeof(InputInfoRec)); + *devs[count - 1] = Pointer; + devs[count - 1]->options = + xf86addNewOption(devs[count -1]->options, + xnfstrdup("CorePointer"), NULL); + devs[count] = NULL; + servlayoutp->inputs = devs; + } + } + + if (!foundPointer && xf86Info.forceInputDevices) { + /* This shouldn't happen. */ + xf86Msg(X_ERROR, "Cannot locate a core pointer device.\n"); + return FALSE; + } + + /* + * always synthesize a 'mouse' section configured to send core + * events, unless a 'void' section is found, in which case the user + * probably wants to run footless. + * + * If you're using an evdev keyboard and expect a default mouse + * section ... deal. + */ + for (devs = servlayoutp->inputs; devs && *devs; devs++) { + const char **driver = mousedrivers; + while(*driver) { + if (!strcmp((*devs)->driver, *driver)) { + found = 1; + break; + } + driver++; + } + } + if (!found && xf86Info.forceInputDevices) { + xf86Msg(X_INFO, "No default mouse found, adding one\n"); + memset(&defPtr, 0, sizeof(defPtr)); + defPtr.inp_identifier = strdup("<default pointer>"); + defPtr.inp_driver = strdup("mouse"); + confInput = &defPtr; + foundPointer = configInput(&Pointer, confInput, from); + if (foundPointer) { + count++; + devs = xnfrealloc(servlayoutp->inputs, + (count + 1) * sizeof(InputInfoPtr)); + devs[count - 1] = xnfalloc(sizeof(InputInfoRec)); + *devs[count - 1] = Pointer; + devs[count - 1]->options = + xf86addNewOption(NULL, xnfstrdup("AlwaysCore"), NULL); + devs[count] = NULL; + servlayoutp->inputs = devs; + } + } + + confInput = NULL; + + /* 1. Check for the -keyboard command line option. */ + if (xf86KeyboardName) { + confInput = xf86findInput(xf86KeyboardName, + xf86configptr->conf_input_lst); + if (!confInput) { + xf86Msg(X_ERROR, "No InputDevice section called \"%s\"\n", + xf86KeyboardName); + return FALSE; + } + from = X_CMDLINE; + /* + * If one was already specified in the ServerLayout, it needs to be + * removed. + */ + if (coreKeyboard) { + for (devs = servlayoutp->inputs; devs && *devs; devs++) + if (*devs == coreKeyboard) + { + free(*devs); + *devs = (InputInfoPtr)0x1; /* ensure we dont skip next loop */ + break; + } + for (; devs && *devs; devs++) + devs[0] = devs[1]; + count--; + } + coreKeyboard = NULL; + foundKeyboard = TRUE; + } + + /* 2. ServerLayout-specified core keyboard. */ + if (coreKeyboard) { + foundKeyboard = TRUE; + from = X_CONFIG; + } + + /* 3. First core keyboard device. */ + if (!foundKeyboard && (xf86Info.forceInputDevices || implicitLayout)) { + XF86ConfInputPtr p; + + for (p = xf86configptr->conf_input_lst; p; p = p->list.next) { + if (p->inp_option_lst && + xf86CheckBoolOption(p->inp_option_lst, "CoreKeyboard", FALSE)) { + confInput = p; + foundKeyboard = TRUE; + from = X_DEFAULT; + keyboardMsg = "first core keyboard device"; + break; + } + } + } + + /* 4. First keyboard with 'keyboard' or 'kbd' as the driver. */ + if (!foundKeyboard && xf86Info.forceInputDevices) { + confInput = xf86findInput(CONF_IMPLICIT_KEYBOARD, + xf86configptr->conf_input_lst); + if (!confInput) { + confInput = xf86findInputByDriver("kbd", + xf86configptr->conf_input_lst); + } + if (confInput) { + foundKeyboard = TRUE; + from = X_DEFAULT; + keyboardMsg = "first keyboard device"; + } + } + + /* 5. Built-in default. */ + if (!foundKeyboard && xf86Info.forceInputDevices) { + memset(&defKbd, 0, sizeof(defKbd)); + defKbd.inp_identifier = strdup("<default keyboard>"); + defKbd.inp_driver = strdup("kbd"); + confInput = &defKbd; + foundKeyboard = TRUE; + keyboardMsg = "default keyboard configuration"; + from = X_DEFAULT; + } + + /* Add the core keyboard device to the layout, and set it to Core. */ + if (foundKeyboard && confInput) { + foundKeyboard = configInput(&Keyboard, confInput, from); + if (foundKeyboard) { + count++; + devs = xnfrealloc(servlayoutp->inputs, + (count + 1) * sizeof(InputInfoPtr)); + devs[count - 1] = xnfalloc(sizeof(InputInfoRec)); + *devs[count - 1] = Keyboard; + devs[count - 1]->options = + xf86addNewOption(devs[count - 1]->options, + xnfstrdup("CoreKeyboard"), NULL); + devs[count] = NULL; + servlayoutp->inputs = devs; + } + } + + if (!foundKeyboard && xf86Info.forceInputDevices) { + /* This shouldn't happen. */ + xf86Msg(X_ERROR, "Cannot locate a core keyboard device.\n"); + return FALSE; + } + + if (pointerMsg) { + if (implicitLayout) + xf86Msg(X_DEFAULT, "No Layout section. Using the %s.\n", + pointerMsg); + else + xf86Msg(X_DEFAULT, "The core pointer device wasn't specified " + "explicitly in the layout.\n" + "\tUsing the %s.\n", pointerMsg); + } + + if (keyboardMsg) { + if (implicitLayout) + xf86Msg(X_DEFAULT, "No Layout section. Using the %s.\n", + keyboardMsg); + else + xf86Msg(X_DEFAULT, "The core keyboard device wasn't specified " + "explicitly in the layout.\n" + "\tUsing the %s.\n", keyboardMsg); + } + + if (!xf86Info.forceInputDevices && !(foundPointer && foundKeyboard)) { +#if defined(CONFIG_HAL) || defined(CONFIG_UDEV) + const char *config_backend; +#if defined(CONFIG_HAL) + config_backend = "HAL"; +#else + config_backend = "udev"; +#endif + xf86Msg(X_INFO, "The server relies on %s to provide the list of " + "input devices.\n\tIf no devices become available, " + "reconfigure %s or disable AutoAddDevices.\n", + config_backend, config_backend); +#else + xf86Msg(X_WARNING, "Hotplugging requested but the server was " + "compiled without a config backend. " + "No input devices were configured, the server " + "will start without any input devices.\n"); +#endif + } + + return TRUE; +} + +typedef enum { + LAYOUT_ISOLATEDEVICE, + LAYOUT_SINGLECARD +} LayoutValues; + +static OptionInfoRec LayoutOptions[] = { + { LAYOUT_ISOLATEDEVICE, "IsolateDevice", OPTV_STRING, + {0}, FALSE }, + { LAYOUT_SINGLECARD, "SingleCard", OPTV_BOOLEAN, + {0}, FALSE }, + { -1, NULL, OPTV_NONE, + {0}, FALSE }, +}; + +static Bool +configInputDevices(XF86ConfLayoutPtr layout, serverLayoutPtr servlayoutp) +{ + XF86ConfInputrefPtr irp; + InputInfoPtr *indp; + int count = 0; + + /* + * Count the number of input devices. + */ + irp = layout->lay_input_lst; + while (irp) { + count++; + irp = (XF86ConfInputrefPtr)irp->list.next; + } + DebugF("Found %d input devices in the layout section %s\n", + count, layout->lay_identifier); + indp = xnfcalloc((count + 1), sizeof(InputInfoPtr)); + indp[count] = NULL; + irp = layout->lay_input_lst; + count = 0; + while (irp) { + indp[count] = xf86AllocateInput(); + if (!configInput(indp[count], irp->iref_inputdev, X_CONFIG)) { + while(count--) + free(indp[count]); + free(indp); + return FALSE; + } + indp[count]->options = xf86OptionListMerge(indp[count]->options, + irp->iref_option_lst); + count++; + irp = (XF86ConfInputrefPtr)irp->list.next; + } + servlayoutp->inputs = indp; + + return TRUE; +} + + +/* + * figure out which layout is active, which screens are used in that layout, + * which drivers and monitors are used in these screens + */ +static Bool +configLayout(serverLayoutPtr servlayoutp, XF86ConfLayoutPtr conf_layout, + char *default_layout) +{ + XF86ConfAdjacencyPtr adjp; + XF86ConfInactivePtr idp; + int count = 0; + int scrnum; + XF86ConfLayoutPtr l; + MessageType from; + screenLayoutPtr slp; + GDevPtr gdp; + int i = 0, j; + + if (!servlayoutp) + return FALSE; + + /* + * which layout section is the active one? + * + * If there is a -layout command line option, use that one, otherwise + * pick the first one. + */ + from = X_DEFAULT; + if (xf86LayoutName != NULL) + from = X_CMDLINE; + else if (default_layout) { + xf86LayoutName = default_layout; + from = X_CONFIG; + } + if (xf86LayoutName != NULL) { + if ((l = xf86findLayout(xf86LayoutName, conf_layout)) == NULL) { + xf86Msg(X_ERROR, "No ServerLayout section called \"%s\"\n", + xf86LayoutName); + return FALSE; + } + conf_layout = l; + } + xf86Msg(from, "ServerLayout \"%s\"\n", conf_layout->lay_identifier); + adjp = conf_layout->lay_adjacency_lst; + + /* + * we know that each screen is referenced exactly once on the left side + * of a layout statement in the Layout section. So to allocate the right + * size for the array we do a quick walk of the list to figure out how + * many sections we have + */ + while (adjp) { + count++; + adjp = (XF86ConfAdjacencyPtr)adjp->list.next; + } + + DebugF("Found %d screens in the layout section %s", + count, conf_layout->lay_identifier); + if (!count) /* alloc enough storage even if no screen is specified */ + count = 1; + + slp = xnfcalloc(1, (count + 1) * sizeof(screenLayoutRec)); + slp[count].screen = NULL; + /* + * now that we have storage, loop over the list again and fill in our + * data structure; at this point we do not fill in the adjacency + * information as it is not clear if we need it at all + */ + adjp = conf_layout->lay_adjacency_lst; + count = 0; + while (adjp) { + slp[count].screen = xnfcalloc(1, sizeof(confScreenRec)); + if (adjp->adj_scrnum < 0) + scrnum = count; + else + scrnum = adjp->adj_scrnum; + if (!configScreen(slp[count].screen, adjp->adj_screen, scrnum, + X_CONFIG)) { + free(slp); + return FALSE; + } + slp[count].x = adjp->adj_x; + slp[count].y = adjp->adj_y; + slp[count].refname = adjp->adj_refscreen; + switch (adjp->adj_where) { + case CONF_ADJ_OBSOLETE: + slp[count].where = PosObsolete; + slp[count].topname = adjp->adj_top_str; + slp[count].bottomname = adjp->adj_bottom_str; + slp[count].leftname = adjp->adj_left_str; + slp[count].rightname = adjp->adj_right_str; + break; + case CONF_ADJ_ABSOLUTE: + slp[count].where = PosAbsolute; + break; + case CONF_ADJ_RIGHTOF: + slp[count].where = PosRightOf; + break; + case CONF_ADJ_LEFTOF: + slp[count].where = PosLeftOf; + break; + case CONF_ADJ_ABOVE: + slp[count].where = PosAbove; + break; + case CONF_ADJ_BELOW: + slp[count].where = PosBelow; + break; + case CONF_ADJ_RELATIVE: + slp[count].where = PosRelative; + break; + } + count++; + adjp = (XF86ConfAdjacencyPtr)adjp->list.next; + } + + /* No screen was specified in the layout. take the first one from the + * config file, or - if it is NULL - configScreen autogenerates one for + * us */ + if (!count) + { + slp[0].screen = xnfcalloc(1, sizeof(confScreenRec)); + if (!configScreen(slp[0].screen, xf86configptr->conf_screen_lst, + 0, X_CONFIG)) { + free(slp[0].screen); + free(slp); + return FALSE; + } + } + + /* XXX Need to tie down the upper left screen. */ + + /* Fill in the refscreen and top/bottom/left/right values */ + for (i = 0; i < count; i++) { + for (j = 0; j < count; j++) { + if (slp[i].refname && + strcmp(slp[i].refname, slp[j].screen->id) == 0) { + slp[i].refscreen = slp[j].screen; + } + if (slp[i].topname && + strcmp(slp[i].topname, slp[j].screen->id) == 0) { + slp[i].top = slp[j].screen; + } + if (slp[i].bottomname && + strcmp(slp[i].bottomname, slp[j].screen->id) == 0) { + slp[i].bottom = slp[j].screen; + } + if (slp[i].leftname && + strcmp(slp[i].leftname, slp[j].screen->id) == 0) { + slp[i].left = slp[j].screen; + } + if (slp[i].rightname && + strcmp(slp[i].rightname, slp[j].screen->id) == 0) { + slp[i].right = slp[j].screen; + } + } + if (slp[i].where != PosObsolete + && slp[i].where != PosAbsolute + && !slp[i].refscreen) { + xf86Msg(X_ERROR,"Screen %s doesn't exist: deleting placement\n", + slp[i].refname); + slp[i].where = PosAbsolute; + slp[i].x = 0; + slp[i].y = 0; + } + } + + /* + * Count the number of inactive devices. + */ + count = 0; + idp = conf_layout->lay_inactive_lst; + while (idp) { + count++; + idp = (XF86ConfInactivePtr)idp->list.next; + } + DebugF("Found %d inactive devices in the layout section %s\n", + count, conf_layout->lay_identifier); + gdp = xnfalloc((count + 1) * sizeof(GDevRec)); + gdp[count].identifier = NULL; + idp = conf_layout->lay_inactive_lst; + count = 0; + while (idp) { + if (!configDevice(&gdp[count], idp->inactive_device, FALSE)) { + free(gdp); + return FALSE; + } + count++; + idp = (XF86ConfInactivePtr)idp->list.next; + } + + if (!configInputDevices(conf_layout, servlayoutp)) + return FALSE; + + servlayoutp->id = conf_layout->lay_identifier; + servlayoutp->screens = slp; + servlayoutp->inactives = gdp; + servlayoutp->options = conf_layout->lay_option_lst; + from = X_DEFAULT; + + return TRUE; +} + +/* + * No layout section, so find the first Screen section and set that up as + * the only active screen. + */ +static Bool +configImpliedLayout(serverLayoutPtr servlayoutp, XF86ConfScreenPtr conf_screen, + XF86ConfigPtr xf86configptr) +{ + MessageType from; + XF86ConfScreenPtr s; + screenLayoutPtr slp; + InputInfoPtr *indp; + XF86ConfLayoutRec layout; + + if (!servlayoutp) + return FALSE; + + /* + * which screen section is the active one? + * + * If there is a -screen option, use that one, otherwise use the first + * one. + */ + + from = X_CONFIG; + if (xf86ScreenName != NULL) { + if ((s = xf86findScreen(xf86ScreenName, conf_screen)) == NULL) { + xf86Msg(X_ERROR, "No Screen section called \"%s\"\n", + xf86ScreenName); + return FALSE; + } + conf_screen = s; + from = X_CMDLINE; + } + + /* We have exactly one screen */ + + slp = xnfcalloc(1, 2 * sizeof(screenLayoutRec)); + slp[0].screen = xnfcalloc(1, sizeof(confScreenRec)); + slp[1].screen = NULL; + if (!configScreen(slp[0].screen, conf_screen, 0, from)) { + free(slp); + return FALSE; + } + servlayoutp->id = "(implicit)"; + servlayoutp->screens = slp; + servlayoutp->inactives = xnfcalloc(1, sizeof(GDevRec)); + servlayoutp->options = NULL; + + memset(&layout, 0, sizeof(layout)); + layout.lay_identifier = servlayoutp->id; + if (xf86layoutAddInputDevices(xf86configptr, &layout) > 0) { + if (!configInputDevices(&layout, servlayoutp)) + return FALSE; + from = X_DEFAULT; + } else { + /* Set up an empty input device list, then look for some core devices. */ + indp = xnfalloc(sizeof(InputInfoPtr)); + *indp = NULL; + servlayoutp->inputs = indp; + } + + return TRUE; +} + +static Bool +configXvAdaptor(confXvAdaptorPtr adaptor, XF86ConfVideoAdaptorPtr conf_adaptor) +{ + int count = 0; + XF86ConfVideoPortPtr conf_port; + + xf86Msg(X_CONFIG, "| |-->VideoAdaptor \"%s\"\n", + conf_adaptor->va_identifier); + adaptor->identifier = conf_adaptor->va_identifier; + adaptor->options = conf_adaptor->va_option_lst; + if (conf_adaptor->va_busid || conf_adaptor->va_driver) { + xf86Msg(X_CONFIG, "| | Unsupported device type, skipping entry\n"); + return FALSE; + } + + /* + * figure out how many videoport subsections there are and fill them in + */ + conf_port = conf_adaptor->va_port_lst; + while(conf_port) { + count++; + conf_port = (XF86ConfVideoPortPtr)conf_port->list.next; + } + adaptor->ports = xnfalloc((count) * sizeof(confXvPortRec)); + adaptor->numports = count; + count = 0; + conf_port = conf_adaptor->va_port_lst; + while(conf_port) { + adaptor->ports[count].identifier = conf_port->vp_identifier; + adaptor->ports[count].options = conf_port->vp_option_lst; + count++; + conf_port = (XF86ConfVideoPortPtr)conf_port->list.next; + } + + return TRUE; +} + +static Bool +configScreen(confScreenPtr screenp, XF86ConfScreenPtr conf_screen, int scrnum, + MessageType from) +{ + int count = 0; + XF86ConfDisplayPtr dispptr; + XF86ConfAdaptorLinkPtr conf_adaptor; + Bool defaultMonitor = FALSE; + + if (!conf_screen) { + conf_screen = xnfcalloc(1, sizeof(XF86ConfScreenRec)); + conf_screen->scrn_identifier = "Default Screen Section"; + xf86Msg(X_DEFAULT, "No screen section available. Using defaults.\n"); + } + + xf86Msg(from, "|-->Screen \"%s\" (%d)\n", conf_screen->scrn_identifier, + scrnum); + /* + * now we fill in the elements of the screen + */ + screenp->id = conf_screen->scrn_identifier; + screenp->screennum = scrnum; + screenp->defaultdepth = conf_screen->scrn_defaultdepth; + screenp->defaultbpp = conf_screen->scrn_defaultbpp; + screenp->defaultfbbpp = conf_screen->scrn_defaultfbbpp; + screenp->monitor = xnfcalloc(1, sizeof(MonRec)); + /* If no monitor is specified, create a default one. */ + if (!conf_screen->scrn_monitor) { + XF86ConfMonitorRec defMon; + + memset(&defMon, 0, sizeof(defMon)); + defMon.mon_identifier = "<default monitor>"; + if (!configMonitor(screenp->monitor, &defMon)) + return FALSE; + defaultMonitor = TRUE; + } else { + if (!configMonitor(screenp->monitor,conf_screen->scrn_monitor)) + return FALSE; + } + /* Configure the device. If there isn't one configured, attach to the + * first inactive one that we can configure. If there's none that work, + * set it to NULL so that the section can be autoconfigured later */ + screenp->device = xnfcalloc(1, sizeof(GDevRec)); + if ((!conf_screen->scrn_device) && (xf86configptr->conf_device_lst)) { + conf_screen->scrn_device = xf86configptr->conf_device_lst; + xf86Msg(X_DEFAULT, "No device specified for screen \"%s\".\n" + "\tUsing the first device section listed.\n", screenp->id); + } + if (configDevice(screenp->device,conf_screen->scrn_device, TRUE)) { + screenp->device->myScreenSection = screenp; + } else { + screenp->device = NULL; + } + screenp->options = conf_screen->scrn_option_lst; + + /* + * figure out how many display subsections there are and fill them in + */ + dispptr = conf_screen->scrn_display_lst; + while(dispptr) { + count++; + dispptr = (XF86ConfDisplayPtr)dispptr->list.next; + } + screenp->displays = xnfalloc((count) * sizeof(DispRec)); + screenp->numdisplays = count; + + /* Fill in the default Virtual size, if any */ + if (conf_screen->scrn_virtualX && conf_screen->scrn_virtualY) { + for (count = 0, dispptr = conf_screen->scrn_display_lst; + dispptr; + dispptr = (XF86ConfDisplayPtr)dispptr->list.next, count++) { + screenp->displays[count].virtualX = conf_screen->scrn_virtualX; + screenp->displays[count].virtualY = conf_screen->scrn_virtualY; + } + } + + /* Now do the per-Display Virtual sizes */ + count = 0; + dispptr = conf_screen->scrn_display_lst; + while(dispptr) { + configDisplay(&(screenp->displays[count]),dispptr); + count++; + dispptr = (XF86ConfDisplayPtr)dispptr->list.next; + } + + /* + * figure out how many videoadaptor references there are and fill them in + */ + conf_adaptor = conf_screen->scrn_adaptor_lst; + while(conf_adaptor) { + count++; + conf_adaptor = (XF86ConfAdaptorLinkPtr)conf_adaptor->list.next; + } + screenp->xvadaptors = xnfalloc((count) * sizeof(confXvAdaptorRec)); + screenp->numxvadaptors = 0; + conf_adaptor = conf_screen->scrn_adaptor_lst; + while(conf_adaptor) { + if (configXvAdaptor(&(screenp->xvadaptors[screenp->numxvadaptors]), + conf_adaptor->al_adaptor)) + screenp->numxvadaptors++; + conf_adaptor = (XF86ConfAdaptorLinkPtr)conf_adaptor->list.next; + } + + if (defaultMonitor) { + xf86Msg(X_DEFAULT, "No monitor specified for screen \"%s\".\n" + "\tUsing a default monitor configuration.\n", screenp->id); + } + return TRUE; +} + +typedef enum { + MON_REDUCEDBLANKING, + MON_MAX_PIX_CLOCK, +} MonitorValues; + +static OptionInfoRec MonitorOptions[] = { + { MON_REDUCEDBLANKING, "ReducedBlanking", OPTV_BOOLEAN, + {0}, FALSE }, + { MON_MAX_PIX_CLOCK, "MaxPixClock", OPTV_FREQ, + {0}, FALSE }, + { -1, NULL, OPTV_NONE, + {0}, FALSE }, +}; + +static Bool +configMonitor(MonPtr monitorp, XF86ConfMonitorPtr conf_monitor) +{ + int count; + DisplayModePtr mode,last = NULL; + XF86ConfModeLinePtr cmodep; + XF86ConfModesPtr modes; + XF86ConfModesLinkPtr modeslnk = conf_monitor->mon_modes_sect_lst; + Gamma zeros = {0.0, 0.0, 0.0}; + float badgamma = 0.0; + double maxPixClock; + + xf86Msg(X_CONFIG, "| |-->Monitor \"%s\"\n", + conf_monitor->mon_identifier); + monitorp->id = conf_monitor->mon_identifier; + monitorp->vendor = conf_monitor->mon_vendor; + monitorp->model = conf_monitor->mon_modelname; + monitorp->Modes = NULL; + monitorp->Last = NULL; + monitorp->gamma = zeros; + monitorp->widthmm = conf_monitor->mon_width; + monitorp->heightmm = conf_monitor->mon_height; + monitorp->reducedblanking = FALSE; + monitorp->maxPixClock = 0; + monitorp->options = conf_monitor->mon_option_lst; + + /* + * fill in the monitor structure + */ + for( count = 0 ; + count < conf_monitor->mon_n_hsync && count < MAX_HSYNC; + count++) { + monitorp->hsync[count].hi = conf_monitor->mon_hsync[count].hi; + monitorp->hsync[count].lo = conf_monitor->mon_hsync[count].lo; + } + monitorp->nHsync = count; + for( count = 0 ; + count < conf_monitor->mon_n_vrefresh && count < MAX_VREFRESH; + count++) { + monitorp->vrefresh[count].hi = conf_monitor->mon_vrefresh[count].hi; + monitorp->vrefresh[count].lo = conf_monitor->mon_vrefresh[count].lo; + } + monitorp->nVrefresh = count; + + /* + * first we collect the mode lines from the UseModes directive + */ + while(modeslnk) + { + modes = xf86findModes (modeslnk->ml_modes_str, + xf86configptr->conf_modes_lst); + modeslnk->ml_modes = modes; + + + /* now add the modes found in the modes + section to the list of modes for this + monitor unless it has been added before + because we are reusing the same section + for another screen */ + if (xf86itemNotSublist( + (GenericListPtr)conf_monitor->mon_modeline_lst, + (GenericListPtr)modes->mon_modeline_lst)) { + conf_monitor->mon_modeline_lst = (XF86ConfModeLinePtr) + xf86addListItem( + (GenericListPtr)conf_monitor->mon_modeline_lst, + (GenericListPtr)modes->mon_modeline_lst); + } + modeslnk = modeslnk->list.next; + } + + /* + * we need to hook in the mode lines now + * here both data structures use lists, only our internal one + * is double linked + */ + cmodep = conf_monitor->mon_modeline_lst; + while( cmodep ) { + mode = xnfcalloc(1, sizeof(DisplayModeRec)); + mode->type = 0; + mode->Clock = cmodep->ml_clock; + mode->HDisplay = cmodep->ml_hdisplay; + mode->HSyncStart = cmodep->ml_hsyncstart; + mode->HSyncEnd = cmodep->ml_hsyncend; + mode->HTotal = cmodep->ml_htotal; + mode->VDisplay = cmodep->ml_vdisplay; + mode->VSyncStart = cmodep->ml_vsyncstart; + mode->VSyncEnd = cmodep->ml_vsyncend; + mode->VTotal = cmodep->ml_vtotal; + mode->Flags = cmodep->ml_flags; + mode->HSkew = cmodep->ml_hskew; + mode->VScan = cmodep->ml_vscan; + mode->name = xnfstrdup(cmodep->ml_identifier); + if( last ) { + mode->prev = last; + last->next = mode; + } + else { + /* + * this is the first mode + */ + monitorp->Modes = mode; + mode->prev = NULL; + } + last = mode; + cmodep = (XF86ConfModeLinePtr)cmodep->list.next; + } + if(last){ + last->next = NULL; + } + monitorp->Last = last; + + /* add the (VESA) default modes */ + if (! addDefaultModes(monitorp) ) + return FALSE; + + if (conf_monitor->mon_gamma_red > GAMMA_ZERO) + monitorp->gamma.red = conf_monitor->mon_gamma_red; + if (conf_monitor->mon_gamma_green > GAMMA_ZERO) + monitorp->gamma.green = conf_monitor->mon_gamma_green; + if (conf_monitor->mon_gamma_blue > GAMMA_ZERO) + monitorp->gamma.blue = conf_monitor->mon_gamma_blue; + + /* Check that the gamma values are within range */ + if (monitorp->gamma.red > GAMMA_ZERO && + (monitorp->gamma.red < GAMMA_MIN || + monitorp->gamma.red > GAMMA_MAX)) { + badgamma = monitorp->gamma.red; + } else if (monitorp->gamma.green > GAMMA_ZERO && + (monitorp->gamma.green < GAMMA_MIN || + monitorp->gamma.green > GAMMA_MAX)) { + badgamma = monitorp->gamma.green; + } else if (monitorp->gamma.blue > GAMMA_ZERO && + (monitorp->gamma.blue < GAMMA_MIN || + monitorp->gamma.blue > GAMMA_MAX)) { + badgamma = monitorp->gamma.blue; + } + if (badgamma > GAMMA_ZERO) { + xf86ConfigError("Gamma value %.f is out of range (%.2f - %.1f)\n", + badgamma, GAMMA_MIN, GAMMA_MAX); + return FALSE; + } + + xf86ProcessOptions(-1, monitorp->options, MonitorOptions); + xf86GetOptValBool(MonitorOptions, MON_REDUCEDBLANKING, + &monitorp->reducedblanking); + if (xf86GetOptValFreq(MonitorOptions, MON_MAX_PIX_CLOCK, OPTUNITS_KHZ, + &maxPixClock) == TRUE) { + monitorp->maxPixClock = (int) maxPixClock; + } + + return TRUE; +} + +static int +lookupVisual(const char *visname) +{ + int i; + + if (!visname || !*visname) + return -1; + + for (i = 0; i <= DirectColor; i++) { + if (!xf86nameCompare(visname, xf86VisualNames[i])) + break; + } + + if (i <= DirectColor) + return i; + + return -1; +} + + +static Bool +configDisplay(DispPtr displayp, XF86ConfDisplayPtr conf_display) +{ + int count = 0; + XF86ModePtr modep; + + displayp->frameX0 = conf_display->disp_frameX0; + displayp->frameY0 = conf_display->disp_frameY0; + displayp->virtualX = conf_display->disp_virtualX; + displayp->virtualY = conf_display->disp_virtualY; + displayp->depth = conf_display->disp_depth; + displayp->fbbpp = conf_display->disp_bpp; + displayp->weight.red = conf_display->disp_weight.red; + displayp->weight.green = conf_display->disp_weight.green; + displayp->weight.blue = conf_display->disp_weight.blue; + displayp->blackColour.red = conf_display->disp_black.red; + displayp->blackColour.green = conf_display->disp_black.green; + displayp->blackColour.blue = conf_display->disp_black.blue; + displayp->whiteColour.red = conf_display->disp_white.red; + displayp->whiteColour.green = conf_display->disp_white.green; + displayp->whiteColour.blue = conf_display->disp_white.blue; + displayp->options = conf_display->disp_option_lst; + if (conf_display->disp_visual) { + displayp->defaultVisual = lookupVisual(conf_display->disp_visual); + if (displayp->defaultVisual == -1) { + xf86ConfigError("Invalid visual name: \"%s\"", + conf_display->disp_visual); + return FALSE; + } + } else { + displayp->defaultVisual = -1; + } + + /* + * now hook in the modes + */ + modep = conf_display->disp_mode_lst; + while(modep) { + count++; + modep = (XF86ModePtr)modep->list.next; + } + displayp->modes = xnfalloc((count+1) * sizeof(char*)); + modep = conf_display->disp_mode_lst; + count = 0; + while(modep) { + displayp->modes[count] = modep->mode_name; + count++; + modep = (XF86ModePtr)modep->list.next; + } + displayp->modes[count] = NULL; + + return TRUE; +} + +static Bool +configDevice(GDevPtr devicep, XF86ConfDevicePtr conf_device, Bool active) +{ + int i; + + if (!conf_device) { + return FALSE; + } + + if (active) + xf86Msg(X_CONFIG, "| |-->Device \"%s\"\n", + conf_device->dev_identifier); + else + xf86Msg(X_CONFIG, "|-->Inactive Device \"%s\"\n", + conf_device->dev_identifier); + + devicep->identifier = conf_device->dev_identifier; + devicep->vendor = conf_device->dev_vendor; + devicep->board = conf_device->dev_board; + devicep->chipset = conf_device->dev_chipset; + devicep->ramdac = conf_device->dev_ramdac; + devicep->driver = conf_device->dev_driver; + devicep->active = active; + devicep->videoRam = conf_device->dev_videoram; + devicep->BiosBase = conf_device->dev_bios_base; + devicep->MemBase = conf_device->dev_mem_base; + devicep->IOBase = conf_device->dev_io_base; + devicep->clockchip = conf_device->dev_clockchip; + devicep->busID = conf_device->dev_busid; + devicep->textClockFreq = conf_device->dev_textclockfreq; + devicep->chipID = conf_device->dev_chipid; + devicep->chipRev = conf_device->dev_chiprev; + devicep->options = conf_device->dev_option_lst; + devicep->irq = conf_device->dev_irq; + devicep->screen = conf_device->dev_screen; + + for (i = 0; i < MAXDACSPEEDS; i++) { + if (i < CONF_MAXDACSPEEDS) + devicep->dacSpeeds[i] = conf_device->dev_dacSpeeds[i]; + else + devicep->dacSpeeds[i] = 0; + } + devicep->numclocks = conf_device->dev_clocks; + if (devicep->numclocks > MAXCLOCKS) + devicep->numclocks = MAXCLOCKS; + for (i = 0; i < devicep->numclocks; i++) { + devicep->clock[i] = conf_device->dev_clock[i]; + } + devicep->claimed = FALSE; + + return TRUE; +} + +#ifdef XF86DRI +static void +configDRI(XF86ConfDRIPtr drip) +{ + struct group *grp; + + xf86ConfigDRI.group = -1; + xf86ConfigDRI.mode = 0; + + if (drip) { + if (drip->dri_group_name) { + if ((grp = getgrnam(drip->dri_group_name))) + xf86ConfigDRI.group = grp->gr_gid; + } else { + if (drip->dri_group >= 0) + xf86ConfigDRI.group = drip->dri_group; + } + xf86ConfigDRI.mode = drip->dri_mode; + } +} +#endif + +static void +configExtensions(XF86ConfExtensionsPtr conf_ext) +{ + XF86OptionPtr o; + + if (conf_ext && conf_ext->ext_option_lst) { + for (o = conf_ext->ext_option_lst; o; o = xf86NextOption(o)) { + char *name = xf86OptionName(o); + char *val = xf86OptionValue(o); + char *n; + Bool enable = TRUE; + + /* Handle "No<ExtensionName>" */ + n = xf86NormalizeName(name); + if (strncmp(n, "no", 2) == 0) { + name += 2; + enable = FALSE; + } + + if (!val || + xf86NameCmp(val, "enable") == 0 || + xf86NameCmp(val, "enabled") == 0 || + xf86NameCmp(val, "on") == 0 || + xf86NameCmp(val, "1") == 0 || + xf86NameCmp(val, "yes") == 0 || + xf86NameCmp(val, "true") == 0) { + /* NOTHING NEEDED -- enabling is handled below */ + } else if (xf86NameCmp(val, "disable") == 0 || + xf86NameCmp(val, "disabled") == 0 || + xf86NameCmp(val, "off") == 0 || + xf86NameCmp(val, "0") == 0 || + xf86NameCmp(val, "no") == 0 || + xf86NameCmp(val, "false") == 0) { + enable = !enable; + } else { + xf86Msg(X_WARNING, "Ignoring unrecognized value \"%s\"\n", val); + free(n); + continue; + } + + if (EnableDisableExtension(name, enable)) { + xf86Msg(X_CONFIG, "Extension \"%s\" is %s\n", + name, enable ? "enabled" : "disabled"); + } else { + xf86Msg(X_WARNING, "Ignoring unrecognized extension \"%s\"\n", + name); + } + free(n); + } + } +} + +static Bool +configInput(InputInfoPtr inputp, XF86ConfInputPtr conf_input, MessageType from) +{ + xf86Msg(from, "|-->Input Device \"%s\"\n", conf_input->inp_identifier); + inputp->name = conf_input->inp_identifier; + inputp->driver = conf_input->inp_driver; + inputp->options = conf_input->inp_option_lst; + inputp->attrs = NULL; + + return TRUE; +} + +static Bool +modeIsPresent(DisplayModePtr mode, MonPtr monitorp) +{ + DisplayModePtr knownmodes = monitorp->Modes; + + /* all I can think of is a linear search... */ + while(knownmodes != NULL) + { + if(!strcmp(mode->name, knownmodes->name) && + !(knownmodes->type & M_T_DEFAULT)) + return TRUE; + knownmodes = knownmodes->next; + } + return FALSE; +} + +static Bool +addDefaultModes(MonPtr monitorp) +{ + DisplayModePtr mode; + DisplayModePtr last = monitorp->Last; + int i = 0; + + for (i = 0; i < xf86NumDefaultModes; i++) + { + mode = xf86DuplicateMode(&xf86DefaultModes[i]); + if (!modeIsPresent(mode, monitorp)) + { + monitorp->Modes = xf86ModesAdd(monitorp->Modes, mode); + last = mode; + } else { + free(mode); + } + } + monitorp->Last = last; + + return TRUE; +} + +static void +checkInput(serverLayoutPtr layout, Bool implicit_layout) { + checkCoreInputDevices(layout, implicit_layout); + + /* Unless we're forcing input devices, disable mouse/kbd devices in the + * config. Otherwise the same physical device is added multiple times, + * leading to duplicate events. + */ + if (!xf86Info.forceInputDevices && layout->inputs) + { + InputInfoPtr *dev = layout->inputs; + BOOL warned = FALSE; + + while(*dev) + { + if (strcmp((*dev)->driver, "kbd") == 0 || + strcmp((*dev)->driver, "mouse") == 0 || + strcmp((*dev)->driver, "vmmouse") == 0) + { + InputInfoPtr *current; + if (!warned) + { + xf86Msg(X_WARNING, "Hotplugging is on, devices using " + "drivers 'kbd', 'mouse' or 'vmmouse' will be disabled.\n"); + warned = TRUE; + } + + xf86Msg(X_WARNING, "Disabling %s\n", (*dev)->name); + + current = dev; + free(*dev); + + do { + *current = *(current + 1); + current++; + } while(*current); + } else + dev++; + } + } +} + +/* + * load the config file and fill the global data structure + */ +ConfigStatus +xf86HandleConfigFile(Bool autoconfig) +{ + const char *filename, *dirname, *sysdirname; + char *filesearch, *dirsearch; + MessageType filefrom = X_DEFAULT; + MessageType dirfrom = X_DEFAULT; + char *scanptr; + Bool singlecard = 0; + Bool implicit_layout = FALSE; + + if (!autoconfig) { + if (getuid() == 0) { + filesearch = ROOT_CONFIGPATH; + dirsearch = ROOT_CONFIGDIRPATH; + } else { + filesearch = USER_CONFIGPATH; + dirsearch = USER_CONFIGDIRPATH; + } + + if (xf86ConfigFile) + filefrom = X_CMDLINE; + if (xf86ConfigDir) + dirfrom = X_CMDLINE; + + xf86initConfigFiles(); + sysdirname = xf86openConfigDirFiles(SYS_CONFIGDIRPATH, NULL, + PROJECTROOT); + dirname = xf86openConfigDirFiles(dirsearch, xf86ConfigDir, PROJECTROOT); + filename = xf86openConfigFile(filesearch, xf86ConfigFile, PROJECTROOT); + if (filename) { + xf86MsgVerb(filefrom, 0, "Using config file: \"%s\"\n", filename); + xf86ConfigFile = xnfstrdup(filename); + } else { + if (xf86ConfigFile) + xf86Msg(X_ERROR, "Unable to locate/open config file: \"%s\"\n", + xf86ConfigFile); + } + if (dirname) { + xf86MsgVerb(dirfrom, 0, "Using config directory: \"%s\"\n", + dirname); + xf86ConfigDir = xnfstrdup(dirname); + } else { + if (xf86ConfigDir) + xf86Msg(X_ERROR, + "Unable to locate/open config directory: \"%s\"\n", + xf86ConfigDir); + } + if (sysdirname) + xf86MsgVerb(X_DEFAULT, 0, "Using system config directory \"%s\"\n", + sysdirname); + if (!filename && !dirname && !sysdirname) + return CONFIG_NOFILE; + } + + if ((xf86configptr = xf86readConfigFile ()) == NULL) { + xf86Msg(X_ERROR, "Problem parsing the config file\n"); + return CONFIG_PARSE_ERROR; + } + xf86closeConfigFile (); + + /* Initialise a few things. */ + + /* + * now we convert part of the information contained in the parser + * structures into our own structures. + * The important part here is to figure out which Screen Sections + * in the XF86Config file are active so that we can piece together + * the modes that we need later down the road. + * And while we are at it, we'll decode the rest of the stuff as well + */ + + /* First check if a layout section is present, and if it is valid. */ + + if (xf86configptr->conf_layout_lst == NULL || xf86ScreenName != NULL) { + if (xf86ScreenName == NULL) { + xf86Msg(X_DEFAULT, + "No Layout section. Using the first Screen section.\n"); + } + if (!configImpliedLayout(&xf86ConfigLayout, + xf86configptr->conf_screen_lst, + xf86configptr)) { + xf86Msg(X_ERROR, "Unable to determine the screen layout\n"); + return CONFIG_PARSE_ERROR; + } + implicit_layout = TRUE; + } else { + if (xf86configptr->conf_flags != NULL) { + char *dfltlayout = NULL; + pointer optlist = xf86configptr->conf_flags->flg_option_lst; + + if (optlist && xf86FindOption(optlist, "defaultserverlayout")) + dfltlayout = xf86SetStrOption(optlist, "defaultserverlayout", NULL); + if (!configLayout(&xf86ConfigLayout, xf86configptr->conf_layout_lst, + dfltlayout)) { + xf86Msg(X_ERROR, "Unable to determine the screen layout\n"); + return CONFIG_PARSE_ERROR; + } + } else { + if (!configLayout(&xf86ConfigLayout, xf86configptr->conf_layout_lst, + NULL)) { + xf86Msg(X_ERROR, "Unable to determine the screen layout\n"); + return CONFIG_PARSE_ERROR; + } + } + } + + xf86ProcessOptions(-1, xf86ConfigLayout.options, LayoutOptions); + + if ((scanptr = xf86GetOptValString(LayoutOptions, LAYOUT_ISOLATEDEVICE))) { + ; /* IsolateDevice specified; overrides SingleCard */ + } else { + xf86GetOptValBool(LayoutOptions, LAYOUT_SINGLECARD, &singlecard); + if (singlecard) + scanptr = xf86ConfigLayout.screens->screen->device->busID; + } + if (scanptr) { + if (strncmp(scanptr, "PCI:", 4) != 0) { + xf86Msg(X_WARNING, "Bus types other than PCI not yet isolable.\n" + "\tIgnoring IsolateDevice option.\n"); + } else + xf86PciIsolateDevice(scanptr); + } + + /* Now process everything else */ + if (!configServerFlags(xf86configptr->conf_flags,xf86ConfigLayout.options)){ + ErrorF ("Problem when converting the config data structures\n"); + return CONFIG_PARSE_ERROR; + } + + configFiles(xf86configptr->conf_files); + configExtensions(xf86configptr->conf_extensions); +#ifdef XF86DRI + configDRI(xf86configptr->conf_dri); +#endif + + checkInput(&xf86ConfigLayout, implicit_layout); + + /* + * Handle some command line options that can override some of the + * ServerFlags settings. + */ +#ifdef XF86VIDMODE + if (xf86VidModeDisabled) + xf86Info.vidModeEnabled = FALSE; + if (xf86VidModeAllowNonLocal) + xf86Info.vidModeAllowNonLocal = TRUE; +#endif + + if (xf86AllowMouseOpenFail) + xf86Info.allowMouseOpenFail = TRUE; + + return CONFIG_OK; +} + +Bool +xf86PathIsSafe(const char *path) +{ + return (xf86pathIsSafe(path) != 0); +} diff --git a/xorg-server/hw/xfree86/common/xf86Option.c b/xorg-server/hw/xfree86/common/xf86Option.c index 16c27e5ee..480f38694 100644 --- a/xorg-server/hw/xfree86/common/xf86Option.c +++ b/xorg-server/hw/xfree86/common/xf86Option.c @@ -212,7 +212,7 @@ LookupBoolOption(pointer optlist, const char *name, int deflt, Bool markUsed) return deflt; } -static int +static double LookupPercentOption(pointer optlist, const char *name, double deflt, Bool markUsed) { OptionInfoRec o; @@ -496,27 +496,33 @@ ParseOptionValue(int scrnIndex, pointer options, OptionInfoPtr p, switch (p->type) { case OPTV_INTEGER: if (*s == '\0') { - xf86DrvMsg(scrnIndex, X_WARNING, - "Option \"%s\" requires an integer value\n", - p->name); + if (markUsed) { + xf86DrvMsg(scrnIndex, X_WARNING, + "Option \"%s\" requires an integer value\n", + p->name); + } p->found = FALSE; } else { p->value.num = strtoul(s, &end, 0); if (*end == '\0') { p->found = TRUE; } else { - xf86DrvMsg(scrnIndex, X_WARNING, - "Option \"%s\" requires an integer value\n", - p->name); + if (markUsed) { + xf86DrvMsg(scrnIndex, X_WARNING, + "Option \"%s\" requires an integer value\n", + p->name); + } p->found = FALSE; } } break; case OPTV_STRING: if (*s == '\0') { - xf86DrvMsg(scrnIndex, X_WARNING, - "Option \"%s\" requires an string value\n", - p->name); + if (markUsed) { + xf86DrvMsg(scrnIndex, X_WARNING, + "Option \"%s\" requires an string value\n", + p->name); + } p->found = FALSE; } else { p->value.str = s; @@ -529,18 +535,22 @@ ParseOptionValue(int scrnIndex, pointer options, OptionInfoPtr p, break; case OPTV_REAL: if (*s == '\0') { - xf86DrvMsg(scrnIndex, X_WARNING, - "Option \"%s\" requires a floating point value\n", - p->name); + if (markUsed) { + xf86DrvMsg(scrnIndex, X_WARNING, + "Option \"%s\" requires a floating point " + "value\n", p->name); + } p->found = FALSE; } else { p->value.realnum = strtod(s, &end); if (*end == '\0') { p->found = TRUE; } else { - xf86DrvMsg(scrnIndex, X_WARNING, - "Option \"%s\" requires a floating point value\n", - p->name); + if (markUsed) { + xf86DrvMsg(scrnIndex, X_WARNING, + "Option \"%s\" requires a floating point " + "value\n", p->name); + } p->found = FALSE; } } @@ -549,8 +559,11 @@ ParseOptionValue(int scrnIndex, pointer options, OptionInfoPtr p, if (GetBoolValue(p, s)) { p->found = TRUE; } else { - xf86DrvMsg(scrnIndex, X_WARNING, - "Option \"%s\" requires a boolean value\n", p->name); + if (markUsed) { + xf86DrvMsg(scrnIndex, X_WARNING, + "Option \"%s\" requires a boolean value\n", + p->name); + } p->found = FALSE; } break; @@ -561,8 +574,10 @@ ParseOptionValue(int scrnIndex, pointer options, OptionInfoPtr p, * hence 100 looks the same as 100% to the caller of sccanf */ if (sscanf(s, "%lf%c", &p->value.realnum, &tmp) != 2 || tmp != '%') { - xf86DrvMsg(scrnIndex, X_WARNING, + if (markUsed) { + xf86DrvMsg(scrnIndex, X_WARNING, "Option \"%s\" requires a percent value\n", p->name); + } p->found = FALSE; } else { p->found = TRUE; @@ -571,9 +586,11 @@ ParseOptionValue(int scrnIndex, pointer options, OptionInfoPtr p, break; case OPTV_FREQ: if (*s == '\0') { - xf86DrvMsg(scrnIndex, X_WARNING, - "Option \"%s\" requires a frequency value\n", - p->name); + if (markUsed) { + xf86DrvMsg(scrnIndex, X_WARNING, + "Option \"%s\" requires a frequency value\n", + p->name); + } p->found = FALSE; } else { double freq = strtod(s, &end); @@ -590,17 +607,21 @@ ParseOptionValue(int scrnIndex, pointer options, OptionInfoPtr p, !xf86NameCmp(end, "M")) units = 1000000; else { - xf86DrvMsg(scrnIndex, X_WARNING, - "Option \"%s\" requires a frequency value\n", - p->name); + if (markUsed) { + xf86DrvMsg(scrnIndex, X_WARNING, + "Option \"%s\" requires a frequency value\n", + p->name); + } p->found = FALSE; } if (p->found) freq *= (double)units; } else { - xf86DrvMsg(scrnIndex, X_WARNING, - "Option \"%s\" requires a frequency value\n", - p->name); + if (markUsed) { + xf86DrvMsg(scrnIndex, X_WARNING, + "Option \"%s\" requires a frequency value\n", + p->name); + } p->found = FALSE; } if (p->found) { diff --git a/xorg-server/hw/xfree86/common/xf86RandR.c b/xorg-server/hw/xfree86/common/xf86RandR.c index 3bd15e059..4663d0366 100644 --- a/xorg-server/hw/xfree86/common/xf86RandR.c +++ b/xorg-server/hw/xfree86/common/xf86RandR.c @@ -1,462 +1,485 @@ -/*
- *
- * Copyright © 2002 Keith Packard, member of The XFree86 Project, Inc.
- *
- * Permission to use, copy, modify, distribute, and sell this software and its
- * documentation for any purpose is hereby granted without fee, provided that
- * the above copyright notice appear in all copies and that both that
- * copyright notice and this permission notice appear in supporting
- * documentation, and that the name of Keith Packard not be used in
- * advertising or publicity pertaining to distribution of the software without
- * specific, written prior permission. Keith Packard makes no
- * representations about the suitability of this software for any purpose. It
- * is provided "as is" without express or implied warranty.
- *
- * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
- * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
- * CONSEQUENTIAL DAMAGES OR ANY 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 THIS SOFTWARE.
- */
-
-#ifdef HAVE_XORG_CONFIG_H
-#include <xorg-config.h>
-#endif
-
-#include <X11/X.h>
-#include "os.h"
-#include "globals.h"
-#include "xf86.h"
-#include "xf86str.h"
-#include "xf86Priv.h"
-#include "xf86DDC.h"
-#include "mipointer.h"
-#include <randrstr.h>
-#include "inputstr.h"
-
-typedef struct _xf86RandRInfo {
- CreateScreenResourcesProcPtr CreateScreenResources;
- CloseScreenProcPtr CloseScreen;
- int virtualX;
- int virtualY;
- int mmWidth;
- int mmHeight;
- Rotation rotation;
-} XF86RandRInfoRec, *XF86RandRInfoPtr;
-
-static DevPrivateKeyRec xf86RandRKeyRec;
-static DevPrivateKey xf86RandRKey;
-
-#define XF86RANDRINFO(p) ((XF86RandRInfoPtr)dixLookupPrivate(&(p)->devPrivates, xf86RandRKey))
-
-static int
-xf86RandRModeRefresh (DisplayModePtr mode)
-{
- if (mode->VRefresh)
- return (int) (mode->VRefresh + 0.5);
- else if (mode->Clock == 0)
- return 0;
- else
- return (int) (mode->Clock * 1000.0 / mode->HTotal / mode->VTotal + 0.5);
-}
-
-static Bool
-xf86RandRGetInfo (ScreenPtr pScreen, Rotation *rotations)
-{
- RRScreenSizePtr pSize;
- ScrnInfoPtr scrp = XF86SCRNINFO(pScreen);
- XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen);
- DisplayModePtr mode;
- int refresh0 = 60;
- xorgRRModeMM RRModeMM;
-
- *rotations = RR_Rotate_0;
-
- for (mode = scrp->modes; mode != NULL ; mode = mode->next)
- {
- int refresh = xf86RandRModeRefresh (mode);
-
- if (mode == scrp->modes)
- refresh0 = refresh;
-
- RRModeMM.mode = mode;
- RRModeMM.virtX = randrp->virtualX;
- RRModeMM.virtY = randrp->virtualY;
- RRModeMM.mmWidth = randrp->mmWidth;
- RRModeMM.mmHeight = randrp->mmHeight;
-
- if(scrp->DriverFunc) {
- (*scrp->DriverFunc)(scrp, RR_GET_MODE_MM, &RRModeMM);
- }
-
- pSize = RRRegisterSize (pScreen,
- mode->HDisplay, mode->VDisplay,
- RRModeMM.mmWidth, RRModeMM.mmHeight);
- if (!pSize)
- return FALSE;
- RRRegisterRate (pScreen, pSize, refresh);
- if (mode == scrp->currentMode &&
- mode->HDisplay == scrp->virtualX && mode->VDisplay == scrp->virtualY)
- RRSetCurrentConfig (pScreen, randrp->rotation, refresh, pSize);
- if (mode->next == scrp->modes)
- break;
- }
- if (scrp->currentMode->HDisplay != randrp->virtualX ||
- scrp->currentMode->VDisplay != randrp->virtualY)
- {
- mode = scrp->modes;
-
- RRModeMM.mode = NULL;
- RRModeMM.virtX = randrp->virtualX;
- RRModeMM.virtY = randrp->virtualY;
- RRModeMM.mmWidth = randrp->mmWidth;
- RRModeMM.mmHeight = randrp->mmHeight;
-
- if(scrp->DriverFunc) {
- (*scrp->DriverFunc)(scrp, RR_GET_MODE_MM, &RRModeMM);
- }
-
- pSize = RRRegisterSize (pScreen,
- randrp->virtualX, randrp->virtualY,
- RRModeMM.mmWidth, RRModeMM.mmHeight);
- if (!pSize)
- return FALSE;
- RRRegisterRate (pScreen, pSize, refresh0);
- if (scrp->virtualX == randrp->virtualX &&
- scrp->virtualY == randrp->virtualY)
- {
- RRSetCurrentConfig (pScreen, randrp->rotation, refresh0, pSize);
- }
- }
-
- /* If there is driver support for randr, let it set our supported rotations */
- if(scrp->DriverFunc) {
- xorgRRRotation RRRotation;
-
- RRRotation.RRRotations = *rotations;
- if (!(*scrp->DriverFunc)(scrp, RR_GET_INFO, &RRRotation))
- return TRUE;
- *rotations = RRRotation.RRRotations;
- }
-
- return TRUE;
-}
-
-static Bool
-xf86RandRSetMode (ScreenPtr pScreen,
- DisplayModePtr mode,
- Bool useVirtual,
- int mmWidth,
- int mmHeight)
-{
- ScrnInfoPtr scrp = XF86SCRNINFO(pScreen);
- XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen);
- int oldWidth = pScreen->width;
- int oldHeight = pScreen->height;
- int oldmmWidth = pScreen->mmWidth;
- int oldmmHeight = pScreen->mmHeight;
- int oldVirtualX = scrp->virtualX;
- int oldVirtualY = scrp->virtualY;
- WindowPtr pRoot = pScreen->root;
- Bool ret = TRUE;
-
- if (pRoot && scrp->vtSema)
- (*scrp->EnableDisableFBAccess) (pScreen->myNum, FALSE);
- if (useVirtual)
- {
- scrp->virtualX = randrp->virtualX;
- scrp->virtualY = randrp->virtualY;
- }
- else
- {
- scrp->virtualX = mode->HDisplay;
- scrp->virtualY = mode->VDisplay;
- }
-
- /*
- * The DIX forgets the physical dimensions we passed into RRRegisterSize, so
- * reconstruct them if possible.
- */
- if(scrp->DriverFunc) {
- xorgRRModeMM RRModeMM;
-
- RRModeMM.mode = mode;
- RRModeMM.virtX = scrp->virtualX;
- RRModeMM.virtY = scrp->virtualY;
- RRModeMM.mmWidth = mmWidth;
- RRModeMM.mmHeight = mmHeight;
-
- (*scrp->DriverFunc)(scrp, RR_GET_MODE_MM, &RRModeMM);
-
- mmWidth = RRModeMM.mmWidth;
- mmHeight = RRModeMM.mmHeight;
- }
- if(randrp->rotation & (RR_Rotate_90 | RR_Rotate_270))
- {
- /* If the screen is rotated 90 or 270 degrees, swap the sizes. */
- pScreen->width = scrp->virtualY;
- pScreen->height = scrp->virtualX;
- pScreen->mmWidth = mmHeight;
- pScreen->mmHeight = mmWidth;
- }
- else
- {
- pScreen->width = scrp->virtualX;
- pScreen->height = scrp->virtualY;
- pScreen->mmWidth = mmWidth;
- pScreen->mmHeight = mmHeight;
- }
- if (!xf86SwitchMode (pScreen, mode))
- {
- pScreen->width = oldWidth;
- pScreen->height = oldHeight;
- pScreen->mmWidth = oldmmWidth;
- pScreen->mmHeight = oldmmHeight;
- scrp->virtualX = oldVirtualX;
- scrp->virtualY = oldVirtualY;
- ret = FALSE;
- }
- /*
- * Make sure the layout is correct
- */
- xf86ReconfigureLayout();
-
- /*
- * Make sure the whole screen is visible
- */
- xf86SetViewport (pScreen, pScreen->width, pScreen->height);
- xf86SetViewport (pScreen, 0, 0);
- if (pRoot && scrp->vtSema)
- (*scrp->EnableDisableFBAccess) (pScreen->myNum, TRUE);
- return ret;
-}
-
-static Bool
-xf86RandRSetConfig (ScreenPtr pScreen,
- Rotation rotation,
- int rate,
- RRScreenSizePtr pSize)
-{
- ScrnInfoPtr scrp = XF86SCRNINFO(pScreen);
- XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen);
- DisplayModePtr mode;
- int px, py;
- Bool useVirtual = FALSE;
- Rotation oldRotation = randrp->rotation;
-
- miPointerGetPosition(inputInfo.pointer, &px, &py);
- for (mode = scrp->modes; ; mode = mode->next)
- {
- if (mode->HDisplay == pSize->width &&
- mode->VDisplay == pSize->height &&
- (rate == 0 || xf86RandRModeRefresh (mode) == rate))
- break;
- if (mode->next == scrp->modes)
- {
- if (pSize->width == randrp->virtualX &&
- pSize->height == randrp->virtualY)
- {
- mode = scrp->modes;
- useVirtual = TRUE;
- break;
- }
- return FALSE;
- }
- }
-
- if (randrp->rotation != rotation) {
-
- /* Have the driver do its thing. */
- if (scrp->DriverFunc) {
- xorgRRRotation RRRotation;
- RRRotation.RRConfig.rotation = rotation;
- RRRotation.RRConfig.rate = rate;
- RRRotation.RRConfig.width = pSize->width;
- RRRotation.RRConfig.height = pSize->height;
-
- /*
- * Currently we need to rely on HW support for rotation.
- */
- if (!(*scrp->DriverFunc)(scrp, RR_SET_CONFIG, &RRRotation))
- return FALSE;
- } else
- return FALSE;
-
- randrp->rotation = rotation;
- }
-
- if (!xf86RandRSetMode (pScreen, mode, useVirtual, pSize->mmWidth, pSize->mmHeight)) {
- if(randrp->rotation != oldRotation) {
- /* Have the driver undo its thing. */
- if (scrp->DriverFunc) {
- xorgRRRotation RRRotation;
- RRRotation.RRConfig.rotation = oldRotation;
- RRRotation.RRConfig.rate = xf86RandRModeRefresh (scrp->currentMode);
- RRRotation.RRConfig.width = scrp->virtualX;
- RRRotation.RRConfig.height = scrp->virtualY;
- (*scrp->DriverFunc)(scrp, RR_SET_CONFIG, &RRRotation);
- }
-
- randrp->rotation = oldRotation;
- }
- return FALSE;
- }
- /*
- * Move the cursor back where it belongs; SwitchMode repositions it
- */
- if (pScreen == miPointerCurrentScreen ())
- {
- px = (px >= pScreen->width ? (pScreen->width - 1) : px);
- py = (py >= pScreen->height ? (pScreen->height - 1) : py);
-
- xf86SetViewport(pScreen, px, py);
-
- (*pScreen->SetCursorPosition) (inputInfo.pointer, pScreen, px, py, FALSE);
- }
-
- return TRUE;
-}
-
-/*
- * Wait until the screen is initialized before whacking the
- * sizes around; otherwise the screen pixmap will be allocated
- * at the current mode size rather than the maximum size
- */
-static Bool
-xf86RandRCreateScreenResources (ScreenPtr pScreen)
-{
- XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen);
-#if 0
- ScrnInfoPtr scrp = XF86SCRNINFO(pScreen);
- DisplayModePtr mode;
-#endif
-
- pScreen->CreateScreenResources = randrp->CreateScreenResources;
- if (!(*pScreen->CreateScreenResources) (pScreen))
- return FALSE;
-
-#if 0
- mode = scrp->currentMode;
- if (mode)
- xf86RandRSetMode (pScreen, mode, TRUE);
-#endif
-
- return TRUE;
-}
-
-/*
- * Reset size back to original
- */
-static Bool
-xf86RandRCloseScreen (int index, ScreenPtr pScreen)
-{
- ScrnInfoPtr scrp = XF86SCRNINFO(pScreen);
- XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen);
-
- scrp->virtualX = pScreen->width = randrp->virtualX;
- scrp->virtualY = pScreen->height = randrp->virtualY;
- scrp->currentMode = scrp->modes;
- pScreen->CloseScreen = randrp->CloseScreen;
- free(randrp);
- dixSetPrivate(&pScreen->devPrivates, xf86RandRKey, NULL);
- return (*pScreen->CloseScreen) (index, pScreen);
-}
-
-Rotation
-xf86GetRotation(ScreenPtr pScreen)
-{
- if (xf86RandRKey == NULL)
- return RR_Rotate_0;
-
- return XF86RANDRINFO(pScreen)->rotation;
-}
-
-/* Function to change RandR's idea of the virtual screen size */
-Bool
-xf86RandRSetNewVirtualAndDimensions(ScreenPtr pScreen,
- int newvirtX, int newvirtY, int newmmWidth, int newmmHeight,
- Bool resetMode)
-{
- XF86RandRInfoPtr randrp;
-
- if (xf86RandRKey == NULL)
- return FALSE;
-
- randrp = XF86RANDRINFO(pScreen);
- if (randrp == NULL)
- return FALSE;
-
- if (newvirtX > 0)
- randrp->virtualX = newvirtX;
-
- if (newvirtY > 0)
- randrp->virtualY = newvirtY;
-
- if (newmmWidth > 0)
- randrp->mmWidth = newmmWidth;
-
- if (newmmHeight > 0)
- randrp->mmHeight = newmmHeight;
-
- /* This is only for during server start */
- if (resetMode) {
- return (xf86RandRSetMode(pScreen,
- XF86SCRNINFO(pScreen)->currentMode,
- TRUE,
- pScreen->mmWidth, pScreen->mmHeight));
- }
-
- return TRUE;
-}
-
-Bool
-xf86RandRInit (ScreenPtr pScreen)
-{
- rrScrPrivPtr rp;
- XF86RandRInfoPtr randrp;
- ScrnInfoPtr scrp = XF86SCRNINFO(pScreen);
-
-#ifdef PANORAMIX
- /* XXX disable RandR when using Xinerama */
- if (!noPanoramiXExtension)
- return TRUE;
-#endif
-
- xf86RandRKey = &xf86RandRKeyRec;
-
- if (!dixRegisterPrivateKey(&xf86RandRKeyRec, PRIVATE_SCREEN, 0))
- return FALSE;
-
- randrp = malloc(sizeof (XF86RandRInfoRec));
- if (!randrp)
- return FALSE;
-
- if (!RRScreenInit (pScreen))
- {
- free(randrp);
- return FALSE;
- }
- rp = rrGetScrPriv(pScreen);
- rp->rrGetInfo = xf86RandRGetInfo;
- rp->rrSetConfig = xf86RandRSetConfig;
-
- randrp->virtualX = scrp->virtualX;
- randrp->virtualY = scrp->virtualY;
- randrp->mmWidth = pScreen->mmWidth;
- randrp->mmHeight = pScreen->mmHeight;
-
- randrp->CreateScreenResources = pScreen->CreateScreenResources;
- pScreen->CreateScreenResources = xf86RandRCreateScreenResources;
-
- randrp->CloseScreen = pScreen->CloseScreen;
- pScreen->CloseScreen = xf86RandRCloseScreen;
-
- randrp->rotation = RR_Rotate_0;
-
- dixSetPrivate(&pScreen->devPrivates, xf86RandRKey, randrp);
- return TRUE;
-}
-
-
+/* + * + * Copyright © 2002 Keith Packard, member of The XFree86 Project, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY 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 THIS SOFTWARE. + */ + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#include <X11/X.h> +#include "os.h" +#include "globals.h" +#include "xf86.h" +#include "xf86str.h" +#include "xf86Priv.h" +#include "xf86DDC.h" +#include "mipointer.h" +#include <randrstr.h> +#include "inputstr.h" + +typedef struct _xf86RandRInfo { + CreateScreenResourcesProcPtr CreateScreenResources; + CloseScreenProcPtr CloseScreen; + int virtualX; + int virtualY; + int mmWidth; + int mmHeight; + Rotation rotation; +} XF86RandRInfoRec, *XF86RandRInfoPtr; + +static DevPrivateKeyRec xf86RandRKeyRec; +static DevPrivateKey xf86RandRKey; + +#define XF86RANDRINFO(p) ((XF86RandRInfoPtr)dixLookupPrivate(&(p)->devPrivates, xf86RandRKey)) + +static int +xf86RandRModeRefresh (DisplayModePtr mode) +{ + if (mode->VRefresh) + return (int) (mode->VRefresh + 0.5); + else if (mode->Clock == 0) + return 0; + else + return (int) (mode->Clock * 1000.0 / mode->HTotal / mode->VTotal + 0.5); +} + +static Bool +xf86RandRGetInfo (ScreenPtr pScreen, Rotation *rotations) +{ + RRScreenSizePtr pSize; + ScrnInfoPtr scrp = XF86SCRNINFO(pScreen); + XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); + DisplayModePtr mode; + int refresh0 = 60; + xorgRRModeMM RRModeMM; + + *rotations = RR_Rotate_0; + + for (mode = scrp->modes; mode != NULL ; mode = mode->next) + { + int refresh = xf86RandRModeRefresh (mode); + + if (mode == scrp->modes) + refresh0 = refresh; + + RRModeMM.mode = mode; + RRModeMM.virtX = randrp->virtualX; + RRModeMM.virtY = randrp->virtualY; + RRModeMM.mmWidth = randrp->mmWidth; + RRModeMM.mmHeight = randrp->mmHeight; + + if(scrp->DriverFunc) { + (*scrp->DriverFunc)(scrp, RR_GET_MODE_MM, &RRModeMM); + } + + pSize = RRRegisterSize (pScreen, + mode->HDisplay, mode->VDisplay, + RRModeMM.mmWidth, RRModeMM.mmHeight); + if (!pSize) + return FALSE; + RRRegisterRate (pScreen, pSize, refresh); + if (mode == scrp->currentMode && + mode->HDisplay == scrp->virtualX && mode->VDisplay == scrp->virtualY) + RRSetCurrentConfig (pScreen, randrp->rotation, refresh, pSize); + if (mode->next == scrp->modes) + break; + } + if (scrp->currentMode->HDisplay != randrp->virtualX || + scrp->currentMode->VDisplay != randrp->virtualY) + { + mode = scrp->modes; + + RRModeMM.mode = NULL; + RRModeMM.virtX = randrp->virtualX; + RRModeMM.virtY = randrp->virtualY; + RRModeMM.mmWidth = randrp->mmWidth; + RRModeMM.mmHeight = randrp->mmHeight; + + if(scrp->DriverFunc) { + (*scrp->DriverFunc)(scrp, RR_GET_MODE_MM, &RRModeMM); + } + + pSize = RRRegisterSize (pScreen, + randrp->virtualX, randrp->virtualY, + RRModeMM.mmWidth, RRModeMM.mmHeight); + if (!pSize) + return FALSE; + RRRegisterRate (pScreen, pSize, refresh0); + if (scrp->virtualX == randrp->virtualX && + scrp->virtualY == randrp->virtualY) + { + RRSetCurrentConfig (pScreen, randrp->rotation, refresh0, pSize); + } + } + + /* If there is driver support for randr, let it set our supported rotations */ + if(scrp->DriverFunc) { + xorgRRRotation RRRotation; + + RRRotation.RRRotations = *rotations; + if (!(*scrp->DriverFunc)(scrp, RR_GET_INFO, &RRRotation)) + return TRUE; + *rotations = RRRotation.RRRotations; + } + + return TRUE; +} + +static Bool +xf86RandRSetMode (ScreenPtr pScreen, + DisplayModePtr mode, + Bool useVirtual, + int mmWidth, + int mmHeight) +{ + ScrnInfoPtr scrp = XF86SCRNINFO(pScreen); + XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); + int oldWidth = pScreen->width; + int oldHeight = pScreen->height; + int oldmmWidth = pScreen->mmWidth; + int oldmmHeight = pScreen->mmHeight; + int oldVirtualX = scrp->virtualX; + int oldVirtualY = scrp->virtualY; + WindowPtr pRoot = pScreen->root; + Bool ret = TRUE; + + if (pRoot && scrp->vtSema) + (*scrp->EnableDisableFBAccess) (pScreen->myNum, FALSE); + if (useVirtual) + { + scrp->virtualX = randrp->virtualX; + scrp->virtualY = randrp->virtualY; + } + else + { + scrp->virtualX = mode->HDisplay; + scrp->virtualY = mode->VDisplay; + } + + /* + * The DIX forgets the physical dimensions we passed into RRRegisterSize, so + * reconstruct them if possible. + */ + if(scrp->DriverFunc) { + xorgRRModeMM RRModeMM; + + RRModeMM.mode = mode; + RRModeMM.virtX = scrp->virtualX; + RRModeMM.virtY = scrp->virtualY; + RRModeMM.mmWidth = mmWidth; + RRModeMM.mmHeight = mmHeight; + + (*scrp->DriverFunc)(scrp, RR_GET_MODE_MM, &RRModeMM); + + mmWidth = RRModeMM.mmWidth; + mmHeight = RRModeMM.mmHeight; + } + if(randrp->rotation & (RR_Rotate_90 | RR_Rotate_270)) + { + /* If the screen is rotated 90 or 270 degrees, swap the sizes. */ + pScreen->width = scrp->virtualY; + pScreen->height = scrp->virtualX; + pScreen->mmWidth = mmHeight; + pScreen->mmHeight = mmWidth; + } + else + { + pScreen->width = scrp->virtualX; + pScreen->height = scrp->virtualY; + pScreen->mmWidth = mmWidth; + pScreen->mmHeight = mmHeight; + } + if (!xf86SwitchMode (pScreen, mode)) + { + pScreen->width = oldWidth; + pScreen->height = oldHeight; + pScreen->mmWidth = oldmmWidth; + pScreen->mmHeight = oldmmHeight; + scrp->virtualX = oldVirtualX; + scrp->virtualY = oldVirtualY; + ret = FALSE; + } + /* + * Make sure the layout is correct + */ + xf86ReconfigureLayout(); + + /* + * Make sure the whole screen is visible + */ + xf86SetViewport (pScreen, pScreen->width, pScreen->height); + xf86SetViewport (pScreen, 0, 0); + if (pRoot && scrp->vtSema) + (*scrp->EnableDisableFBAccess) (pScreen->myNum, TRUE); + return ret; +} + +static Bool +xf86RandRSetConfig (ScreenPtr pScreen, + Rotation rotation, + int rate, + RRScreenSizePtr pSize) +{ + ScrnInfoPtr scrp = XF86SCRNINFO(pScreen); + XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); + DisplayModePtr mode; + int pos[MAXDEVICES][2]; + Bool useVirtual = FALSE; + Rotation oldRotation = randrp->rotation; + DeviceIntPtr dev; + Bool view_adjusted = FALSE; + + for (dev = inputInfo.devices; dev; dev = dev->next) + { + if (!IsMaster(dev) && !IsFloating(dev)) + continue; + + miPointerGetPosition(dev, &pos[dev->id][0], &pos[dev->id][1]); + } + + for (mode = scrp->modes; ; mode = mode->next) + { + if (mode->HDisplay == pSize->width && + mode->VDisplay == pSize->height && + (rate == 0 || xf86RandRModeRefresh (mode) == rate)) + break; + if (mode->next == scrp->modes) + { + if (pSize->width == randrp->virtualX && + pSize->height == randrp->virtualY) + { + mode = scrp->modes; + useVirtual = TRUE; + break; + } + return FALSE; + } + } + + if (randrp->rotation != rotation) { + + /* Have the driver do its thing. */ + if (scrp->DriverFunc) { + xorgRRRotation RRRotation; + RRRotation.RRConfig.rotation = rotation; + RRRotation.RRConfig.rate = rate; + RRRotation.RRConfig.width = pSize->width; + RRRotation.RRConfig.height = pSize->height; + + /* + * Currently we need to rely on HW support for rotation. + */ + if (!(*scrp->DriverFunc)(scrp, RR_SET_CONFIG, &RRRotation)) + return FALSE; + } else + return FALSE; + + randrp->rotation = rotation; + } + + if (!xf86RandRSetMode (pScreen, mode, useVirtual, pSize->mmWidth, pSize->mmHeight)) { + if(randrp->rotation != oldRotation) { + /* Have the driver undo its thing. */ + if (scrp->DriverFunc) { + xorgRRRotation RRRotation; + RRRotation.RRConfig.rotation = oldRotation; + RRRotation.RRConfig.rate = xf86RandRModeRefresh (scrp->currentMode); + RRRotation.RRConfig.width = scrp->virtualX; + RRRotation.RRConfig.height = scrp->virtualY; + (*scrp->DriverFunc)(scrp, RR_SET_CONFIG, &RRRotation); + } + + randrp->rotation = oldRotation; + } + return FALSE; + } + + /* + * Move the cursor back where it belongs; SwitchMode repositions it + * FIXME: duplicated code, see modes/xf86RandR12.c + */ + for (dev = inputInfo.devices; dev; dev = dev->next) + { + if (!IsMaster(dev) && !IsFloating(dev)) + continue; + + if (pScreen == miPointerGetScreen(dev)) { + int px = pos[dev->id][0]; + int py = pos[dev->id][1]; + + px = (px >= pScreen->width ? (pScreen->width - 1) : px); + py = (py >= pScreen->height ? (pScreen->height - 1) : py); + + /* Setting the viewpoint makes only sense on one device */ + if (!view_adjusted && IsMaster(dev)) { + xf86SetViewport(pScreen, px, py); + view_adjusted = TRUE; + } + + (*pScreen->SetCursorPosition) (dev, pScreen, px, py, FALSE); + } + } + + return TRUE; +} + +/* + * Wait until the screen is initialized before whacking the + * sizes around; otherwise the screen pixmap will be allocated + * at the current mode size rather than the maximum size + */ +static Bool +xf86RandRCreateScreenResources (ScreenPtr pScreen) +{ + XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); +#if 0 + ScrnInfoPtr scrp = XF86SCRNINFO(pScreen); + DisplayModePtr mode; +#endif + + pScreen->CreateScreenResources = randrp->CreateScreenResources; + if (!(*pScreen->CreateScreenResources) (pScreen)) + return FALSE; + +#if 0 + mode = scrp->currentMode; + if (mode) + xf86RandRSetMode (pScreen, mode, TRUE); +#endif + + return TRUE; +} + +/* + * Reset size back to original + */ +static Bool +xf86RandRCloseScreen (int index, ScreenPtr pScreen) +{ + ScrnInfoPtr scrp = XF86SCRNINFO(pScreen); + XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); + + scrp->virtualX = pScreen->width = randrp->virtualX; + scrp->virtualY = pScreen->height = randrp->virtualY; + scrp->currentMode = scrp->modes; + pScreen->CloseScreen = randrp->CloseScreen; + free(randrp); + dixSetPrivate(&pScreen->devPrivates, xf86RandRKey, NULL); + return (*pScreen->CloseScreen) (index, pScreen); +} + +Rotation +xf86GetRotation(ScreenPtr pScreen) +{ + if (xf86RandRKey == NULL) + return RR_Rotate_0; + + return XF86RANDRINFO(pScreen)->rotation; +} + +/* Function to change RandR's idea of the virtual screen size */ +Bool +xf86RandRSetNewVirtualAndDimensions(ScreenPtr pScreen, + int newvirtX, int newvirtY, int newmmWidth, int newmmHeight, + Bool resetMode) +{ + XF86RandRInfoPtr randrp; + + if (xf86RandRKey == NULL) + return FALSE; + + randrp = XF86RANDRINFO(pScreen); + if (randrp == NULL) + return FALSE; + + if (newvirtX > 0) + randrp->virtualX = newvirtX; + + if (newvirtY > 0) + randrp->virtualY = newvirtY; + + if (newmmWidth > 0) + randrp->mmWidth = newmmWidth; + + if (newmmHeight > 0) + randrp->mmHeight = newmmHeight; + + /* This is only for during server start */ + if (resetMode) { + return (xf86RandRSetMode(pScreen, + XF86SCRNINFO(pScreen)->currentMode, + TRUE, + pScreen->mmWidth, pScreen->mmHeight)); + } + + return TRUE; +} + +Bool +xf86RandRInit (ScreenPtr pScreen) +{ + rrScrPrivPtr rp; + XF86RandRInfoPtr randrp; + ScrnInfoPtr scrp = XF86SCRNINFO(pScreen); + +#ifdef PANORAMIX + /* XXX disable RandR when using Xinerama */ + if (!noPanoramiXExtension) + return TRUE; +#endif + + xf86RandRKey = &xf86RandRKeyRec; + + if (!dixRegisterPrivateKey(&xf86RandRKeyRec, PRIVATE_SCREEN, 0)) + return FALSE; + + randrp = malloc(sizeof (XF86RandRInfoRec)); + if (!randrp) + return FALSE; + + if (!RRScreenInit (pScreen)) + { + free(randrp); + return FALSE; + } + rp = rrGetScrPriv(pScreen); + rp->rrGetInfo = xf86RandRGetInfo; + rp->rrSetConfig = xf86RandRSetConfig; + + randrp->virtualX = scrp->virtualX; + randrp->virtualY = scrp->virtualY; + randrp->mmWidth = pScreen->mmWidth; + randrp->mmHeight = pScreen->mmHeight; + + randrp->CreateScreenResources = pScreen->CreateScreenResources; + pScreen->CreateScreenResources = xf86RandRCreateScreenResources; + + randrp->CloseScreen = pScreen->CloseScreen; + pScreen->CloseScreen = xf86RandRCloseScreen; + + randrp->rotation = RR_Rotate_0; + + dixSetPrivate(&pScreen->devPrivates, xf86RandRKey, randrp); + return TRUE; +} + + diff --git a/xorg-server/hw/xfree86/loader/Makefile.am b/xorg-server/hw/xfree86/loader/Makefile.am index 7f386ccc0..0e5b304a4 100644 --- a/xorg-server/hw/xfree86/loader/Makefile.am +++ b/xorg-server/hw/xfree86/loader/Makefile.am @@ -12,18 +12,21 @@ EXTRA_DIST = \ loaderProcs.h \ sdksyms.sh +nodist_libloader_la_SOURCES = \ + sdksyms.c + libloader_la_SOURCES = \ loader.c \ loaderProcs.h \ loadext.c \ loadmod.c \ - os.c \ - sdksyms.c + os.c + libloader_la_LIBADD = $(DLOPEN_LIBS) CLEANFILES = sdksyms.c sdksyms.dep -sdksyms.dep sdksyms.c: sdksyms.sh +sdksyms.dep sdksyms.c: sdksyms.sh $(top_builddir)/include/do-not-use-config.h CPP='$(CPP)' AWK='$(AWK)' $(srcdir)/sdksyms.sh $(top_srcdir) $(AM_CFLAGS) $(CFLAGS) $(INCLUDES) SDKSYMS_DEP = sdksyms.dep diff --git a/xorg-server/hw/xfree86/loader/sdksyms.sh b/xorg-server/hw/xfree86/loader/sdksyms.sh index f60b8ed74..18bb73523 100644 --- a/xorg-server/hw/xfree86/loader/sdksyms.sh +++ b/xorg-server/hw/xfree86/loader/sdksyms.sh @@ -259,6 +259,7 @@ cat > sdksyms.c << EOF #include "colormap.h" #include "colormapst.h" #include "hotplug.h" +#include "client.h" #include "cursor.h" #include "cursorstr.h" #include "dix.h" diff --git a/xorg-server/hw/xfree86/modes/xf86RandR12.c b/xorg-server/hw/xfree86/modes/xf86RandR12.c index 2fe0c47e6..744a03abe 100644 --- a/xorg-server/hw/xfree86/modes/xf86RandR12.c +++ b/xorg-server/hw/xfree86/modes/xf86RandR12.c @@ -584,10 +584,12 @@ xf86RandR12SetConfig (ScreenPtr pScreen, ScrnInfoPtr scrp = XF86SCRNINFO(pScreen); XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); DisplayModePtr mode; - int px, py; + int pos[MAXDEVICES][2]; Bool useVirtual = FALSE; int maxX = 0, maxY = 0; Rotation oldRotation = randrp->rotation; + DeviceIntPtr dev; + Bool view_adjusted = FALSE; randrp->rotation = rotation; @@ -597,7 +599,14 @@ xf86RandR12SetConfig (ScreenPtr pScreen, randrp->virtualY = scrp->virtualY; } - miPointerGetPosition (inputInfo.pointer, &px, &py); + for (dev = inputInfo.devices; dev; dev = dev->next) + { + if (!IsMaster(dev) && !IsFloating(dev)) + continue; + + miPointerGetPosition(dev, &pos[dev->id][0], &pos[dev->id][1]); + } + for (mode = scrp->modes; ; mode = mode->next) { if (randrp->maxX == 0 || randrp->maxY == 0) @@ -643,15 +652,28 @@ xf86RandR12SetConfig (ScreenPtr pScreen, /* * Move the cursor back where it belongs; SwitchMode repositions it + * FIXME: duplicated code, see modes/xf86RandR12.c */ - if (pScreen == miPointerGetScreen(inputInfo.pointer)) + for (dev = inputInfo.devices; dev; dev = dev->next) { - px = (px >= pScreen->width ? (pScreen->width - 1) : px); - py = (py >= pScreen->height ? (pScreen->height - 1) : py); + if (!IsMaster(dev) && !IsFloating(dev)) + continue; - xf86SetViewport(pScreen, px, py); + if (pScreen == miPointerGetScreen(dev)) { + int px = pos[dev->id][0]; + int py = pos[dev->id][1]; - (*pScreen->SetCursorPosition) (inputInfo.pointer, pScreen, px, py, FALSE); + px = (px >= pScreen->width ? (pScreen->width - 1) : px); + py = (py >= pScreen->height ? (pScreen->height - 1) : py); + + /* Setting the viewpoint makes only sense on one device */ + if (!view_adjusted && IsMaster(dev)) { + xf86SetViewport(pScreen, px, py); + view_adjusted = TRUE; + } + + (*pScreen->SetCursorPosition) (dev, pScreen, px, py, FALSE); + } } return TRUE; diff --git a/xorg-server/hw/xfree86/ramdac/xf86Cursor.c b/xorg-server/hw/xfree86/ramdac/xf86Cursor.c index 0e648ff49..24c91cc37 100644 --- a/xorg-server/hw/xfree86/ramdac/xf86Cursor.c +++ b/xorg-server/hw/xfree86/ramdac/xf86Cursor.c @@ -1,477 +1,475 @@ -
-#ifdef HAVE_XORG_CONFIG_H
-#include <xorg-config.h>
-#endif
-
-#include "xf86.h"
-#include "xf86CursorPriv.h"
-#include "colormapst.h"
-#include "cursorstr.h"
-
-/* FIXME: This was added with the ABI change of the miPointerSpriteFuncs for
- * MPX.
- * inputInfo is needed to pass the core pointer as the default argument into
- * the cursor functions.
- *
- * Externing inputInfo is not the nice way to do it but it works.
- */
-#include "inputstr.h"
-extern InputInfo inputInfo;
-
-DevPrivateKeyRec xf86CursorScreenKeyRec;
-
-/* sprite functions */
-
-static Bool xf86CursorRealizeCursor(DeviceIntPtr, ScreenPtr, CursorPtr);
-static Bool xf86CursorUnrealizeCursor(DeviceIntPtr, ScreenPtr, CursorPtr);
-static void xf86CursorSetCursor(DeviceIntPtr, ScreenPtr, CursorPtr, int, int);
-static void xf86CursorMoveCursor(DeviceIntPtr, ScreenPtr, int, int);
-static Bool xf86DeviceCursorInitialize(DeviceIntPtr, ScreenPtr);
-static void xf86DeviceCursorCleanup(DeviceIntPtr, ScreenPtr);
-
-static miPointerSpriteFuncRec xf86CursorSpriteFuncs = {
- xf86CursorRealizeCursor,
- xf86CursorUnrealizeCursor,
- xf86CursorSetCursor,
- xf86CursorMoveCursor,
- xf86DeviceCursorInitialize,
- xf86DeviceCursorCleanup
-};
-
-/* Screen functions */
-
-static void xf86CursorInstallColormap(ColormapPtr);
-static void xf86CursorRecolorCursor(DeviceIntPtr pDev, ScreenPtr, CursorPtr, Bool);
-static Bool xf86CursorCloseScreen(int, ScreenPtr);
-static void xf86CursorQueryBestSize(int, unsigned short*, unsigned short*,
- ScreenPtr);
-
-/* ScrnInfoRec functions */
-
-static void xf86CursorEnableDisableFBAccess(int, Bool);
-static Bool xf86CursorSwitchMode(int, DisplayModePtr,int);
-
-Bool
-xf86InitCursor(
- ScreenPtr pScreen,
- xf86CursorInfoPtr infoPtr
-)
-{
- ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
- xf86CursorScreenPtr ScreenPriv;
- miPointerScreenPtr PointPriv;
-
- if (!xf86InitHardwareCursor(pScreen, infoPtr))
- return FALSE;
-
- if (!dixRegisterPrivateKey(&xf86CursorScreenKeyRec, PRIVATE_SCREEN, 0))
- return FALSE;
-
- ScreenPriv = calloc(1, sizeof(xf86CursorScreenRec));
- if (!ScreenPriv)
- return FALSE;
-
- dixSetPrivate(&pScreen->devPrivates, xf86CursorScreenKey, ScreenPriv);
-
- ScreenPriv->SWCursor = TRUE;
- ScreenPriv->isUp = FALSE;
- ScreenPriv->CurrentCursor = NULL;
- ScreenPriv->CursorInfoPtr = infoPtr;
- ScreenPriv->PalettedCursor = FALSE;
- ScreenPriv->pInstalledMap = NULL;
-
- ScreenPriv->CloseScreen = pScreen->CloseScreen;
- pScreen->CloseScreen = xf86CursorCloseScreen;
- ScreenPriv->QueryBestSize = pScreen->QueryBestSize;
- pScreen->QueryBestSize = xf86CursorQueryBestSize;
- ScreenPriv->RecolorCursor = pScreen->RecolorCursor;
- pScreen->RecolorCursor = xf86CursorRecolorCursor;
-
- if ((infoPtr->pScrn->bitsPerPixel == 8) &&
- !(infoPtr->Flags & HARDWARE_CURSOR_TRUECOLOR_AT_8BPP)) {
- ScreenPriv->InstallColormap = pScreen->InstallColormap;
- pScreen->InstallColormap = xf86CursorInstallColormap;
- ScreenPriv->PalettedCursor = TRUE;
- }
-
- PointPriv = dixLookupPrivate(&pScreen->devPrivates, miPointerScreenKey);
-
- ScreenPriv->showTransparent = PointPriv->showTransparent;
- if (infoPtr->Flags & HARDWARE_CURSOR_SHOW_TRANSPARENT)
- PointPriv->showTransparent = TRUE;
- else
- PointPriv->showTransparent = FALSE;
- ScreenPriv->spriteFuncs = PointPriv->spriteFuncs;
- PointPriv->spriteFuncs = &xf86CursorSpriteFuncs;
-
- ScreenPriv->EnableDisableFBAccess = pScrn->EnableDisableFBAccess;
- ScreenPriv->SwitchMode = pScrn->SwitchMode;
-
- ScreenPriv->ForceHWCursorCount = 0;
- ScreenPriv->HWCursorForced = FALSE;
-
- pScrn->EnableDisableFBAccess = xf86CursorEnableDisableFBAccess;
- if (pScrn->SwitchMode)
- pScrn->SwitchMode = xf86CursorSwitchMode;
-
- return TRUE;
-}
-
-/***** Screen functions *****/
-
-static Bool
-xf86CursorCloseScreen(int i, ScreenPtr pScreen)
-{
- ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
- miPointerScreenPtr PointPriv = (miPointerScreenPtr)dixLookupPrivate(
- &pScreen->devPrivates, miPointerScreenKey);
- xf86CursorScreenPtr ScreenPriv = (xf86CursorScreenPtr)dixLookupPrivate(
- &pScreen->devPrivates, xf86CursorScreenKey);
-
- if (ScreenPriv->isUp && pScrn->vtSema)
- xf86SetCursor(pScreen, NullCursor, ScreenPriv->x, ScreenPriv->y);
-
- if (ScreenPriv->CurrentCursor)
- FreeCursor(ScreenPriv->CurrentCursor, None);
-
- pScreen->CloseScreen = ScreenPriv->CloseScreen;
- pScreen->QueryBestSize = ScreenPriv->QueryBestSize;
- pScreen->RecolorCursor = ScreenPriv->RecolorCursor;
- if (ScreenPriv->InstallColormap)
- pScreen->InstallColormap = ScreenPriv->InstallColormap;
-
- PointPriv->spriteFuncs = ScreenPriv->spriteFuncs;
- PointPriv->showTransparent = ScreenPriv->showTransparent;
-
- pScrn->EnableDisableFBAccess = ScreenPriv->EnableDisableFBAccess;
- pScrn->SwitchMode = ScreenPriv->SwitchMode;
-
- free(ScreenPriv->transparentData);
- free(ScreenPriv);
-
- return (*pScreen->CloseScreen)(i, pScreen);
-}
-
-static void
-xf86CursorQueryBestSize(
- int class,
- unsigned short *width,
- unsigned short *height,
- ScreenPtr pScreen)
-{
- xf86CursorScreenPtr ScreenPriv = (xf86CursorScreenPtr)dixLookupPrivate(
- &pScreen->devPrivates, xf86CursorScreenKey);
-
- if (class == CursorShape) {
- if(*width > ScreenPriv->CursorInfoPtr->MaxWidth)
- *width = ScreenPriv->CursorInfoPtr->MaxWidth;
- if(*height > ScreenPriv->CursorInfoPtr->MaxHeight)
- *height = ScreenPriv->CursorInfoPtr->MaxHeight;
- } else
- (*ScreenPriv->QueryBestSize)(class, width, height, pScreen);
-}
-
-static void
-xf86CursorInstallColormap(ColormapPtr pMap)
-{
- xf86CursorScreenPtr ScreenPriv = (xf86CursorScreenPtr)dixLookupPrivate(
- &pMap->pScreen->devPrivates, xf86CursorScreenKey);
-
- ScreenPriv->pInstalledMap = pMap;
-
- (*ScreenPriv->InstallColormap)(pMap);
-}
-
-static void
-xf86CursorRecolorCursor(
- DeviceIntPtr pDev,
- ScreenPtr pScreen,
- CursorPtr pCurs,
- Bool displayed)
-{
- xf86CursorScreenPtr ScreenPriv = (xf86CursorScreenPtr)dixLookupPrivate(
- &pScreen->devPrivates, xf86CursorScreenKey);
-
- if (!displayed)
- return;
-
- if (ScreenPriv->SWCursor)
- (*ScreenPriv->RecolorCursor)(pDev, pScreen, pCurs, displayed);
- else
- xf86RecolorCursor(pScreen, pCurs, displayed);
-}
-
-/***** ScrnInfoRec functions *********/
-
-static void
-xf86CursorEnableDisableFBAccess(
- int index,
- Bool enable)
-{
- DeviceIntPtr pDev = inputInfo.pointer;
-
- ScreenPtr pScreen = screenInfo.screens[index];
- xf86CursorScreenPtr ScreenPriv = (xf86CursorScreenPtr)dixLookupPrivate(
- &pScreen->devPrivates, xf86CursorScreenKey);
-
- if (!enable && ScreenPriv->CurrentCursor != NullCursor) {
- CursorPtr currentCursor = ScreenPriv->CurrentCursor;
- xf86CursorSetCursor(pDev, pScreen, NullCursor, ScreenPriv->x,
- ScreenPriv->y);
- ScreenPriv->isUp = FALSE;
- ScreenPriv->SWCursor = TRUE;
- ScreenPriv->SavedCursor = currentCursor;
- }
-
- if (ScreenPriv->EnableDisableFBAccess)
- (*ScreenPriv->EnableDisableFBAccess)(index, enable);
-
- if (enable && ScreenPriv->SavedCursor)
- {
- /*
- * Re-set current cursor so drivers can react to FB access having been
- * temporarily disabled.
- */
- xf86CursorSetCursor(pDev, pScreen, ScreenPriv->SavedCursor,
- ScreenPriv->x, ScreenPriv->y);
- ScreenPriv->SavedCursor = NULL;
- }
-}
-
-static Bool
-xf86CursorSwitchMode(int index, DisplayModePtr mode, int flags)
-{
- Bool ret;
- ScreenPtr pScreen = screenInfo.screens[index];
- xf86CursorScreenPtr ScreenPriv = (xf86CursorScreenPtr)dixLookupPrivate(
- &pScreen->devPrivates, xf86CursorScreenKey);
-
- if (ScreenPriv->isUp) {
- xf86SetCursor(pScreen, NullCursor, ScreenPriv->x, ScreenPriv->y);
- ScreenPriv->isUp = FALSE;
- }
-
- ret = (*ScreenPriv->SwitchMode)(index, mode, flags);
-
- /*
- * Cannot restore cursor here because the new frame[XY][01] haven't been
- * calculated yet. However, because the hardware cursor was removed above,
- * ensure the cursor is repainted by miPointerWarpCursor().
- */
- ScreenPriv->CursorToRestore = ScreenPriv->CurrentCursor;
- miPointerSetWaitForUpdate(pScreen, FALSE); /* Force cursor repaint */
-
- return ret;
-}
-
-/****** miPointerSpriteFunctions *******/
-
-static Bool
-xf86CursorRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCurs)
-{
- xf86CursorScreenPtr ScreenPriv = (xf86CursorScreenPtr)dixLookupPrivate(
- &pScreen->devPrivates, xf86CursorScreenKey);
-
- if (pCurs->refcnt <= 1)
- dixSetPrivate(&pCurs->devPrivates, CursorScreenKey(pScreen), NULL);
-
- return (*ScreenPriv->spriteFuncs->RealizeCursor)(pDev, pScreen, pCurs);
-}
-
-static Bool
-xf86CursorUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
- CursorPtr pCurs)
-{
- xf86CursorScreenPtr ScreenPriv = (xf86CursorScreenPtr)dixLookupPrivate(
- &pScreen->devPrivates, xf86CursorScreenKey);
-
- if (pCurs->refcnt <= 1) {
- free(dixLookupPrivate(&pCurs->devPrivates, CursorScreenKey(pScreen)));
- dixSetPrivate(&pCurs->devPrivates, CursorScreenKey(pScreen), NULL);
- }
-
- return (*ScreenPriv->spriteFuncs->UnrealizeCursor)(pDev, pScreen, pCurs);
-}
-
-static void
-xf86CursorSetCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCurs,
- int x, int y)
-{
- xf86CursorScreenPtr ScreenPriv = (xf86CursorScreenPtr)dixLookupPrivate(
- &pScreen->devPrivates, xf86CursorScreenKey);
- xf86CursorInfoPtr infoPtr = ScreenPriv->CursorInfoPtr;
-
- if (pCurs == NullCursor) { /* means we're supposed to remove the cursor */
- if (ScreenPriv->SWCursor ||
- !(GetMaster(pDev, MASTER_POINTER) == inputInfo.pointer))
- (*ScreenPriv->spriteFuncs->SetCursor)(pDev, pScreen, NullCursor, x, y);
- else if (ScreenPriv->isUp) {
- xf86SetCursor(pScreen, NullCursor, x, y);
- ScreenPriv->isUp = FALSE;
- }
- if (ScreenPriv->CurrentCursor)
- FreeCursor(ScreenPriv->CurrentCursor, None);
- ScreenPriv->CurrentCursor = NullCursor;
- return;
- }
-
- /* only update for VCP, otherwise we get cursor jumps when removing a
- sprite. The second cursor is never HW rendered anyway. */
- if (pDev == inputInfo.pointer ||
- (!IsMaster(pDev) && pDev->u.master == inputInfo.pointer))
- {
- pCurs->refcnt++;
- if (ScreenPriv->CurrentCursor)
- FreeCursor(ScreenPriv->CurrentCursor, None);
- ScreenPriv->CurrentCursor = pCurs;
- ScreenPriv->x = x;
- ScreenPriv->y = y;
- ScreenPriv->CursorToRestore = NULL;
- ScreenPriv->HotX = pCurs->bits->xhot;
- ScreenPriv->HotY = pCurs->bits->yhot;
-
- if (!infoPtr->pScrn->vtSema)
- ScreenPriv->SavedCursor = pCurs;
-
- if (infoPtr->pScrn->vtSema && (ScreenPriv->ForceHWCursorCount || ((
-#ifdef ARGB_CURSOR
- pCurs->bits->argb && infoPtr->UseHWCursorARGB &&
- (*infoPtr->UseHWCursorARGB) (pScreen, pCurs) ) || (
- pCurs->bits->argb == 0 &&
-#endif
- (pCurs->bits->height <= infoPtr->MaxHeight) &&
- (pCurs->bits->width <= infoPtr->MaxWidth) &&
- (!infoPtr->UseHWCursor || (*infoPtr->UseHWCursor)(pScreen, pCurs))))))
- {
-
- if (ScreenPriv->SWCursor) /* remove the SW cursor */
- (*ScreenPriv->spriteFuncs->SetCursor)(pDev, pScreen, NullCursor, x, y);
-
- xf86SetCursor(pScreen, pCurs, x, y);
- ScreenPriv->SWCursor = FALSE;
- ScreenPriv->isUp = TRUE;
-
- miPointerSetWaitForUpdate(pScreen, !infoPtr->pScrn->silkenMouse);
- return;
- }
-
- miPointerSetWaitForUpdate(pScreen, TRUE);
-
- if (ScreenPriv->isUp) {
- /* Remove the HW cursor, or make it transparent */
- if (infoPtr->Flags & HARDWARE_CURSOR_SHOW_TRANSPARENT) {
- xf86SetTransparentCursor(pScreen);
- } else {
- xf86SetCursor(pScreen, NullCursor, x, y);
- ScreenPriv->isUp = FALSE;
- }
- }
-
- if (!ScreenPriv->SWCursor)
- ScreenPriv->SWCursor = TRUE;
-
- }
-
- if (pCurs->bits->emptyMask && !ScreenPriv->showTransparent)
- pCurs = NullCursor;
-
- (*ScreenPriv->spriteFuncs->SetCursor)(pDev, pScreen, pCurs, x, y);
-}
-
-static void
-xf86CursorMoveCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)
-{
- xf86CursorScreenPtr ScreenPriv = (xf86CursorScreenPtr)dixLookupPrivate(
- &pScreen->devPrivates, xf86CursorScreenKey);
-
- /* only update coordinate state for first sprite, otherwise we get jumps
- when removing a sprite. The second sprite is never HW rendered anyway */
- if (pDev == inputInfo.pointer ||
- (!IsMaster(pDev) && pDev->u.master == inputInfo.pointer))
- {
- ScreenPriv->x = x;
- ScreenPriv->y = y;
-
- if (ScreenPriv->CursorToRestore)
- xf86CursorSetCursor(pDev, pScreen, ScreenPriv->CursorToRestore, x, y);
- else if (ScreenPriv->SWCursor)
- (*ScreenPriv->spriteFuncs->MoveCursor)(pDev, pScreen, x, y);
- else if (ScreenPriv->isUp)
- xf86MoveCursor(pScreen, x, y);
- } else
- (*ScreenPriv->spriteFuncs->MoveCursor)(pDev, pScreen, x, y);
-}
-
-void
-xf86ForceHWCursor (ScreenPtr pScreen, Bool on)
-{
- DeviceIntPtr pDev = inputInfo.pointer;
- xf86CursorScreenPtr ScreenPriv = (xf86CursorScreenPtr)dixLookupPrivate(
- &pScreen->devPrivates, xf86CursorScreenKey);
-
- if (on)
- {
- if (ScreenPriv->ForceHWCursorCount++ == 0)
- {
- if (ScreenPriv->SWCursor && ScreenPriv->CurrentCursor)
- {
- ScreenPriv->HWCursorForced = TRUE;
- xf86CursorSetCursor (pDev, pScreen, ScreenPriv->CurrentCursor,
- ScreenPriv->x, ScreenPriv->y);
- }
- else
- ScreenPriv->HWCursorForced = FALSE;
- }
- }
- else
- {
- if (--ScreenPriv->ForceHWCursorCount == 0)
- {
- if (ScreenPriv->HWCursorForced && ScreenPriv->CurrentCursor)
- xf86CursorSetCursor (pDev, pScreen, ScreenPriv->CurrentCursor,
- ScreenPriv->x, ScreenPriv->y);
- }
- }
-}
-
-xf86CursorInfoPtr
-xf86CreateCursorInfoRec(void)
-{
- return calloc(1, sizeof(xf86CursorInfoRec));
-}
-
-void
-xf86DestroyCursorInfoRec(xf86CursorInfoPtr infoPtr)
-{
- free(infoPtr);
-}
-
-/**
- * New cursor has been created. Do your initalizations here.
- */
-static Bool
-xf86DeviceCursorInitialize(DeviceIntPtr pDev, ScreenPtr pScreen)
-{
- int ret;
- xf86CursorScreenPtr ScreenPriv = (xf86CursorScreenPtr)dixLookupPrivate(
- &pScreen->devPrivates, xf86CursorScreenKey);
-
- /* Init SW cursor */
- ret = (*ScreenPriv->spriteFuncs->DeviceCursorInitialize)(pDev, pScreen);
-
- return ret;
-}
-
-/**
- * Cursor has been removed. Clean up after yourself.
- */
-static void
-xf86DeviceCursorCleanup(DeviceIntPtr pDev, ScreenPtr pScreen)
-{
- xf86CursorScreenPtr ScreenPriv = (xf86CursorScreenPtr)dixLookupPrivate(
- &pScreen->devPrivates, xf86CursorScreenKey);
-
- /* Clean up SW cursor */
- (*ScreenPriv->spriteFuncs->DeviceCursorCleanup)(pDev, pScreen);
-}
-
+ +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#include "xf86.h" +#include "xf86CursorPriv.h" +#include "colormapst.h" +#include "cursorstr.h" + +/* FIXME: This was added with the ABI change of the miPointerSpriteFuncs for + * MPX. + * inputInfo is needed to pass the core pointer as the default argument into + * the cursor functions. + * + * Externing inputInfo is not the nice way to do it but it works. + */ +#include "inputstr.h" +extern InputInfo inputInfo; + +DevPrivateKeyRec xf86CursorScreenKeyRec; + +/* sprite functions */ + +static Bool xf86CursorRealizeCursor(DeviceIntPtr, ScreenPtr, CursorPtr); +static Bool xf86CursorUnrealizeCursor(DeviceIntPtr, ScreenPtr, CursorPtr); +static void xf86CursorSetCursor(DeviceIntPtr, ScreenPtr, CursorPtr, int, int); +static void xf86CursorMoveCursor(DeviceIntPtr, ScreenPtr, int, int); +static Bool xf86DeviceCursorInitialize(DeviceIntPtr, ScreenPtr); +static void xf86DeviceCursorCleanup(DeviceIntPtr, ScreenPtr); + +static miPointerSpriteFuncRec xf86CursorSpriteFuncs = { + xf86CursorRealizeCursor, + xf86CursorUnrealizeCursor, + xf86CursorSetCursor, + xf86CursorMoveCursor, + xf86DeviceCursorInitialize, + xf86DeviceCursorCleanup +}; + +/* Screen functions */ + +static void xf86CursorInstallColormap(ColormapPtr); +static void xf86CursorRecolorCursor(DeviceIntPtr pDev, ScreenPtr, CursorPtr, Bool); +static Bool xf86CursorCloseScreen(int, ScreenPtr); +static void xf86CursorQueryBestSize(int, unsigned short*, unsigned short*, + ScreenPtr); + +/* ScrnInfoRec functions */ + +static void xf86CursorEnableDisableFBAccess(int, Bool); +static Bool xf86CursorSwitchMode(int, DisplayModePtr,int); + +Bool +xf86InitCursor( + ScreenPtr pScreen, + xf86CursorInfoPtr infoPtr +) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + xf86CursorScreenPtr ScreenPriv; + miPointerScreenPtr PointPriv; + + if (!xf86InitHardwareCursor(pScreen, infoPtr)) + return FALSE; + + if (!dixRegisterPrivateKey(&xf86CursorScreenKeyRec, PRIVATE_SCREEN, 0)) + return FALSE; + + ScreenPriv = calloc(1, sizeof(xf86CursorScreenRec)); + if (!ScreenPriv) + return FALSE; + + dixSetPrivate(&pScreen->devPrivates, xf86CursorScreenKey, ScreenPriv); + + ScreenPriv->SWCursor = TRUE; + ScreenPriv->isUp = FALSE; + ScreenPriv->CurrentCursor = NULL; + ScreenPriv->CursorInfoPtr = infoPtr; + ScreenPriv->PalettedCursor = FALSE; + ScreenPriv->pInstalledMap = NULL; + + ScreenPriv->CloseScreen = pScreen->CloseScreen; + pScreen->CloseScreen = xf86CursorCloseScreen; + ScreenPriv->QueryBestSize = pScreen->QueryBestSize; + pScreen->QueryBestSize = xf86CursorQueryBestSize; + ScreenPriv->RecolorCursor = pScreen->RecolorCursor; + pScreen->RecolorCursor = xf86CursorRecolorCursor; + + if ((infoPtr->pScrn->bitsPerPixel == 8) && + !(infoPtr->Flags & HARDWARE_CURSOR_TRUECOLOR_AT_8BPP)) { + ScreenPriv->InstallColormap = pScreen->InstallColormap; + pScreen->InstallColormap = xf86CursorInstallColormap; + ScreenPriv->PalettedCursor = TRUE; + } + + PointPriv = dixLookupPrivate(&pScreen->devPrivates, miPointerScreenKey); + + ScreenPriv->showTransparent = PointPriv->showTransparent; + if (infoPtr->Flags & HARDWARE_CURSOR_SHOW_TRANSPARENT) + PointPriv->showTransparent = TRUE; + else + PointPriv->showTransparent = FALSE; + ScreenPriv->spriteFuncs = PointPriv->spriteFuncs; + PointPriv->spriteFuncs = &xf86CursorSpriteFuncs; + + ScreenPriv->EnableDisableFBAccess = pScrn->EnableDisableFBAccess; + ScreenPriv->SwitchMode = pScrn->SwitchMode; + + ScreenPriv->ForceHWCursorCount = 0; + ScreenPriv->HWCursorForced = FALSE; + + pScrn->EnableDisableFBAccess = xf86CursorEnableDisableFBAccess; + if (pScrn->SwitchMode) + pScrn->SwitchMode = xf86CursorSwitchMode; + + return TRUE; +} + +/***** Screen functions *****/ + +static Bool +xf86CursorCloseScreen(int i, ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + miPointerScreenPtr PointPriv = (miPointerScreenPtr)dixLookupPrivate( + &pScreen->devPrivates, miPointerScreenKey); + xf86CursorScreenPtr ScreenPriv = (xf86CursorScreenPtr)dixLookupPrivate( + &pScreen->devPrivates, xf86CursorScreenKey); + + if (ScreenPriv->isUp && pScrn->vtSema) + xf86SetCursor(pScreen, NullCursor, ScreenPriv->x, ScreenPriv->y); + + if (ScreenPriv->CurrentCursor) + FreeCursor(ScreenPriv->CurrentCursor, None); + + pScreen->CloseScreen = ScreenPriv->CloseScreen; + pScreen->QueryBestSize = ScreenPriv->QueryBestSize; + pScreen->RecolorCursor = ScreenPriv->RecolorCursor; + if (ScreenPriv->InstallColormap) + pScreen->InstallColormap = ScreenPriv->InstallColormap; + + PointPriv->spriteFuncs = ScreenPriv->spriteFuncs; + PointPriv->showTransparent = ScreenPriv->showTransparent; + + pScrn->EnableDisableFBAccess = ScreenPriv->EnableDisableFBAccess; + pScrn->SwitchMode = ScreenPriv->SwitchMode; + + free(ScreenPriv->transparentData); + free(ScreenPriv); + + return (*pScreen->CloseScreen)(i, pScreen); +} + +static void +xf86CursorQueryBestSize( + int class, + unsigned short *width, + unsigned short *height, + ScreenPtr pScreen) +{ + xf86CursorScreenPtr ScreenPriv = (xf86CursorScreenPtr)dixLookupPrivate( + &pScreen->devPrivates, xf86CursorScreenKey); + + if (class == CursorShape) { + if(*width > ScreenPriv->CursorInfoPtr->MaxWidth) + *width = ScreenPriv->CursorInfoPtr->MaxWidth; + if(*height > ScreenPriv->CursorInfoPtr->MaxHeight) + *height = ScreenPriv->CursorInfoPtr->MaxHeight; + } else + (*ScreenPriv->QueryBestSize)(class, width, height, pScreen); +} + +static void +xf86CursorInstallColormap(ColormapPtr pMap) +{ + xf86CursorScreenPtr ScreenPriv = (xf86CursorScreenPtr)dixLookupPrivate( + &pMap->pScreen->devPrivates, xf86CursorScreenKey); + + ScreenPriv->pInstalledMap = pMap; + + (*ScreenPriv->InstallColormap)(pMap); +} + +static void +xf86CursorRecolorCursor( + DeviceIntPtr pDev, + ScreenPtr pScreen, + CursorPtr pCurs, + Bool displayed) +{ + xf86CursorScreenPtr ScreenPriv = (xf86CursorScreenPtr)dixLookupPrivate( + &pScreen->devPrivates, xf86CursorScreenKey); + + if (!displayed) + return; + + if (ScreenPriv->SWCursor) + (*ScreenPriv->RecolorCursor)(pDev, pScreen, pCurs, displayed); + else + xf86RecolorCursor(pScreen, pCurs, displayed); +} + +/***** ScrnInfoRec functions *********/ + +static void +xf86CursorEnableDisableFBAccess( + int index, + Bool enable) +{ + DeviceIntPtr pDev = inputInfo.pointer; + + ScreenPtr pScreen = screenInfo.screens[index]; + xf86CursorScreenPtr ScreenPriv = (xf86CursorScreenPtr)dixLookupPrivate( + &pScreen->devPrivates, xf86CursorScreenKey); + + if (!enable && ScreenPriv->CurrentCursor != NullCursor) { + CursorPtr currentCursor = ScreenPriv->CurrentCursor; + xf86CursorSetCursor(pDev, pScreen, NullCursor, ScreenPriv->x, + ScreenPriv->y); + ScreenPriv->isUp = FALSE; + ScreenPriv->SWCursor = TRUE; + ScreenPriv->SavedCursor = currentCursor; + } + + if (ScreenPriv->EnableDisableFBAccess) + (*ScreenPriv->EnableDisableFBAccess)(index, enable); + + if (enable && ScreenPriv->SavedCursor) + { + /* + * Re-set current cursor so drivers can react to FB access having been + * temporarily disabled. + */ + xf86CursorSetCursor(pDev, pScreen, ScreenPriv->SavedCursor, + ScreenPriv->x, ScreenPriv->y); + ScreenPriv->SavedCursor = NULL; + } +} + +static Bool +xf86CursorSwitchMode(int index, DisplayModePtr mode, int flags) +{ + Bool ret; + ScreenPtr pScreen = screenInfo.screens[index]; + xf86CursorScreenPtr ScreenPriv = (xf86CursorScreenPtr)dixLookupPrivate( + &pScreen->devPrivates, xf86CursorScreenKey); + + if (ScreenPriv->isUp) { + xf86SetCursor(pScreen, NullCursor, ScreenPriv->x, ScreenPriv->y); + ScreenPriv->isUp = FALSE; + } + + ret = (*ScreenPriv->SwitchMode)(index, mode, flags); + + /* + * Cannot restore cursor here because the new frame[XY][01] haven't been + * calculated yet. However, because the hardware cursor was removed above, + * ensure the cursor is repainted by miPointerWarpCursor(). + */ + ScreenPriv->CursorToRestore = ScreenPriv->CurrentCursor; + miPointerSetWaitForUpdate(pScreen, FALSE); /* Force cursor repaint */ + + return ret; +} + +/****** miPointerSpriteFunctions *******/ + +static Bool +xf86CursorRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCurs) +{ + xf86CursorScreenPtr ScreenPriv = (xf86CursorScreenPtr)dixLookupPrivate( + &pScreen->devPrivates, xf86CursorScreenKey); + + if (pCurs->refcnt <= 1) + dixSetPrivate(&pCurs->devPrivates, CursorScreenKey(pScreen), NULL); + + return (*ScreenPriv->spriteFuncs->RealizeCursor)(pDev, pScreen, pCurs); +} + +static Bool +xf86CursorUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, + CursorPtr pCurs) +{ + xf86CursorScreenPtr ScreenPriv = (xf86CursorScreenPtr)dixLookupPrivate( + &pScreen->devPrivates, xf86CursorScreenKey); + + if (pCurs->refcnt <= 1) { + free(dixLookupPrivate(&pCurs->devPrivates, CursorScreenKey(pScreen))); + dixSetPrivate(&pCurs->devPrivates, CursorScreenKey(pScreen), NULL); + } + + return (*ScreenPriv->spriteFuncs->UnrealizeCursor)(pDev, pScreen, pCurs); +} + +static void +xf86CursorSetCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCurs, + int x, int y) +{ + xf86CursorScreenPtr ScreenPriv = (xf86CursorScreenPtr)dixLookupPrivate( + &pScreen->devPrivates, xf86CursorScreenKey); + xf86CursorInfoPtr infoPtr = ScreenPriv->CursorInfoPtr; + + if (pCurs == NullCursor) { /* means we're supposed to remove the cursor */ + if (ScreenPriv->SWCursor || + !(GetMaster(pDev, MASTER_POINTER) == inputInfo.pointer)) + (*ScreenPriv->spriteFuncs->SetCursor)(pDev, pScreen, NullCursor, x, y); + else if (ScreenPriv->isUp) { + xf86SetCursor(pScreen, NullCursor, x, y); + ScreenPriv->isUp = FALSE; + } + if (ScreenPriv->CurrentCursor) + FreeCursor(ScreenPriv->CurrentCursor, None); + ScreenPriv->CurrentCursor = NullCursor; + return; + } + + /* only update for VCP, otherwise we get cursor jumps when removing a + sprite. The second cursor is never HW rendered anyway. */ + if (GetMaster(pDev, MASTER_POINTER) == inputInfo.pointer) + { + pCurs->refcnt++; + if (ScreenPriv->CurrentCursor) + FreeCursor(ScreenPriv->CurrentCursor, None); + ScreenPriv->CurrentCursor = pCurs; + ScreenPriv->x = x; + ScreenPriv->y = y; + ScreenPriv->CursorToRestore = NULL; + ScreenPriv->HotX = pCurs->bits->xhot; + ScreenPriv->HotY = pCurs->bits->yhot; + + if (!infoPtr->pScrn->vtSema) + ScreenPriv->SavedCursor = pCurs; + + if (infoPtr->pScrn->vtSema && (ScreenPriv->ForceHWCursorCount || (( +#ifdef ARGB_CURSOR + pCurs->bits->argb && infoPtr->UseHWCursorARGB && + (*infoPtr->UseHWCursorARGB) (pScreen, pCurs) ) || ( + pCurs->bits->argb == 0 && +#endif + (pCurs->bits->height <= infoPtr->MaxHeight) && + (pCurs->bits->width <= infoPtr->MaxWidth) && + (!infoPtr->UseHWCursor || (*infoPtr->UseHWCursor)(pScreen, pCurs)))))) + { + + if (ScreenPriv->SWCursor) /* remove the SW cursor */ + (*ScreenPriv->spriteFuncs->SetCursor)(pDev, pScreen, NullCursor, x, y); + + xf86SetCursor(pScreen, pCurs, x, y); + ScreenPriv->SWCursor = FALSE; + ScreenPriv->isUp = TRUE; + + miPointerSetWaitForUpdate(pScreen, !infoPtr->pScrn->silkenMouse); + return; + } + + miPointerSetWaitForUpdate(pScreen, TRUE); + + if (ScreenPriv->isUp) { + /* Remove the HW cursor, or make it transparent */ + if (infoPtr->Flags & HARDWARE_CURSOR_SHOW_TRANSPARENT) { + xf86SetTransparentCursor(pScreen); + } else { + xf86SetCursor(pScreen, NullCursor, x, y); + ScreenPriv->isUp = FALSE; + } + } + + if (!ScreenPriv->SWCursor) + ScreenPriv->SWCursor = TRUE; + + } + + if (pCurs->bits->emptyMask && !ScreenPriv->showTransparent) + pCurs = NullCursor; + + (*ScreenPriv->spriteFuncs->SetCursor)(pDev, pScreen, pCurs, x, y); +} + +static void +xf86CursorMoveCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y) +{ + xf86CursorScreenPtr ScreenPriv = (xf86CursorScreenPtr)dixLookupPrivate( + &pScreen->devPrivates, xf86CursorScreenKey); + + /* only update coordinate state for first sprite, otherwise we get jumps + when removing a sprite. The second sprite is never HW rendered anyway */ + if (GetMaster(pDev, MASTER_POINTER) == inputInfo.pointer) + { + ScreenPriv->x = x; + ScreenPriv->y = y; + + if (ScreenPriv->CursorToRestore) + xf86CursorSetCursor(pDev, pScreen, ScreenPriv->CursorToRestore, x, y); + else if (ScreenPriv->SWCursor) + (*ScreenPriv->spriteFuncs->MoveCursor)(pDev, pScreen, x, y); + else if (ScreenPriv->isUp) + xf86MoveCursor(pScreen, x, y); + } else + (*ScreenPriv->spriteFuncs->MoveCursor)(pDev, pScreen, x, y); +} + +void +xf86ForceHWCursor (ScreenPtr pScreen, Bool on) +{ + DeviceIntPtr pDev = inputInfo.pointer; + xf86CursorScreenPtr ScreenPriv = (xf86CursorScreenPtr)dixLookupPrivate( + &pScreen->devPrivates, xf86CursorScreenKey); + + if (on) + { + if (ScreenPriv->ForceHWCursorCount++ == 0) + { + if (ScreenPriv->SWCursor && ScreenPriv->CurrentCursor) + { + ScreenPriv->HWCursorForced = TRUE; + xf86CursorSetCursor (pDev, pScreen, ScreenPriv->CurrentCursor, + ScreenPriv->x, ScreenPriv->y); + } + else + ScreenPriv->HWCursorForced = FALSE; + } + } + else + { + if (--ScreenPriv->ForceHWCursorCount == 0) + { + if (ScreenPriv->HWCursorForced && ScreenPriv->CurrentCursor) + xf86CursorSetCursor (pDev, pScreen, ScreenPriv->CurrentCursor, + ScreenPriv->x, ScreenPriv->y); + } + } +} + +xf86CursorInfoPtr +xf86CreateCursorInfoRec(void) +{ + return calloc(1, sizeof(xf86CursorInfoRec)); +} + +void +xf86DestroyCursorInfoRec(xf86CursorInfoPtr infoPtr) +{ + free(infoPtr); +} + +/** + * New cursor has been created. Do your initalizations here. + */ +static Bool +xf86DeviceCursorInitialize(DeviceIntPtr pDev, ScreenPtr pScreen) +{ + int ret; + xf86CursorScreenPtr ScreenPriv = (xf86CursorScreenPtr)dixLookupPrivate( + &pScreen->devPrivates, xf86CursorScreenKey); + + /* Init SW cursor */ + ret = (*ScreenPriv->spriteFuncs->DeviceCursorInitialize)(pDev, pScreen); + + return ret; +} + +/** + * Cursor has been removed. Clean up after yourself. + */ +static void +xf86DeviceCursorCleanup(DeviceIntPtr pDev, ScreenPtr pScreen) +{ + xf86CursorScreenPtr ScreenPriv = (xf86CursorScreenPtr)dixLookupPrivate( + &pScreen->devPrivates, xf86CursorScreenKey); + + /* Clean up SW cursor */ + (*ScreenPriv->spriteFuncs->DeviceCursorCleanup)(pDev, pScreen); +} + diff --git a/xorg-server/hw/xquartz/X11Application.h b/xorg-server/hw/xquartz/X11Application.h index b3ad19b53..256ff187a 100644 --- a/xorg-server/hw/xquartz/X11Application.h +++ b/xorg-server/hw/xquartz/X11Application.h @@ -73,6 +73,8 @@ void X11ApplicationServerReady (void); void X11ApplicationShowHideMenubar (int state); void X11ApplicationLaunchClient (const char *cmd); +Bool X11ApplicationCanEnterRandR (void); + void X11ApplicationMain(int argc, char **argv, char **envp); #define PREFS_APPSMENU "apps_menu" @@ -86,6 +88,7 @@ void X11ApplicationMain(int argc, char **argv, char **envp); #define PREFS_NO_TCP "nolisten_tcp" #define PREFS_DONE_XINIT_CHECK "done_xinit_check" #define PREFS_NO_QUIT_ALERT "no_quit_alert" +#define PREFS_NO_RANDR_ALERT "no_randr_alert" #define PREFS_OPTION_SENDS_ALT "option_sends_alt" #define PREFS_FAKE_BUTTON2 "fake_button2" #define PREFS_FAKE_BUTTON3 "fake_button3" diff --git a/xorg-server/hw/xquartz/X11Application.m b/xorg-server/hw/xquartz/X11Application.m index b855c8358..3521517a2 100644 --- a/xorg-server/hw/xquartz/X11Application.m +++ b/xorg-server/hw/xquartz/X11Application.m @@ -883,6 +883,35 @@ void X11ApplicationLaunchClient (const char *cmd) { [string release]; } +/* This is a special function in that it is run from the *SERVER* thread and + * not the AppKit thread. We want to block entering a screen-capturing RandR + * mode until we notify the user about how to get out if the X11 client crashes. + */ +Bool X11ApplicationCanEnterRandR(void) { + NSString *title, *msg; + + if([X11App prefs_get_boolean:@PREFS_NO_RANDR_ALERT default:NO] || XQuartzShieldingWindowLevel != 0) + return TRUE; + + title = NSLocalizedString(@"Enter RandR mode?", @"Dialog title when switching to RandR"); + msg = NSLocalizedString(@"An application has requested X11 to change the resolution of your display. X11 will restore the display to its previous state when the requesting application requests to return to the previous state. Alternatively, you can use the ⌥⌘A key sequence to force X11 to return to the previous state.", + @"Dialog when switching to RandR"); + + if(!XQuartzIsRootless) + QuartzShowFullscreen(FALSE); + + switch(NSRunAlertPanel(title, msg, NSLocalizedString(@"Allow", @""), NSLocalizedString (@"Cancel", @""), NSLocalizedString (@"Always Allow", @""))) { + case NSAlertOtherReturn: + [X11App prefs_set_boolean:@PREFS_NO_RANDR_ALERT value:YES]; + [X11App prefs_synchronize]; + case NSAlertDefaultReturn: + return YES; + + default: + return NO; + } +} + static void check_xinitrc (void) { char *tem, buf[1024]; NSString *msg; diff --git a/xorg-server/hw/xquartz/bundle/Resources/English.lproj/Localizable.strings b/xorg-server/hw/xquartz/bundle/Resources/English.lproj/Localizable.strings Binary files differindex 03415026e..bf2089ca1 100644 --- a/xorg-server/hw/xquartz/bundle/Resources/English.lproj/Localizable.strings +++ b/xorg-server/hw/xquartz/bundle/Resources/English.lproj/Localizable.strings diff --git a/xorg-server/hw/xquartz/pbproxy/x-selection.h b/xorg-server/hw/xquartz/pbproxy/x-selection.h index 614c8b091..d4a39e58f 100644 --- a/xorg-server/hw/xquartz/pbproxy/x-selection.h +++ b/xorg-server/hw/xquartz/pbproxy/x-selection.h @@ -33,7 +33,9 @@ #include "pbproxy.h" +#define Cursor X_Cursor #include <X11/extensions/Xfixes.h> +#undef Cursor #include <AppKit/NSPasteboard.h> diff --git a/xorg-server/hw/xquartz/quartz.c b/xorg-server/hw/xquartz/quartz.c index 222a5eab0..11e5a74d7 100644 --- a/xorg-server/hw/xquartz/quartz.c +++ b/xorg-server/hw/xquartz/quartz.c @@ -82,6 +82,8 @@ Bool XQuartzIsRootless = TRUE; Bool XQuartzServerVisible = FALSE; Bool XQuartzFullscreenMenu = FALSE; +int32_t XQuartzShieldingWindowLevel = 0; + /* =========================================================================== diff --git a/xorg-server/hw/xquartz/quartz.h b/xorg-server/hw/xquartz/quartz.h index b83391db9..67a7919b2 100644 --- a/xorg-server/hw/xquartz/quartz.h +++ b/xorg-server/hw/xquartz/quartz.h @@ -124,6 +124,8 @@ extern Bool XQuartzFullscreenMenu; /* Show the menu bar (autohide) while in FS extern Bool XQuartzFullscreenDisableHotkeys; extern Bool XQuartzOptionSendsAlt; /* Alt or Mode_switch? */ +extern int32_t XQuartzShieldingWindowLevel; /* CGShieldingWindowLevel() or 0 */ + Bool QuartzAddScreen(int index, ScreenPtr pScreen); Bool QuartzSetupScreen(int index, ScreenPtr pScreen); void QuartzInitOutput(int argc,char **argv); diff --git a/xorg-server/hw/xquartz/quartzRandR.c b/xorg-server/hw/xquartz/quartzRandR.c index 64ad72d84..05641a65d 100644 --- a/xorg-server/hw/xquartz/quartzRandR.c +++ b/xorg-server/hw/xquartz/quartzRandR.c @@ -1,563 +1,570 @@ -/*
- * Quartz-specific support for the XRandR extension
- *
- * Copyright (c) 2001-2004 Greg Parker and Torrey T. Lyons,
- * 2010 Jan Hauffa.
- * 2010 Apple Inc.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Except as contained in this notice, the name(s) of the above copyright
- * holders shall not be used in advertising or otherwise to promote the sale,
- * use or other dealings in this Software without prior written authorization.
- */
-
-#include "sanitizedCarbon.h"
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#include "quartzCommon.h"
-#include "quartzRandR.h"
-#include "quartz.h"
-#include "darwin.h"
-
-#include <AvailabilityMacros.h>
-
-#include <X11/extensions/randr.h>
-#include <randrstr.h>
-#include <IOKit/graphics/IOGraphicsTypes.h>
-
-/* TODO: UGLY, find a better way!
- * We want to ignore kXquartzDisplayChanged which are generated by us
- */
-static Bool ignore_next_fake_mode_update = FALSE;
-
-#define FAKE_REFRESH_ROOTLESS 1
-#define FAKE_REFRESH_FULLSCREEN 2
-
-#define DEFAULT_REFRESH 60
-#define kDisplayModeUsableFlags (kDisplayModeValidFlag | kDisplayModeSafeFlag)
-
-#define CALLBACK_SUCCESS 0
-#define CALLBACK_CONTINUE 1
-#define CALLBACK_ERROR -1
-
-typedef int (*QuartzModeCallback)
- (ScreenPtr, QuartzModeInfoPtr, void *);
-
-#if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
-
-static long getDictLong (CFDictionaryRef dictRef, CFStringRef key) {
- long value;
-
- CFNumberRef numRef = (CFNumberRef) CFDictionaryGetValue(dictRef, key);
- if (!numRef)
- return 0;
-
- if (!CFNumberGetValue(numRef, kCFNumberLongType, &value))
- return 0;
- return value;
-}
-
-static double getDictDouble (CFDictionaryRef dictRef, CFStringRef key) {
- double value;
-
- CFNumberRef numRef = (CFNumberRef) CFDictionaryGetValue(dictRef, key);
- if (!numRef)
- return 0.0;
-
- if (!CFNumberGetValue(numRef, kCFNumberDoubleType, &value))
- return 0.0;
- return value;
-}
-
-static void QuartzRandRGetModeInfo (CFDictionaryRef modeRef,
- QuartzModeInfoPtr pMode) {
- pMode->width = (size_t) getDictLong(modeRef, kCGDisplayWidth);
- pMode->height = (size_t) getDictLong(modeRef, kCGDisplayHeight);
- pMode->refresh = (int)(getDictDouble(modeRef, kCGDisplayRefreshRate) + 0.5);
- if (pMode->refresh == 0)
- pMode->refresh = DEFAULT_REFRESH;
- pMode->ref = NULL;
- pMode->pSize = NULL;
-}
-
-static Bool QuartzRandRCopyCurrentModeInfo (CGDirectDisplayID screenId,
- QuartzModeInfoPtr pMode) {
- CFDictionaryRef curModeRef = CGDisplayCurrentMode(screenId);
- if (!curModeRef)
- return FALSE;
-
- QuartzRandRGetModeInfo(curModeRef, pMode);
- pMode->ref = (void *)curModeRef;
- CFRetain(pMode->ref);
- return TRUE;
-}
-
-static Bool QuartzRandRSetCGMode (CGDirectDisplayID screenId,
- QuartzModeInfoPtr pMode) {
- CFDictionaryRef modeRef = (CFDictionaryRef) pMode->ref;
- return (CGDisplaySwitchToMode(screenId, modeRef) == kCGErrorSuccess);
-}
-
-static Bool QuartzRandREnumerateModes (ScreenPtr pScreen,
- QuartzModeCallback callback,
- void *data) {
- CFDictionaryRef curModeRef, modeRef;
- long curBpp;
- CFArrayRef modes;
- QuartzModeInfo modeInfo;
- int i;
- BOOL retval = FALSE;
- QuartzScreenPtr pQuartzScreen = QUARTZ_PRIV(pScreen);
- CGDirectDisplayID screenId = pQuartzScreen->displayIDs[0];
-
- curModeRef = CGDisplayCurrentMode(screenId);
- if (!curModeRef)
- return FALSE;
- curBpp = getDictLong(curModeRef, kCGDisplayBitsPerPixel);
-
- modes = CGDisplayAvailableModes(screenId);
- if (!modes)
- return FALSE;
- for (i = 0; i < CFArrayGetCount(modes); i++) {
- int cb;
- modeRef = (CFDictionaryRef) CFArrayGetValueAtIndex(modes, i);
-
- /* Skip modes that are not usable on the current display or have a
- different pixel encoding than the current mode. */
- if (((unsigned long) getDictLong(modeRef, kCGDisplayIOFlags) &
- kDisplayModeUsableFlags) != kDisplayModeUsableFlags)
- continue;
- if (getDictLong(modeRef, kCGDisplayBitsPerPixel) != curBpp)
- continue;
-
- QuartzRandRGetModeInfo(modeRef, &modeInfo);
- modeInfo.ref = (void *)modeRef;
- cb = callback(pScreen, &modeInfo, data);
- if (cb == CALLBACK_CONTINUE)
- retval = TRUE;
- else if (cb == CALLBACK_SUCCESS)
- return TRUE;
- else if (cb == CALLBACK_ERROR)
- return FALSE;
- }
-
- switch(callback(pScreen, &pQuartzScreen->rootlessMode, data)) {
- case CALLBACK_SUCCESS:
- return TRUE;
- case CALLBACK_ERROR:
- return FALSE;
- case CALLBACK_CONTINUE:
- retval = TRUE;
- default:
- break;
- }
-
- switch(callback(pScreen, &pQuartzScreen->fullscreenMode, data)) {
- case CALLBACK_SUCCESS:
- return TRUE;
- case CALLBACK_ERROR:
- return FALSE;
- case CALLBACK_CONTINUE:
- retval = TRUE;
- default:
- break;
- }
-
- return retval;
-}
-
-#else /* we have the new CG APIs from Snow Leopard */
-
-static void QuartzRandRGetModeInfo (CGDisplayModeRef modeRef,
- QuartzModeInfoPtr pMode) {
- pMode->width = CGDisplayModeGetWidth(modeRef);
- pMode->height = CGDisplayModeGetHeight(modeRef);
- pMode->refresh = (int) (CGDisplayModeGetRefreshRate(modeRef) + 0.5);
- if (pMode->refresh == 0)
- pMode->refresh = DEFAULT_REFRESH;
- pMode->ref = NULL;
- pMode->pSize = NULL;
-}
-
-static Bool QuartzRandRCopyCurrentModeInfo (CGDirectDisplayID screenId,
- QuartzModeInfoPtr pMode) {
- CGDisplayModeRef curModeRef = CGDisplayCopyDisplayMode(screenId);
- if (!curModeRef)
- return FALSE;
-
- QuartzRandRGetModeInfo(curModeRef, pMode);
- pMode->ref = curModeRef;
- return TRUE;
-}
-
-static Bool QuartzRandRSetCGMode (CGDirectDisplayID screenId,
- QuartzModeInfoPtr pMode) {
- CGDisplayModeRef modeRef = (CGDisplayModeRef) pMode->ref;
- if (!modeRef)
- return FALSE;
-
- return (CGDisplaySetDisplayMode(screenId, modeRef, NULL) == kCGErrorSuccess);
-}
-
-static Bool QuartzRandREnumerateModes (ScreenPtr pScreen,
- QuartzModeCallback callback,
- void *data) {
- CGDisplayModeRef curModeRef, modeRef;
- CFStringRef curPixelEnc, pixelEnc;
- CFComparisonResult pixelEncEqual;
- CFArrayRef modes;
- QuartzModeInfo modeInfo;
- int i;
- Bool retval = FALSE;
-
- QuartzScreenPtr pQuartzScreen = QUARTZ_PRIV(pScreen);
- CGDirectDisplayID screenId = pQuartzScreen->displayIDs[0];
-
- curModeRef = CGDisplayCopyDisplayMode(screenId);
- if (!curModeRef)
- return FALSE;
- curPixelEnc = CGDisplayModeCopyPixelEncoding(curModeRef);
- CGDisplayModeRelease(curModeRef);
-
- modes = CGDisplayCopyAllDisplayModes(screenId, NULL);
- if (!modes) {
- CFRelease(curPixelEnc);
- return FALSE;
- }
- for (i = 0; i < CFArrayGetCount(modes); i++) {
- int cb;
- modeRef = (CGDisplayModeRef) CFArrayGetValueAtIndex(modes, i);
-
- /* Skip modes that are not usable on the current display or have a
- different pixel encoding than the current mode. */
- if ((CGDisplayModeGetIOFlags(modeRef) & kDisplayModeUsableFlags) !=
- kDisplayModeUsableFlags)
- continue;
- pixelEnc = CGDisplayModeCopyPixelEncoding(modeRef);
- pixelEncEqual = CFStringCompare(pixelEnc, curPixelEnc, 0);
- CFRelease(pixelEnc);
- if (pixelEncEqual != kCFCompareEqualTo)
- continue;
-
- QuartzRandRGetModeInfo(modeRef, &modeInfo);
- modeInfo.ref = modeRef;
- cb = callback(pScreen, &modeInfo, data);
- if (cb == CALLBACK_CONTINUE) {
- retval = TRUE;
- } else if (cb == CALLBACK_SUCCESS) {
- CFRelease(modes);
- CFRelease(curPixelEnc);
- return TRUE;
- } else if (cb == CALLBACK_ERROR) {
- CFRelease(modes);
- CFRelease(curPixelEnc);
- return FALSE;
- }
- }
-
- CFRelease(modes);
- CFRelease(curPixelEnc);
-
- switch(callback(pScreen, &pQuartzScreen->rootlessMode, data)) {
- case CALLBACK_SUCCESS:
- return TRUE;
- case CALLBACK_ERROR:
- return FALSE;
- case CALLBACK_CONTINUE:
- retval = TRUE;
- default:
- break;
- }
-
- switch(callback(pScreen, &pQuartzScreen->fullscreenMode, data)) {
- case CALLBACK_SUCCESS:
- return TRUE;
- case CALLBACK_ERROR:
- return FALSE;
- case CALLBACK_CONTINUE:
- retval = TRUE;
- default:
- break;
- }
-
- return retval;
-}
-
-#endif /* Snow Leopard CoreGraphics APIs */
-
-
-static Bool QuartzRandRModesEqual (QuartzModeInfoPtr pMode1,
- QuartzModeInfoPtr pMode2) {
- return (pMode1->width == pMode2->width) &&
- (pMode1->height == pMode2->height) &&
- (pMode1->refresh == pMode2->refresh);
-}
-
-static Bool QuartzRandRRegisterMode (ScreenPtr pScreen,
- QuartzModeInfoPtr pMode) {
- QuartzScreenPtr pQuartzScreen = QUARTZ_PRIV(pScreen);
- Bool isCurrentMode = QuartzRandRModesEqual(&pQuartzScreen->currentMode, pMode);
-
- /* TODO: DPI */
- pMode->pSize = RRRegisterSize(pScreen, pMode->width, pMode->height, pScreen->mmWidth, pScreen->mmHeight);
- if (pMode->pSize) {
- //DEBUG_LOG("registering: %d x %d @ %d %s\n", (int)pMode->width, (int)pMode->height, (int)pMode->refresh, isCurrentMode ? "*" : "");
- RRRegisterRate(pScreen, pMode->pSize, pMode->refresh);
-
- if (isCurrentMode)
- RRSetCurrentConfig(pScreen, RR_Rotate_0, pMode->refresh, pMode->pSize);
-
- return TRUE;
- }
- return FALSE;
-}
-
-static int QuartzRandRRegisterModeCallback (ScreenPtr pScreen,
- QuartzModeInfoPtr pMode,
- void *data __unused) {
- if(QuartzRandRRegisterMode(pScreen, pMode)) {
- return CALLBACK_CONTINUE;
- } else {
- return CALLBACK_ERROR;
- }
-}
-
-static Bool QuartzRandRSetMode(ScreenPtr pScreen, QuartzModeInfoPtr pMode, BOOL doRegister) {
- QuartzScreenPtr pQuartzScreen = QUARTZ_PRIV(pScreen);
- CGDirectDisplayID screenId = pQuartzScreen->displayIDs[0];
-
- if (pQuartzScreen->currentMode.ref && CFEqual(pMode->ref, pQuartzScreen->currentMode.ref)) {
- DEBUG_LOG("Requested RandR resolution matches current CG mode\n");
- } if (QuartzRandRSetCGMode(screenId, pMode)) {
- ignore_next_fake_mode_update = TRUE;
- } else {
- DEBUG_LOG("Error while requesting CG resolution change.\n");
- return FALSE;
- }
-
- /* If the client requested the fake rootless mode, switch to rootless.
- * Otherwise, force fullscreen mode.
- */
- QuartzSetRootless(pMode->refresh == FAKE_REFRESH_ROOTLESS);
- if (pMode->refresh != FAKE_REFRESH_ROOTLESS) {
- QuartzShowFullscreen(TRUE);
- }
-
- if(pQuartzScreen->currentMode.ref)
- CFRelease(pQuartzScreen->currentMode.ref);
- pQuartzScreen->currentMode = *pMode;
- CFRetain(pQuartzScreen->currentMode.ref);
-
- return TRUE;
-}
-
-static int QuartzRandRSetModeCallback (ScreenPtr pScreen,
- QuartzModeInfoPtr pMode,
- void *data) {
- QuartzModeInfoPtr pReqMode = (QuartzModeInfoPtr) data;
-
- if (!QuartzRandRModesEqual(pMode, pReqMode))
- return CALLBACK_CONTINUE; /* continue enumeration */
-
- DEBUG_LOG("Found a match for requested RandR resolution (%dx%d@%d).\n", (int)pMode->width, (int)pMode->height, (int)pMode->refresh);
-
- if(QuartzRandRSetMode(pScreen, pMode, FALSE))
- return CALLBACK_SUCCESS;
- else
- return CALLBACK_ERROR;
-}
-
-static Bool QuartzRandRGetInfo (ScreenPtr pScreen, Rotation *rotations) {
- QuartzScreenPtr pQuartzScreen = QUARTZ_PRIV(pScreen);
-
- *rotations = RR_Rotate_0; /* TODO: support rotation */
-
- if (pQuartzScreen->displayCount == 0)
- return FALSE;
-
- if (pQuartzScreen->displayCount > 1) {
- /* RandR operations are not well-defined for an X11 screen spanning
- multiple CG displays. Create two entries for the current virtual
- resolution including/excluding the menu bar. */
-
- QuartzRandRRegisterMode(pScreen, &pQuartzScreen->rootlessMode);
- QuartzRandRRegisterMode(pScreen, &pQuartzScreen->fullscreenMode);
- return TRUE;
- }
-
- return QuartzRandREnumerateModes(pScreen, QuartzRandRRegisterModeCallback, NULL);
-}
-
-static Bool QuartzRandRSetConfig (ScreenPtr pScreen,
- Rotation randr,
- int rate,
- RRScreenSizePtr pSize) {
- QuartzScreenPtr pQuartzScreen = QUARTZ_PRIV(pScreen);
- QuartzModeInfo reqMode;
-
- reqMode.width = pSize->width;
- reqMode.height = pSize->height;
- reqMode.refresh = rate;
-
- if (pQuartzScreen->displayCount == 0)
- return FALSE;
-
- /* Do not switch modes if requested mode is equal to current mode. */
- if (QuartzRandRModesEqual(&reqMode, &pQuartzScreen->currentMode))
- return TRUE;
-
- if (QuartzRandREnumerateModes(pScreen, QuartzRandRSetModeCallback, &reqMode)) {
- return TRUE;
- }
-
- DEBUG_LOG("Unable to find a matching config: %d x %d @ %d\n", (int)reqMode.width, (int)reqMode.height, (int)reqMode.refresh);
- return FALSE;
-}
-
-static Bool _QuartzRandRUpdateFakeModes (ScreenPtr pScreen) {
- QuartzScreenPtr pQuartzScreen = QUARTZ_PRIV(pScreen);
-
- if(pQuartzScreen->fullscreenMode.ref)
- CFRelease(pQuartzScreen->fullscreenMode.ref);
- if(pQuartzScreen->currentMode.ref)
- CFRelease(pQuartzScreen->currentMode.ref);
-
- if (!QuartzRandRCopyCurrentModeInfo(pQuartzScreen->displayIDs[0],
- &pQuartzScreen->fullscreenMode))
- return FALSE;
-
- if (pQuartzScreen->displayCount > 1) {
- pQuartzScreen->fullscreenMode.width = pScreen->width;
- pQuartzScreen->fullscreenMode.height = pScreen->height;
- if(XQuartzIsRootless)
- pQuartzScreen->fullscreenMode.height += aquaMenuBarHeight;
- }
-
- pQuartzScreen->fullscreenMode.refresh = FAKE_REFRESH_FULLSCREEN;
-
- pQuartzScreen->rootlessMode = pQuartzScreen->fullscreenMode;
- pQuartzScreen->rootlessMode.refresh = FAKE_REFRESH_ROOTLESS;
- pQuartzScreen->rootlessMode.height -= aquaMenuBarHeight;
-
- if(XQuartzIsRootless) {
- pQuartzScreen->currentMode = pQuartzScreen->rootlessMode;
- } else {
- pQuartzScreen->currentMode = pQuartzScreen->fullscreenMode;
- }
-
- /* This extra retain is for currentMode's copy.
- * fullscreen and rootless share a retain.
- */
- CFRetain(pQuartzScreen->currentMode.ref);
-
- DEBUG_LOG("rootlessMode: %d x %d\n", (int)pQuartzScreen->rootlessMode.width, (int)pQuartzScreen->rootlessMode.height);
- DEBUG_LOG("fullscreenMode: %d x %d\n", (int)pQuartzScreen->fullscreenMode.width, (int)pQuartzScreen->fullscreenMode.height);
- DEBUG_LOG("currentMode: %d x %d\n", (int)pQuartzScreen->currentMode.width, (int)pQuartzScreen->currentMode.height);
-
- return TRUE;
-}
-
-Bool QuartzRandRUpdateFakeModes (BOOL force_update) {
- ScreenPtr pScreen = screenInfo.screens[0];
-
- if(ignore_next_fake_mode_update) {
- DEBUG_LOG("Ignoring update request caused by RandR resolution change.\n");
- ignore_next_fake_mode_update = FALSE;
- return TRUE;
- }
-
- if(!_QuartzRandRUpdateFakeModes(pScreen))
- return FALSE;
-
- if(force_update)
- RRGetInfo(pScreen, TRUE);
-
- return TRUE;
-}
-
-Bool QuartzRandRInit (ScreenPtr pScreen) {
- rrScrPrivPtr pScrPriv;
-
- if (!RRScreenInit (pScreen)) return FALSE;
- if (!_QuartzRandRUpdateFakeModes (pScreen)) return FALSE;
-
- pScrPriv = rrGetScrPriv(pScreen);
- pScrPriv->rrGetInfo = QuartzRandRGetInfo;
- pScrPriv->rrSetConfig = QuartzRandRSetConfig;
- return TRUE;
-}
-
-void QuartzRandRSetFakeRootless (void) {
- int i;
-
- DEBUG_LOG("QuartzRandRSetFakeRootless called.\n");
-
- for (i=0; i < screenInfo.numScreens; i++) {
- ScreenPtr pScreen = screenInfo.screens[i];
- QuartzScreenPtr pQuartzScreen = QUARTZ_PRIV(pScreen);
-
- QuartzRandRSetMode(pScreen, &pQuartzScreen->rootlessMode, TRUE);
- }
-}
-
-void QuartzRandRSetFakeFullscreen (BOOL state) {
- int i;
-
- DEBUG_LOG("QuartzRandRSetFakeFullscreen called.\n");
-
- for (i=0; i < screenInfo.numScreens; i++) {
- ScreenPtr pScreen = screenInfo.screens[i];
- QuartzScreenPtr pQuartzScreen = QUARTZ_PRIV(pScreen);
-
- QuartzRandRSetMode(pScreen, &pQuartzScreen->fullscreenMode, TRUE);
- }
-
- QuartzShowFullscreen(state);
-}
-
-/* Toggle fullscreen mode. If "fake" fullscreen is the current mode,
- * this will just show/hide the X11 windows. If we are in a RandR fullscreen
- * mode, this will toggles us to the default fake mode and hide windows if
- * it is fullscreen
- */
-void QuartzRandRToggleFullscreen (void) {
- ScreenPtr pScreen = screenInfo.screens[0];
- QuartzScreenPtr pQuartzScreen = QUARTZ_PRIV(pScreen);
-
- if (pQuartzScreen->currentMode.ref == NULL) {
- ErrorF("Ignoring QuartzRandRToggleFullscreen because don't have a current mode set.\n");
- } else if (pQuartzScreen->currentMode.refresh == FAKE_REFRESH_ROOTLESS) {
- ErrorF("Ignoring QuartzRandRToggleFullscreen because we are in rootless mode.\n");
- } else if (pQuartzScreen->currentMode.refresh == FAKE_REFRESH_FULLSCREEN) {
- /* Legacy fullscreen mode. Hide/Show */
- QuartzShowFullscreen(!XQuartzFullscreenVisible);
- } else {
- /* RandR fullscreen mode. Return to default mode and hide if it is fullscreen. */
- if(XQuartzRootlessDefault) {
- QuartzRandRSetFakeRootless();
- } else {
- QuartzRandRSetFakeFullscreen(FALSE);
- }
- }
-}
+/* + * Quartz-specific support for the XRandR extension + * + * Copyright (c) 2001-2004 Greg Parker and Torrey T. Lyons, + * 2010 Jan Hauffa. + * 2010 Apple Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name(s) of the above copyright + * holders shall not be used in advertising or otherwise to promote the sale, + * use or other dealings in this Software without prior written authorization. + */ + +#include "sanitizedCarbon.h" + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include "quartzCommon.h" +#include "quartzRandR.h" +#include "quartz.h" +#include "darwin.h" + +#include "X11Application.h" + +#include <AvailabilityMacros.h> + +#include <X11/extensions/randr.h> +#include <randrstr.h> +#include <IOKit/graphics/IOGraphicsTypes.h> + +/* TODO: UGLY, find a better way! + * We want to ignore kXquartzDisplayChanged which are generated by us + */ +static Bool ignore_next_fake_mode_update = FALSE; + +#define FAKE_REFRESH_ROOTLESS 1 +#define FAKE_REFRESH_FULLSCREEN 2 + +#define DEFAULT_REFRESH 60 +#define kDisplayModeUsableFlags (kDisplayModeValidFlag | kDisplayModeSafeFlag) + +#define CALLBACK_SUCCESS 0 +#define CALLBACK_CONTINUE 1 +#define CALLBACK_ERROR -1 + +typedef int (*QuartzModeCallback) + (ScreenPtr, QuartzModeInfoPtr, void *); + +#if MAC_OS_X_VERSION_MIN_REQUIRED < 1060 + +static long getDictLong (CFDictionaryRef dictRef, CFStringRef key) { + long value; + + CFNumberRef numRef = (CFNumberRef) CFDictionaryGetValue(dictRef, key); + if (!numRef) + return 0; + + if (!CFNumberGetValue(numRef, kCFNumberLongType, &value)) + return 0; + return value; +} + +static double getDictDouble (CFDictionaryRef dictRef, CFStringRef key) { + double value; + + CFNumberRef numRef = (CFNumberRef) CFDictionaryGetValue(dictRef, key); + if (!numRef) + return 0.0; + + if (!CFNumberGetValue(numRef, kCFNumberDoubleType, &value)) + return 0.0; + return value; +} + +static void QuartzRandRGetModeInfo (CFDictionaryRef modeRef, + QuartzModeInfoPtr pMode) { + pMode->width = (size_t) getDictLong(modeRef, kCGDisplayWidth); + pMode->height = (size_t) getDictLong(modeRef, kCGDisplayHeight); + pMode->refresh = (int)(getDictDouble(modeRef, kCGDisplayRefreshRate) + 0.5); + if (pMode->refresh == 0) + pMode->refresh = DEFAULT_REFRESH; + pMode->ref = NULL; + pMode->pSize = NULL; +} + +static Bool QuartzRandRCopyCurrentModeInfo (CGDirectDisplayID screenId, + QuartzModeInfoPtr pMode) { + CFDictionaryRef curModeRef = CGDisplayCurrentMode(screenId); + if (!curModeRef) + return FALSE; + + QuartzRandRGetModeInfo(curModeRef, pMode); + pMode->ref = (void *)curModeRef; + CFRetain(pMode->ref); + return TRUE; +} + +static Bool QuartzRandRSetCGMode (CGDirectDisplayID screenId, + QuartzModeInfoPtr pMode) { + CFDictionaryRef modeRef = (CFDictionaryRef) pMode->ref; + return (CGDisplaySwitchToMode(screenId, modeRef) == kCGErrorSuccess); +} + +static Bool QuartzRandREnumerateModes (ScreenPtr pScreen, + QuartzModeCallback callback, + void *data) { + CFDictionaryRef curModeRef, modeRef; + long curBpp; + CFArrayRef modes; + QuartzModeInfo modeInfo; + int i; + BOOL retval = FALSE; + QuartzScreenPtr pQuartzScreen = QUARTZ_PRIV(pScreen); + CGDirectDisplayID screenId = pQuartzScreen->displayIDs[0]; + + curModeRef = CGDisplayCurrentMode(screenId); + if (!curModeRef) + return FALSE; + curBpp = getDictLong(curModeRef, kCGDisplayBitsPerPixel); + + modes = CGDisplayAvailableModes(screenId); + if (!modes) + return FALSE; + for (i = 0; i < CFArrayGetCount(modes); i++) { + int cb; + modeRef = (CFDictionaryRef) CFArrayGetValueAtIndex(modes, i); + + /* Skip modes that are not usable on the current display or have a + different pixel encoding than the current mode. */ + if (((unsigned long) getDictLong(modeRef, kCGDisplayIOFlags) & + kDisplayModeUsableFlags) != kDisplayModeUsableFlags) + continue; + if (getDictLong(modeRef, kCGDisplayBitsPerPixel) != curBpp) + continue; + + QuartzRandRGetModeInfo(modeRef, &modeInfo); + modeInfo.ref = (void *)modeRef; + cb = callback(pScreen, &modeInfo, data); + if (cb == CALLBACK_CONTINUE) + retval = TRUE; + else if (cb == CALLBACK_SUCCESS) + return TRUE; + else if (cb == CALLBACK_ERROR) + return FALSE; + } + + switch(callback(pScreen, &pQuartzScreen->rootlessMode, data)) { + case CALLBACK_SUCCESS: + return TRUE; + case CALLBACK_ERROR: + return FALSE; + case CALLBACK_CONTINUE: + retval = TRUE; + default: + break; + } + + switch(callback(pScreen, &pQuartzScreen->fullscreenMode, data)) { + case CALLBACK_SUCCESS: + return TRUE; + case CALLBACK_ERROR: + return FALSE; + case CALLBACK_CONTINUE: + retval = TRUE; + default: + break; + } + + return retval; +} + +#else /* we have the new CG APIs from Snow Leopard */ + +static void QuartzRandRGetModeInfo (CGDisplayModeRef modeRef, + QuartzModeInfoPtr pMode) { + pMode->width = CGDisplayModeGetWidth(modeRef); + pMode->height = CGDisplayModeGetHeight(modeRef); + pMode->refresh = (int) (CGDisplayModeGetRefreshRate(modeRef) + 0.5); + if (pMode->refresh == 0) + pMode->refresh = DEFAULT_REFRESH; + pMode->ref = NULL; + pMode->pSize = NULL; +} + +static Bool QuartzRandRCopyCurrentModeInfo (CGDirectDisplayID screenId, + QuartzModeInfoPtr pMode) { + CGDisplayModeRef curModeRef = CGDisplayCopyDisplayMode(screenId); + if (!curModeRef) + return FALSE; + + QuartzRandRGetModeInfo(curModeRef, pMode); + pMode->ref = curModeRef; + return TRUE; +} + +static Bool QuartzRandRSetCGMode (CGDirectDisplayID screenId, + QuartzModeInfoPtr pMode) { + CGDisplayModeRef modeRef = (CGDisplayModeRef) pMode->ref; + if (!modeRef) + return FALSE; + + return (CGDisplaySetDisplayMode(screenId, modeRef, NULL) == kCGErrorSuccess); +} + +static Bool QuartzRandREnumerateModes (ScreenPtr pScreen, + QuartzModeCallback callback, + void *data) { + CGDisplayModeRef curModeRef, modeRef; + CFStringRef curPixelEnc, pixelEnc; + CFComparisonResult pixelEncEqual; + CFArrayRef modes; + QuartzModeInfo modeInfo; + int i; + Bool retval = FALSE; + + QuartzScreenPtr pQuartzScreen = QUARTZ_PRIV(pScreen); + CGDirectDisplayID screenId = pQuartzScreen->displayIDs[0]; + + curModeRef = CGDisplayCopyDisplayMode(screenId); + if (!curModeRef) + return FALSE; + curPixelEnc = CGDisplayModeCopyPixelEncoding(curModeRef); + CGDisplayModeRelease(curModeRef); + + modes = CGDisplayCopyAllDisplayModes(screenId, NULL); + if (!modes) { + CFRelease(curPixelEnc); + return FALSE; + } + for (i = 0; i < CFArrayGetCount(modes); i++) { + int cb; + modeRef = (CGDisplayModeRef) CFArrayGetValueAtIndex(modes, i); + + /* Skip modes that are not usable on the current display or have a + different pixel encoding than the current mode. */ + if ((CGDisplayModeGetIOFlags(modeRef) & kDisplayModeUsableFlags) != + kDisplayModeUsableFlags) + continue; + pixelEnc = CGDisplayModeCopyPixelEncoding(modeRef); + pixelEncEqual = CFStringCompare(pixelEnc, curPixelEnc, 0); + CFRelease(pixelEnc); + if (pixelEncEqual != kCFCompareEqualTo) + continue; + + QuartzRandRGetModeInfo(modeRef, &modeInfo); + modeInfo.ref = modeRef; + cb = callback(pScreen, &modeInfo, data); + if (cb == CALLBACK_CONTINUE) { + retval = TRUE; + } else if (cb == CALLBACK_SUCCESS) { + CFRelease(modes); + CFRelease(curPixelEnc); + return TRUE; + } else if (cb == CALLBACK_ERROR) { + CFRelease(modes); + CFRelease(curPixelEnc); + return FALSE; + } + } + + CFRelease(modes); + CFRelease(curPixelEnc); + + switch(callback(pScreen, &pQuartzScreen->rootlessMode, data)) { + case CALLBACK_SUCCESS: + return TRUE; + case CALLBACK_ERROR: + return FALSE; + case CALLBACK_CONTINUE: + retval = TRUE; + default: + break; + } + + switch(callback(pScreen, &pQuartzScreen->fullscreenMode, data)) { + case CALLBACK_SUCCESS: + return TRUE; + case CALLBACK_ERROR: + return FALSE; + case CALLBACK_CONTINUE: + retval = TRUE; + default: + break; + } + + return retval; +} + +#endif /* Snow Leopard CoreGraphics APIs */ + + +static Bool QuartzRandRModesEqual (QuartzModeInfoPtr pMode1, + QuartzModeInfoPtr pMode2) { + return (pMode1->width == pMode2->width) && + (pMode1->height == pMode2->height) && + (pMode1->refresh == pMode2->refresh); +} + +static Bool QuartzRandRRegisterMode (ScreenPtr pScreen, + QuartzModeInfoPtr pMode) { + QuartzScreenPtr pQuartzScreen = QUARTZ_PRIV(pScreen); + Bool isCurrentMode = QuartzRandRModesEqual(&pQuartzScreen->currentMode, pMode); + + /* TODO: DPI */ + pMode->pSize = RRRegisterSize(pScreen, pMode->width, pMode->height, pScreen->mmWidth, pScreen->mmHeight); + if (pMode->pSize) { + //DEBUG_LOG("registering: %d x %d @ %d %s\n", (int)pMode->width, (int)pMode->height, (int)pMode->refresh, isCurrentMode ? "*" : ""); + RRRegisterRate(pScreen, pMode->pSize, pMode->refresh); + + if (isCurrentMode) + RRSetCurrentConfig(pScreen, RR_Rotate_0, pMode->refresh, pMode->pSize); + + return TRUE; + } + return FALSE; +} + +static int QuartzRandRRegisterModeCallback (ScreenPtr pScreen, + QuartzModeInfoPtr pMode, + void *data __unused) { + if(QuartzRandRRegisterMode(pScreen, pMode)) { + return CALLBACK_CONTINUE; + } else { + return CALLBACK_ERROR; + } +} + +static Bool QuartzRandRSetMode(ScreenPtr pScreen, QuartzModeInfoPtr pMode, BOOL doRegister) { + QuartzScreenPtr pQuartzScreen = QUARTZ_PRIV(pScreen); + CGDirectDisplayID screenId = pQuartzScreen->displayIDs[0]; + Bool captureDisplay = (pMode->refresh != FAKE_REFRESH_FULLSCREEN && pMode->refresh != FAKE_REFRESH_ROOTLESS); + + if(XQuartzShieldingWindowLevel == 0 && captureDisplay) { + if(!X11ApplicationCanEnterRandR()) + return FALSE; + CGCaptureAllDisplays(); + XQuartzShieldingWindowLevel = CGShieldingWindowLevel(); // 2147483630 + DEBUG_LOG("Display captured. ShieldWindowID: %u, Shield level: %d\n", + CGShieldingWindowID(screenId), XQuartzShieldingWindowLevel); + } + + if (pQuartzScreen->currentMode.ref && CFEqual(pMode->ref, pQuartzScreen->currentMode.ref)) { + DEBUG_LOG("Requested RandR resolution matches current CG mode\n"); + } if (QuartzRandRSetCGMode(screenId, pMode)) { + ignore_next_fake_mode_update = TRUE; + } else { + DEBUG_LOG("Error while requesting CG resolution change.\n"); + return FALSE; + } + + /* If the client requested the fake rootless mode, switch to rootless. + * Otherwise, force fullscreen mode. + */ + QuartzSetRootless(pMode->refresh == FAKE_REFRESH_ROOTLESS); + if (pMode->refresh != FAKE_REFRESH_ROOTLESS) { + QuartzShowFullscreen(TRUE); + } + + if(pQuartzScreen->currentMode.ref) + CFRelease(pQuartzScreen->currentMode.ref); + pQuartzScreen->currentMode = *pMode; + CFRetain(pQuartzScreen->currentMode.ref); + + if(XQuartzShieldingWindowLevel != 0 && !captureDisplay) { + CGReleaseAllDisplays(); + XQuartzShieldingWindowLevel = 0; + } + + return TRUE; +} + +static int QuartzRandRSetModeCallback (ScreenPtr pScreen, + QuartzModeInfoPtr pMode, + void *data) { + QuartzModeInfoPtr pReqMode = (QuartzModeInfoPtr) data; + + if (!QuartzRandRModesEqual(pMode, pReqMode)) + return CALLBACK_CONTINUE; /* continue enumeration */ + + DEBUG_LOG("Found a match for requested RandR resolution (%dx%d@%d).\n", (int)pMode->width, (int)pMode->height, (int)pMode->refresh); + + if(QuartzRandRSetMode(pScreen, pMode, FALSE)) + return CALLBACK_SUCCESS; + else + return CALLBACK_ERROR; +} + +static Bool QuartzRandRGetInfo (ScreenPtr pScreen, Rotation *rotations) { + QuartzScreenPtr pQuartzScreen = QUARTZ_PRIV(pScreen); + + *rotations = RR_Rotate_0; /* TODO: support rotation */ + + if (pQuartzScreen->displayCount == 0) + return FALSE; + + return QuartzRandREnumerateModes(pScreen, QuartzRandRRegisterModeCallback, NULL); +} + +static Bool QuartzRandRSetConfig (ScreenPtr pScreen, + Rotation randr, + int rate, + RRScreenSizePtr pSize) { + QuartzScreenPtr pQuartzScreen = QUARTZ_PRIV(pScreen); + QuartzModeInfo reqMode; + + reqMode.width = pSize->width; + reqMode.height = pSize->height; + reqMode.refresh = rate; + + if (pQuartzScreen->displayCount == 0) + return FALSE; + + /* Do not switch modes if requested mode is equal to current mode. */ + if (QuartzRandRModesEqual(&reqMode, &pQuartzScreen->currentMode)) + return TRUE; + + if (QuartzRandREnumerateModes(pScreen, QuartzRandRSetModeCallback, &reqMode)) { + return TRUE; + } + + DEBUG_LOG("Unable to find a matching config: %d x %d @ %d\n", (int)reqMode.width, (int)reqMode.height, (int)reqMode.refresh); + return FALSE; +} + +static Bool _QuartzRandRUpdateFakeModes (ScreenPtr pScreen) { + QuartzScreenPtr pQuartzScreen = QUARTZ_PRIV(pScreen); + + if(pQuartzScreen->fullscreenMode.ref) + CFRelease(pQuartzScreen->fullscreenMode.ref); + if(pQuartzScreen->currentMode.ref) + CFRelease(pQuartzScreen->currentMode.ref); + + if (!QuartzRandRCopyCurrentModeInfo(pQuartzScreen->displayIDs[0], + &pQuartzScreen->fullscreenMode)) + return FALSE; + + if (pQuartzScreen->displayCount > 1) { + pQuartzScreen->fullscreenMode.width = pScreen->width; + pQuartzScreen->fullscreenMode.height = pScreen->height; + if(XQuartzIsRootless) + pQuartzScreen->fullscreenMode.height += aquaMenuBarHeight; + } + + pQuartzScreen->fullscreenMode.refresh = FAKE_REFRESH_FULLSCREEN; + + pQuartzScreen->rootlessMode = pQuartzScreen->fullscreenMode; + pQuartzScreen->rootlessMode.refresh = FAKE_REFRESH_ROOTLESS; + pQuartzScreen->rootlessMode.height -= aquaMenuBarHeight; + + if(XQuartzIsRootless) { + pQuartzScreen->currentMode = pQuartzScreen->rootlessMode; + } else { + pQuartzScreen->currentMode = pQuartzScreen->fullscreenMode; + } + + /* This extra retain is for currentMode's copy. + * fullscreen and rootless share a retain. + */ + CFRetain(pQuartzScreen->currentMode.ref); + + DEBUG_LOG("rootlessMode: %d x %d\n", (int)pQuartzScreen->rootlessMode.width, (int)pQuartzScreen->rootlessMode.height); + DEBUG_LOG("fullscreenMode: %d x %d\n", (int)pQuartzScreen->fullscreenMode.width, (int)pQuartzScreen->fullscreenMode.height); + DEBUG_LOG("currentMode: %d x %d\n", (int)pQuartzScreen->currentMode.width, (int)pQuartzScreen->currentMode.height); + + return TRUE; +} + +Bool QuartzRandRUpdateFakeModes (BOOL force_update) { + ScreenPtr pScreen = screenInfo.screens[0]; + + if(ignore_next_fake_mode_update) { + DEBUG_LOG("Ignoring update request caused by RandR resolution change.\n"); + ignore_next_fake_mode_update = FALSE; + return TRUE; + } + + if(!_QuartzRandRUpdateFakeModes(pScreen)) + return FALSE; + + if(force_update) + RRGetInfo(pScreen, TRUE); + + return TRUE; +} + +Bool QuartzRandRInit (ScreenPtr pScreen) { + rrScrPrivPtr pScrPriv; + + if (!RRScreenInit (pScreen)) return FALSE; + if (!_QuartzRandRUpdateFakeModes (pScreen)) return FALSE; + + pScrPriv = rrGetScrPriv(pScreen); + pScrPriv->rrGetInfo = QuartzRandRGetInfo; + pScrPriv->rrSetConfig = QuartzRandRSetConfig; + return TRUE; +} + +void QuartzRandRSetFakeRootless (void) { + int i; + + DEBUG_LOG("QuartzRandRSetFakeRootless called.\n"); + + for (i=0; i < screenInfo.numScreens; i++) { + ScreenPtr pScreen = screenInfo.screens[i]; + QuartzScreenPtr pQuartzScreen = QUARTZ_PRIV(pScreen); + + QuartzRandRSetMode(pScreen, &pQuartzScreen->rootlessMode, TRUE); + } +} + +void QuartzRandRSetFakeFullscreen (BOOL state) { + int i; + + DEBUG_LOG("QuartzRandRSetFakeFullscreen called.\n"); + + for (i=0; i < screenInfo.numScreens; i++) { + ScreenPtr pScreen = screenInfo.screens[i]; + QuartzScreenPtr pQuartzScreen = QUARTZ_PRIV(pScreen); + + QuartzRandRSetMode(pScreen, &pQuartzScreen->fullscreenMode, TRUE); + } + + QuartzShowFullscreen(state); +} + +/* Toggle fullscreen mode. If "fake" fullscreen is the current mode, + * this will just show/hide the X11 windows. If we are in a RandR fullscreen + * mode, this will toggles us to the default fake mode and hide windows if + * it is fullscreen + */ +void QuartzRandRToggleFullscreen (void) { + ScreenPtr pScreen = screenInfo.screens[0]; + QuartzScreenPtr pQuartzScreen = QUARTZ_PRIV(pScreen); + + if (pQuartzScreen->currentMode.ref == NULL) { + ErrorF("Ignoring QuartzRandRToggleFullscreen because don't have a current mode set.\n"); + } else if (pQuartzScreen->currentMode.refresh == FAKE_REFRESH_ROOTLESS) { + ErrorF("Ignoring QuartzRandRToggleFullscreen because we are in rootless mode.\n"); + } else if (pQuartzScreen->currentMode.refresh == FAKE_REFRESH_FULLSCREEN) { + /* Legacy fullscreen mode. Hide/Show */ + QuartzShowFullscreen(!XQuartzFullscreenVisible); + } else { + /* RandR fullscreen mode. Return to default mode and hide if it is fullscreen. */ + if(XQuartzRootlessDefault) { + QuartzRandRSetFakeRootless(); + } else { + QuartzRandRSetFakeFullscreen(FALSE); + } + } +} diff --git a/xorg-server/hw/xquartz/xpr/xprAppleWM.c b/xorg-server/hw/xquartz/xpr/xprAppleWM.c index 59ce6375e..21e6f98fa 100644 --- a/xorg-server/hw/xquartz/xpr/xprAppleWM.c +++ b/xorg-server/hw/xquartz/xpr/xprAppleWM.c @@ -1,160 +1,162 @@ -/*
- * Xplugin rootless implementation functions for AppleWM extension
- *
- * Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
- * Copyright (c) 2003 Torrey T. Lyons. All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Except as contained in this notice, the name(s) of the above copyright
- * holders shall not be used in advertising or otherwise to promote the sale,
- * use or other dealings in this Software without prior written authorization.
- */
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#include "xpr.h"
-
-#include <X11/extensions/applewmproto.h>
-
-#include "applewmExt.h"
-#include "rootless.h"
-#include "rootlessCommon.h"
-#include <Xplugin.h>
-#include <X11/X.h>
-#include "quartz.h"
-#include "x-hash.h"
-
-static int xprSetWindowLevel(
- WindowPtr pWin,
- int level)
-{
- xp_window_id wid;
- xp_window_changes wc;
- RootlessWindowRec *winRec;
-
- // AppleWMNumWindowLevels is allowed, but is only set by the server
- // for the root window.
- if (level < 0 || level >= AppleWMNumWindowLevels) {
- return BadValue;
- }
-
- wid = x_cvt_vptr_to_uint(RootlessFrameForWindow (pWin, TRUE));
- if (wid == 0)
- return BadWindow;
-
- RootlessStopDrawing (pWin, FALSE);
- winRec = WINREC(pWin);
-
- if(!winRec)
- return BadWindow;
-
- if(XQuartzIsRootless)
- wc.window_level = normal_window_levels[level];
- else
- wc.window_level = rooted_window_levels[level];
-
- if (xp_configure_window (wid, XP_WINDOW_LEVEL, &wc) != Success) {
- return BadValue;
- }
-
- winRec->level = level;
-
- return Success;
-}
-
-#if defined(XPLUGIN_VERSION) && XPLUGIN_VERSION >= 3
-static int xprAttachTransient(WindowPtr pWinChild, WindowPtr pWinParent) {
- xp_window_id child_wid, parent_wid;
- xp_window_changes wc;
-
- child_wid = x_cvt_vptr_to_uint(RootlessFrameForWindow(pWinChild, TRUE));
- if (child_wid == 0)
- return BadWindow;
-
- if(pWinParent) {
- parent_wid = x_cvt_vptr_to_uint(RootlessFrameForWindow(pWinParent, TRUE));
- if (parent_wid == 0)
- return BadWindow;
- } else {
- parent_wid = 0;
- }
-
- wc.transient_for = parent_wid;
-
- RootlessStopDrawing (pWinChild, FALSE);
-
- if (xp_configure_window(child_wid, XP_ATTACH_TRANSIENT, &wc) != Success) {
- return BadValue;
- }
-
- return Success;
-}
-#endif
-
-static int xprFrameDraw(
- WindowPtr pWin,
- int class,
- unsigned int attr,
- const BoxRec *outer,
- const BoxRec *inner,
- unsigned int title_len,
- const unsigned char *title_bytes)
-{
- xp_window_id wid;
-
- wid = x_cvt_vptr_to_uint(RootlessFrameForWindow (pWin, FALSE));
- if (wid == 0)
- return BadWindow;
-
- if (xp_frame_draw (wid, class, attr, outer, inner,
- title_len, title_bytes) != Success)
- {
- return BadValue;
- }
-
- return Success;
-}
-
-static AppleWMProcsRec xprAppleWMProcs = {
- xp_disable_update,
- xp_reenable_update,
- xprSetWindowLevel,
- xp_frame_get_rect,
- xp_frame_hit_test,
- xprFrameDraw,
-#if defined(XPLUGIN_VERSION) && XPLUGIN_VERSION >= 3
- xp_set_dock_proxy,
- xprAttachTransient
-#elif defined(XPLUGIN_VERSION) && XPLUGIN_VERSION >= 2
- xp_set_dock_proxy,
- NULL
-#else
- NULL,
- NULL
-#endif
-};
-
-
-void xprAppleWMInit(void)
-{
- AppleWMExtensionInit(&xprAppleWMProcs);
-}
+/* + * Xplugin rootless implementation functions for AppleWM extension + * + * Copyright (c) 2002 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2003 Torrey T. Lyons. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name(s) of the above copyright + * holders shall not be used in advertising or otherwise to promote the sale, + * use or other dealings in this Software without prior written authorization. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include "xpr.h" + +#include <X11/extensions/applewmproto.h> + +#include "applewmExt.h" +#include "rootless.h" +#include "rootlessCommon.h" +#include <Xplugin.h> +#include <X11/X.h> +#include "quartz.h" +#include "x-hash.h" + +static int xprSetWindowLevel( + WindowPtr pWin, + int level) +{ + xp_window_id wid; + xp_window_changes wc; + RootlessWindowRec *winRec; + + // AppleWMNumWindowLevels is allowed, but is only set by the server + // for the root window. + if (level < 0 || level >= AppleWMNumWindowLevels) { + return BadValue; + } + + wid = x_cvt_vptr_to_uint(RootlessFrameForWindow (pWin, TRUE)); + if (wid == 0) + return BadWindow; + + RootlessStopDrawing (pWin, FALSE); + winRec = WINREC(pWin); + + if(!winRec) + return BadWindow; + + if(XQuartzIsRootless) + wc.window_level = normal_window_levels[level]; + else if(XQuartzShieldingWindowLevel) + wc.window_level = XQuartzShieldingWindowLevel + 1; + else + wc.window_level = rooted_window_levels[level]; + + if (xp_configure_window (wid, XP_WINDOW_LEVEL, &wc) != Success) { + return BadValue; + } + + winRec->level = level; + + return Success; +} + +#if defined(XPLUGIN_VERSION) && XPLUGIN_VERSION >= 3 +static int xprAttachTransient(WindowPtr pWinChild, WindowPtr pWinParent) { + xp_window_id child_wid, parent_wid; + xp_window_changes wc; + + child_wid = x_cvt_vptr_to_uint(RootlessFrameForWindow(pWinChild, TRUE)); + if (child_wid == 0) + return BadWindow; + + if(pWinParent) { + parent_wid = x_cvt_vptr_to_uint(RootlessFrameForWindow(pWinParent, TRUE)); + if (parent_wid == 0) + return BadWindow; + } else { + parent_wid = 0; + } + + wc.transient_for = parent_wid; + + RootlessStopDrawing (pWinChild, FALSE); + + if (xp_configure_window(child_wid, XP_ATTACH_TRANSIENT, &wc) != Success) { + return BadValue; + } + + return Success; +} +#endif + +static int xprFrameDraw( + WindowPtr pWin, + int class, + unsigned int attr, + const BoxRec *outer, + const BoxRec *inner, + unsigned int title_len, + const unsigned char *title_bytes) +{ + xp_window_id wid; + + wid = x_cvt_vptr_to_uint(RootlessFrameForWindow (pWin, FALSE)); + if (wid == 0) + return BadWindow; + + if (xp_frame_draw (wid, class, attr, outer, inner, + title_len, title_bytes) != Success) + { + return BadValue; + } + + return Success; +} + +static AppleWMProcsRec xprAppleWMProcs = { + xp_disable_update, + xp_reenable_update, + xprSetWindowLevel, + xp_frame_get_rect, + xp_frame_hit_test, + xprFrameDraw, +#if defined(XPLUGIN_VERSION) && XPLUGIN_VERSION >= 3 + xp_set_dock_proxy, + xprAttachTransient +#elif defined(XPLUGIN_VERSION) && XPLUGIN_VERSION >= 2 + xp_set_dock_proxy, + NULL +#else + NULL, + NULL +#endif +}; + + +void xprAppleWMInit(void) +{ + AppleWMExtensionInit(&xprAppleWMProcs); +} diff --git a/xorg-server/hw/xquartz/xpr/xprFrame.c b/xorg-server/hw/xquartz/xpr/xprFrame.c index fecae5a1b..15598e942 100644 --- a/xorg-server/hw/xquartz/xpr/xprFrame.c +++ b/xorg-server/hw/xquartz/xpr/xprFrame.c @@ -1,642 +1,646 @@ -/*
- * Xplugin rootless implementation frame functions
- *
- * Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
- * Copyright (c) 2003 Torrey T. Lyons. All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Except as contained in this notice, the name(s) of the above copyright
- * holders shall not be used in advertising or otherwise to promote the sale,
- * use or other dealings in this Software without prior written authorization.
- */
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#include "xpr.h"
-#include "rootlessCommon.h"
-#include <Xplugin.h>
-#include "x-hash.h"
-#include "x-list.h"
-#include "applewmExt.h"
-
-#include "propertyst.h"
-#include "dix.h"
-#include <X11/Xatom.h>
-#include "windowstr.h"
-#include "quartz.h"
-
-#include "threadSafety.h"
-
-#include <pthread.h>
-
-#define DEFINE_ATOM_HELPER(func,atom_name) \
-static Atom func (void) { \
- static int generation; \
- static Atom atom; \
- if (generation != serverGeneration) { \
- generation = serverGeneration; \
- atom = MakeAtom (atom_name, strlen (atom_name), TRUE); \
- } \
- return atom; \
-}
-
-DEFINE_ATOM_HELPER(xa_native_window_id, "_NATIVE_WINDOW_ID")
-
-/* Maps xp_window_id -> RootlessWindowRec */
-static x_hash_table *window_hash;
-static pthread_mutex_t window_hash_mutex;
-
-/* Prototypes for static functions */
-static Bool xprCreateFrame(RootlessWindowPtr pFrame, ScreenPtr pScreen,
- int newX, int newY, RegionPtr pShape);
-static void xprDestroyFrame(RootlessFrameID wid);
-static void xprMoveFrame(RootlessFrameID wid, ScreenPtr pScreen, int newX, int newY);
-static void xprResizeFrame(RootlessFrameID wid, ScreenPtr pScreen,
- int newX, int newY, unsigned int newW, unsigned int newH,
- unsigned int gravity);
-static void xprRestackFrame(RootlessFrameID wid, RootlessFrameID nextWid);
-static void xprReshapeFrame(RootlessFrameID wid, RegionPtr pShape);
-static void xprUnmapFrame(RootlessFrameID wid);
-static void xprStartDrawing(RootlessFrameID wid, char **pixelData, int *bytesPerRow);
-static void xprStopDrawing(RootlessFrameID wid, Bool flush);
-static void xprUpdateRegion(RootlessFrameID wid, RegionPtr pDamage);
-static void xprDamageRects(RootlessFrameID wid, int nrects, const BoxRec *rects,
- int shift_x, int shift_y);
-static void xprSwitchWindow(RootlessWindowPtr pFrame, WindowPtr oldWin);
-static Bool xprDoReorderWindow(RootlessWindowPtr pFrame);
-static void xprHideWindow(RootlessFrameID wid);
-static void xprUpdateColormap(RootlessFrameID wid, ScreenPtr pScreen);
-static void xprCopyWindow(RootlessFrameID wid, int dstNrects, const BoxRec *dstRects,
- int dx, int dy);
-
-
-static inline xp_error
-xprConfigureWindow(xp_window_id id, unsigned int mask,
- const xp_window_changes *values)
-{
- TA_SERVER();
-
- return xp_configure_window(id, mask, values);
-}
-
-
-static void
-xprSetNativeProperty(RootlessWindowPtr pFrame)
-{
- xp_error err;
- unsigned int native_id;
- long data;
-
- TA_SERVER();
-
- err = xp_get_native_window(x_cvt_vptr_to_uint(pFrame->wid), &native_id);
- if (err == Success)
- {
- /* FIXME: move this to AppleWM extension */
-
- data = native_id;
- dixChangeWindowProperty(serverClient, pFrame->win, xa_native_window_id(),
- XA_INTEGER, 32, PropModeReplace, 1, &data, TRUE);
- }
-}
-
-static xp_error
-xprColormapCallback(void *data, int first_color, int n_colors, uint32_t *colors)
-{
- return (RootlessResolveColormap (data, first_color, n_colors, colors) ? XP_Success : XP_BadMatch);
-}
-
-/*
- * Create and display a new frame.
- */
-static Bool
-xprCreateFrame(RootlessWindowPtr pFrame, ScreenPtr pScreen,
- int newX, int newY, RegionPtr pShape)
-{
- WindowPtr pWin = pFrame->win;
- xp_window_changes wc;
- unsigned int mask = 0;
- xp_error err;
-
- TA_SERVER();
-
- wc.x = newX;
- wc.y = newY;
- wc.width = pFrame->width;
- wc.height = pFrame->height;
- wc.bit_gravity = XP_GRAVITY_NONE;
- mask |= XP_BOUNDS;
-
- if (pWin->drawable.depth == 8)
- {
- wc.depth = XP_DEPTH_INDEX8;
- wc.colormap = xprColormapCallback;
- wc.colormap_data = pScreen;
- mask |= XP_COLORMAP;
- }
- else if (pWin->drawable.depth == 15)
- wc.depth = XP_DEPTH_RGB555;
- else if (pWin->drawable.depth == 24)
- wc.depth = XP_DEPTH_ARGB8888;
- else
- wc.depth = XP_DEPTH_NIL;
- mask |= XP_DEPTH;
-
- if (pShape != NULL)
- {
- wc.shape_nrects = RegionNumRects(pShape);
- wc.shape_rects = RegionRects(pShape);
- wc.shape_tx = wc.shape_ty = 0;
- mask |= XP_SHAPE;
- }
-
- pFrame->level = !IsRoot (pWin) ? AppleWMWindowLevelNormal : AppleWMNumWindowLevels;
-
- if(XQuartzIsRootless)
- wc.window_level = normal_window_levels[pFrame->level];
- else
- wc.window_level = rooted_window_levels[pFrame->level];
- mask |= XP_WINDOW_LEVEL;
-
- err = xp_create_window(mask, &wc, (xp_window_id *) &pFrame->wid);
-
- if (err != Success)
- {
- return FALSE;
- }
-
- if (window_hash == NULL)
- {
- window_hash = x_hash_table_new(NULL, NULL, NULL, NULL);
- pthread_mutex_init(&window_hash_mutex, NULL);
- }
-
- pthread_mutex_lock(&window_hash_mutex);
- x_hash_table_insert(window_hash, pFrame->wid, pFrame);
- pthread_mutex_unlock(&window_hash_mutex);
-
- xprSetNativeProperty(pFrame);
-
- return TRUE;
-}
-
-
-/*
- * Destroy a frame.
- */
-static void
-xprDestroyFrame(RootlessFrameID wid)
-{
- xp_error err;
- TA_SERVER();
-
- pthread_mutex_lock(&window_hash_mutex);
- x_hash_table_remove(window_hash, wid);
- pthread_mutex_unlock(&window_hash_mutex);
-
- err = xp_destroy_window(x_cvt_vptr_to_uint(wid));
- if (err != Success)
- FatalError("Could not destroy window %i.", (int)x_cvt_vptr_to_uint(wid));
-}
-
-
-/*
- * Move a frame on screen.
- */
-static void
-xprMoveFrame(RootlessFrameID wid, ScreenPtr pScreen, int newX, int newY)
-{
- xp_window_changes wc;
-
- TA_SERVER();
-
- wc.x = newX;
- wc.y = newY;
- // ErrorF("xprMoveFrame(%d, %p, %d, %d)\n", wid, pScreen, newX, newY);
- xprConfigureWindow(x_cvt_vptr_to_uint(wid), XP_ORIGIN, &wc);
-}
-
-
-/*
- * Resize and move a frame.
- */
-static void
-xprResizeFrame(RootlessFrameID wid, ScreenPtr pScreen,
- int newX, int newY, unsigned int newW, unsigned int newH,
- unsigned int gravity)
-{
- xp_window_changes wc;
-
- TA_SERVER();
-
- wc.x = newX;
- wc.y = newY;
- wc.width = newW;
- wc.height = newH;
- wc.bit_gravity = gravity;
-
- /* It's unlikely that being async will save us anything here.
- But it can't hurt. */
-
- xprConfigureWindow(x_cvt_vptr_to_uint(wid), XP_BOUNDS, &wc);
-}
-
-
-/*
- * Change frame stacking.
- */
-static void xprRestackFrame(RootlessFrameID wid, RootlessFrameID nextWid) {
- xp_window_changes wc;
- unsigned int mask = XP_STACKING;
-
- TA_SERVER();
-
- /* Stack frame below nextWid it if it exists, or raise
- frame above everything otherwise. */
-
- if(nextWid == NULL) {
- wc.stack_mode = XP_MAPPED_ABOVE;
- wc.sibling = 0;
- } else {
- wc.stack_mode = XP_MAPPED_BELOW;
- wc.sibling = x_cvt_vptr_to_uint(nextWid);
- }
-
- if(window_hash) {
- RootlessWindowRec *winRec = x_hash_table_lookup(window_hash, wid, NULL);
-
- if(winRec) {
- if(XQuartzIsRootless)
- wc.window_level = normal_window_levels[winRec->level];
- else
- wc.window_level = rooted_window_levels[winRec->level];
- mask |= XP_WINDOW_LEVEL;
- }
- }
-
- xprConfigureWindow(x_cvt_vptr_to_uint(wid), mask, &wc);
-}
-
-
-/*
- * Change the frame's shape.
- */
-static void
-xprReshapeFrame(RootlessFrameID wid, RegionPtr pShape)
-{
- xp_window_changes wc;
-
- TA_SERVER();
-
- if (pShape != NULL)
- {
- wc.shape_nrects = RegionNumRects(pShape);
- wc.shape_rects = RegionRects(pShape);
- }
- else
- {
- wc.shape_nrects = -1;
- wc.shape_rects = NULL;
- }
-
- wc.shape_tx = wc.shape_ty = 0;
-
- xprConfigureWindow(x_cvt_vptr_to_uint(wid), XP_SHAPE, &wc);
-}
-
-
-/*
- * Unmap a frame.
- */
-static void
-xprUnmapFrame(RootlessFrameID wid)
-{
- xp_window_changes wc;
-
- TA_SERVER();
-
- wc.stack_mode = XP_UNMAPPED;
- wc.sibling = 0;
-
- xprConfigureWindow(x_cvt_vptr_to_uint(wid), XP_STACKING, &wc);
-}
-
-
-/*
- * Start drawing to a frame.
- * Prepare for direct access to its backing buffer.
- */
-static void
-xprStartDrawing(RootlessFrameID wid, char **pixelData, int *bytesPerRow)
-{
- void *data[2];
- unsigned int rowbytes[2];
- xp_error err;
-
- TA_SERVER();
-
- err = xp_lock_window(x_cvt_vptr_to_uint(wid), NULL, NULL, data, rowbytes, NULL);
- if (err != Success)
- FatalError("Could not lock window %i for drawing.", (int)x_cvt_vptr_to_uint(wid));
-
- *pixelData = data[0];
- *bytesPerRow = rowbytes[0];
-}
-
-
-/*
- * Stop drawing to a frame.
- */
-static void
-xprStopDrawing(RootlessFrameID wid, Bool flush)
-{
- xp_error err;
- TA_SERVER();
-
- err = xp_unlock_window(x_cvt_vptr_to_uint(wid), flush);
- if(err != Success)
- FatalError("Could not unlock window %i after drawing.", (int)x_cvt_vptr_to_uint(wid));
-}
-
-
-/*
- * Flush drawing updates to the screen.
- */
-static void
-xprUpdateRegion(RootlessFrameID wid, RegionPtr pDamage)
-{
- TA_SERVER();
-
- xp_flush_window(x_cvt_vptr_to_uint(wid));
-}
-
-
-/*
- * Mark damaged rectangles as requiring redisplay to screen.
- */
-static void
-xprDamageRects(RootlessFrameID wid, int nrects, const BoxRec *rects,
- int shift_x, int shift_y)
-{
- TA_SERVER();
-
- xp_mark_window(x_cvt_vptr_to_uint(wid), nrects, rects, shift_x, shift_y);
-}
-
-
-/*
- * Called after the window associated with a frame has been switched
- * to a new top-level parent.
- */
-static void
-xprSwitchWindow(RootlessWindowPtr pFrame, WindowPtr oldWin)
-{
- DeleteProperty(serverClient, oldWin, xa_native_window_id());
-
- TA_SERVER();
-
- xprSetNativeProperty(pFrame);
-}
-
-
-/*
- * Called to check if the frame should be reordered when it is restacked.
- */
-static Bool xprDoReorderWindow(RootlessWindowPtr pFrame)
-{
- WindowPtr pWin = pFrame->win;
-
- TA_SERVER();
-
- return AppleWMDoReorderWindow(pWin);
-}
-
-
-/*
- * Copy area in frame to another part of frame.
- * Used to accelerate scrolling.
- */
-static void
-xprCopyWindow(RootlessFrameID wid, int dstNrects, const BoxRec *dstRects,
- int dx, int dy)
-{
- TA_SERVER();
-
- xp_copy_window(x_cvt_vptr_to_uint(wid), x_cvt_vptr_to_uint(wid),
- dstNrects, dstRects, dx, dy);
-}
-
-
-static RootlessFrameProcsRec xprRootlessProcs = {
- xprCreateFrame,
- xprDestroyFrame,
- xprMoveFrame,
- xprResizeFrame,
- xprRestackFrame,
- xprReshapeFrame,
- xprUnmapFrame,
- xprStartDrawing,
- xprStopDrawing,
- xprUpdateRegion,
- xprDamageRects,
- xprSwitchWindow,
- xprDoReorderWindow,
- xprHideWindow,
- xprUpdateColormap,
- xp_copy_bytes,
- xprCopyWindow
-};
-
-
-/*
- * Initialize XPR implementation
- */
-Bool
-xprInit(ScreenPtr pScreen)
-{
- RootlessInit(pScreen, &xprRootlessProcs);
-
- TA_SERVER();
-
- rootless_CopyBytes_threshold = xp_copy_bytes_threshold;
- rootless_CopyWindow_threshold = xp_scroll_area_threshold;
-
- return TRUE;
-}
-
-
-/*
- * Given the id of a physical window, try to find the top-level (or root)
- * X window that it represents.
- */
-WindowPtr
-xprGetXWindow(xp_window_id wid)
-{
- RootlessWindowRec *winRec;
-
- if (window_hash == NULL)
- return NULL;
-
- winRec = x_hash_table_lookup(window_hash, x_cvt_uint_to_vptr(wid), NULL);
-
- return winRec != NULL ? winRec->win : NULL;
-}
-
-#ifdef UNUSED_CODE
-/*
- * Given the id of a physical window, try to find the top-level (or root)
- * X window that it represents.
- */
-WindowPtr
-xprGetXWindowFromAppKit(int windowNumber)
-{
- RootlessWindowRec *winRec;
- Bool ret;
- xp_window_id wid;
-
- if (window_hash == NULL)
- return FALSE;
-
- /* need to lock, since this function can be called by any thread */
-
- pthread_mutex_lock(&window_hash_mutex);
-
- if (xp_lookup_native_window(windowNumber, &wid))
- ret = xprGetXWindow(wid) != NULL;
- else
- ret = FALSE;
-
- pthread_mutex_unlock(&window_hash_mutex);
-
- if (!ret) return NULL;
- winRec = x_hash_table_lookup(window_hash, x_cvt_uint_to_vptr(wid), NULL);
-
- return winRec != NULL ? winRec->win : NULL;
-}
-#endif
-
-/*
- * The windowNumber is an AppKit window number. Returns TRUE if xpr is
- * displaying a window with that number.
- */
-Bool
-xprIsX11Window(void *nsWindow, int windowNumber)
-{
- Bool ret;
- xp_window_id wid;
-
- if (window_hash == NULL)
- return FALSE;
-
- /* need to lock, since this function can be called by any thread */
-
- pthread_mutex_lock(&window_hash_mutex);
-
- if (xp_lookup_native_window(windowNumber, &wid))
- ret = xprGetXWindow(wid) != NULL;
- else
- ret = FALSE;
-
- pthread_mutex_unlock(&window_hash_mutex);
-
- return ret;
-}
-
-
-/*
- * xprHideWindows
- * Hide or unhide all top level windows. This is called for application hide/
- * unhide events if the window manager is not Apple-WM aware. Xplugin windows
- * do not hide or unhide themselves.
- */
-void
-xprHideWindows(Bool hide)
-{
- int screen;
- WindowPtr pRoot, pWin;
-
- TA_SERVER();
-
- for (screen = 0; screen < screenInfo.numScreens; screen++) {
- RootlessFrameID prevWid = NULL;
- pRoot = screenInfo.screens[screen]->root;
-
- for (pWin = pRoot->firstChild; pWin; pWin = pWin->nextSib) {
- RootlessWindowRec *winRec = WINREC(pWin);
-
- if (winRec != NULL) {
- if (hide) {
- xprUnmapFrame(winRec->wid);
- } else {
- BoxRec box;
-
- xprRestackFrame(winRec->wid, prevWid);
- prevWid = winRec->wid;
-
- box.x1 = 0;
- box.y1 = 0;
- box.x2 = winRec->width;
- box.y2 = winRec->height;
-
- xprDamageRects(winRec->wid, 1, &box, 0, 0);
- RootlessQueueRedisplay(screenInfo.screens[screen]);
- }
- }
- }
- }
-}
-
-// XXX: identical to x_cvt_vptr_to_uint ?
-#define MAKE_WINDOW_ID(x) ((xp_window_id)((size_t)(x)))
-
-Bool no_configure_window;
-
-static inline int
-configure_window (xp_window_id id, unsigned int mask,
- const xp_window_changes *values)
-{
- if (!no_configure_window)
- return xp_configure_window (id, mask, values);
- else
- return XP_Success;
-}
-
-
-static
-void xprUpdateColormap(RootlessFrameID wid, ScreenPtr pScreen)
-{
- /* This is how we tell xp that the colormap may have changed. */
- xp_window_changes wc;
- wc.colormap = xprColormapCallback;
- wc.colormap_data = pScreen;
-
- configure_window(MAKE_WINDOW_ID(wid), XP_COLORMAP, &wc);
-}
-
-static
-void xprHideWindow(RootlessFrameID wid)
-{
- xp_window_changes wc;
- wc.stack_mode = XP_UNMAPPED;
- wc.sibling = 0;
- configure_window(MAKE_WINDOW_ID(wid), XP_STACKING, &wc);
-}
+/* + * Xplugin rootless implementation frame functions + * + * Copyright (c) 2002 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2003 Torrey T. Lyons. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name(s) of the above copyright + * holders shall not be used in advertising or otherwise to promote the sale, + * use or other dealings in this Software without prior written authorization. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include "xpr.h" +#include "rootlessCommon.h" +#include <Xplugin.h> +#include "x-hash.h" +#include "x-list.h" +#include "applewmExt.h" + +#include "propertyst.h" +#include "dix.h" +#include <X11/Xatom.h> +#include "windowstr.h" +#include "quartz.h" + +#include "threadSafety.h" + +#include <pthread.h> + +#define DEFINE_ATOM_HELPER(func,atom_name) \ +static Atom func (void) { \ + static int generation; \ + static Atom atom; \ + if (generation != serverGeneration) { \ + generation = serverGeneration; \ + atom = MakeAtom (atom_name, strlen (atom_name), TRUE); \ + } \ + return atom; \ +} + +DEFINE_ATOM_HELPER(xa_native_window_id, "_NATIVE_WINDOW_ID") + +/* Maps xp_window_id -> RootlessWindowRec */ +static x_hash_table *window_hash; +static pthread_mutex_t window_hash_mutex; + +/* Prototypes for static functions */ +static Bool xprCreateFrame(RootlessWindowPtr pFrame, ScreenPtr pScreen, + int newX, int newY, RegionPtr pShape); +static void xprDestroyFrame(RootlessFrameID wid); +static void xprMoveFrame(RootlessFrameID wid, ScreenPtr pScreen, int newX, int newY); +static void xprResizeFrame(RootlessFrameID wid, ScreenPtr pScreen, + int newX, int newY, unsigned int newW, unsigned int newH, + unsigned int gravity); +static void xprRestackFrame(RootlessFrameID wid, RootlessFrameID nextWid); +static void xprReshapeFrame(RootlessFrameID wid, RegionPtr pShape); +static void xprUnmapFrame(RootlessFrameID wid); +static void xprStartDrawing(RootlessFrameID wid, char **pixelData, int *bytesPerRow); +static void xprStopDrawing(RootlessFrameID wid, Bool flush); +static void xprUpdateRegion(RootlessFrameID wid, RegionPtr pDamage); +static void xprDamageRects(RootlessFrameID wid, int nrects, const BoxRec *rects, + int shift_x, int shift_y); +static void xprSwitchWindow(RootlessWindowPtr pFrame, WindowPtr oldWin); +static Bool xprDoReorderWindow(RootlessWindowPtr pFrame); +static void xprHideWindow(RootlessFrameID wid); +static void xprUpdateColormap(RootlessFrameID wid, ScreenPtr pScreen); +static void xprCopyWindow(RootlessFrameID wid, int dstNrects, const BoxRec *dstRects, + int dx, int dy); + + +static inline xp_error +xprConfigureWindow(xp_window_id id, unsigned int mask, + const xp_window_changes *values) +{ + TA_SERVER(); + + return xp_configure_window(id, mask, values); +} + + +static void +xprSetNativeProperty(RootlessWindowPtr pFrame) +{ + xp_error err; + unsigned int native_id; + long data; + + TA_SERVER(); + + err = xp_get_native_window(x_cvt_vptr_to_uint(pFrame->wid), &native_id); + if (err == Success) + { + /* FIXME: move this to AppleWM extension */ + + data = native_id; + dixChangeWindowProperty(serverClient, pFrame->win, xa_native_window_id(), + XA_INTEGER, 32, PropModeReplace, 1, &data, TRUE); + } +} + +static xp_error +xprColormapCallback(void *data, int first_color, int n_colors, uint32_t *colors) +{ + return (RootlessResolveColormap (data, first_color, n_colors, colors) ? XP_Success : XP_BadMatch); +} + +/* + * Create and display a new frame. + */ +static Bool +xprCreateFrame(RootlessWindowPtr pFrame, ScreenPtr pScreen, + int newX, int newY, RegionPtr pShape) +{ + WindowPtr pWin = pFrame->win; + xp_window_changes wc; + unsigned int mask = 0; + xp_error err; + + TA_SERVER(); + + wc.x = newX; + wc.y = newY; + wc.width = pFrame->width; + wc.height = pFrame->height; + wc.bit_gravity = XP_GRAVITY_NONE; + mask |= XP_BOUNDS; + + if (pWin->drawable.depth == 8) + { + wc.depth = XP_DEPTH_INDEX8; + wc.colormap = xprColormapCallback; + wc.colormap_data = pScreen; + mask |= XP_COLORMAP; + } + else if (pWin->drawable.depth == 15) + wc.depth = XP_DEPTH_RGB555; + else if (pWin->drawable.depth == 24) + wc.depth = XP_DEPTH_ARGB8888; + else + wc.depth = XP_DEPTH_NIL; + mask |= XP_DEPTH; + + if (pShape != NULL) + { + wc.shape_nrects = RegionNumRects(pShape); + wc.shape_rects = RegionRects(pShape); + wc.shape_tx = wc.shape_ty = 0; + mask |= XP_SHAPE; + } + + pFrame->level = !IsRoot (pWin) ? AppleWMWindowLevelNormal : AppleWMNumWindowLevels; + + if(XQuartzIsRootless) + wc.window_level = normal_window_levels[pFrame->level]; + else if(XQuartzShieldingWindowLevel) + wc.window_level = XQuartzShieldingWindowLevel + 1; + else + wc.window_level = rooted_window_levels[pFrame->level]; + mask |= XP_WINDOW_LEVEL; + + err = xp_create_window(mask, &wc, (xp_window_id *) &pFrame->wid); + + if (err != Success) + { + return FALSE; + } + + if (window_hash == NULL) + { + window_hash = x_hash_table_new(NULL, NULL, NULL, NULL); + pthread_mutex_init(&window_hash_mutex, NULL); + } + + pthread_mutex_lock(&window_hash_mutex); + x_hash_table_insert(window_hash, pFrame->wid, pFrame); + pthread_mutex_unlock(&window_hash_mutex); + + xprSetNativeProperty(pFrame); + + return TRUE; +} + + +/* + * Destroy a frame. + */ +static void +xprDestroyFrame(RootlessFrameID wid) +{ + xp_error err; + TA_SERVER(); + + pthread_mutex_lock(&window_hash_mutex); + x_hash_table_remove(window_hash, wid); + pthread_mutex_unlock(&window_hash_mutex); + + err = xp_destroy_window(x_cvt_vptr_to_uint(wid)); + if (err != Success) + FatalError("Could not destroy window %i.", (int)x_cvt_vptr_to_uint(wid)); +} + + +/* + * Move a frame on screen. + */ +static void +xprMoveFrame(RootlessFrameID wid, ScreenPtr pScreen, int newX, int newY) +{ + xp_window_changes wc; + + TA_SERVER(); + + wc.x = newX; + wc.y = newY; + // ErrorF("xprMoveFrame(%d, %p, %d, %d)\n", wid, pScreen, newX, newY); + xprConfigureWindow(x_cvt_vptr_to_uint(wid), XP_ORIGIN, &wc); +} + + +/* + * Resize and move a frame. + */ +static void +xprResizeFrame(RootlessFrameID wid, ScreenPtr pScreen, + int newX, int newY, unsigned int newW, unsigned int newH, + unsigned int gravity) +{ + xp_window_changes wc; + + TA_SERVER(); + + wc.x = newX; + wc.y = newY; + wc.width = newW; + wc.height = newH; + wc.bit_gravity = gravity; + + /* It's unlikely that being async will save us anything here. + But it can't hurt. */ + + xprConfigureWindow(x_cvt_vptr_to_uint(wid), XP_BOUNDS, &wc); +} + + +/* + * Change frame stacking. + */ +static void xprRestackFrame(RootlessFrameID wid, RootlessFrameID nextWid) { + xp_window_changes wc; + unsigned int mask = XP_STACKING; + + TA_SERVER(); + + /* Stack frame below nextWid it if it exists, or raise + frame above everything otherwise. */ + + if(nextWid == NULL) { + wc.stack_mode = XP_MAPPED_ABOVE; + wc.sibling = 0; + } else { + wc.stack_mode = XP_MAPPED_BELOW; + wc.sibling = x_cvt_vptr_to_uint(nextWid); + } + + if(window_hash) { + RootlessWindowRec *winRec = x_hash_table_lookup(window_hash, wid, NULL); + + if(winRec) { + if(XQuartzIsRootless) + wc.window_level = normal_window_levels[winRec->level]; + else if(XQuartzShieldingWindowLevel) + wc.window_level = XQuartzShieldingWindowLevel + 1; + else + wc.window_level = rooted_window_levels[winRec->level]; + mask |= XP_WINDOW_LEVEL; + } + } + + xprConfigureWindow(x_cvt_vptr_to_uint(wid), mask, &wc); +} + + +/* + * Change the frame's shape. + */ +static void +xprReshapeFrame(RootlessFrameID wid, RegionPtr pShape) +{ + xp_window_changes wc; + + TA_SERVER(); + + if (pShape != NULL) + { + wc.shape_nrects = RegionNumRects(pShape); + wc.shape_rects = RegionRects(pShape); + } + else + { + wc.shape_nrects = -1; + wc.shape_rects = NULL; + } + + wc.shape_tx = wc.shape_ty = 0; + + xprConfigureWindow(x_cvt_vptr_to_uint(wid), XP_SHAPE, &wc); +} + + +/* + * Unmap a frame. + */ +static void +xprUnmapFrame(RootlessFrameID wid) +{ + xp_window_changes wc; + + TA_SERVER(); + + wc.stack_mode = XP_UNMAPPED; + wc.sibling = 0; + + xprConfigureWindow(x_cvt_vptr_to_uint(wid), XP_STACKING, &wc); +} + + +/* + * Start drawing to a frame. + * Prepare for direct access to its backing buffer. + */ +static void +xprStartDrawing(RootlessFrameID wid, char **pixelData, int *bytesPerRow) +{ + void *data[2]; + unsigned int rowbytes[2]; + xp_error err; + + TA_SERVER(); + + err = xp_lock_window(x_cvt_vptr_to_uint(wid), NULL, NULL, data, rowbytes, NULL); + if (err != Success) + FatalError("Could not lock window %i for drawing.", (int)x_cvt_vptr_to_uint(wid)); + + *pixelData = data[0]; + *bytesPerRow = rowbytes[0]; +} + + +/* + * Stop drawing to a frame. + */ +static void +xprStopDrawing(RootlessFrameID wid, Bool flush) +{ + xp_error err; + TA_SERVER(); + + err = xp_unlock_window(x_cvt_vptr_to_uint(wid), flush); + if(err != Success) + FatalError("Could not unlock window %i after drawing.", (int)x_cvt_vptr_to_uint(wid)); +} + + +/* + * Flush drawing updates to the screen. + */ +static void +xprUpdateRegion(RootlessFrameID wid, RegionPtr pDamage) +{ + TA_SERVER(); + + xp_flush_window(x_cvt_vptr_to_uint(wid)); +} + + +/* + * Mark damaged rectangles as requiring redisplay to screen. + */ +static void +xprDamageRects(RootlessFrameID wid, int nrects, const BoxRec *rects, + int shift_x, int shift_y) +{ + TA_SERVER(); + + xp_mark_window(x_cvt_vptr_to_uint(wid), nrects, rects, shift_x, shift_y); +} + + +/* + * Called after the window associated with a frame has been switched + * to a new top-level parent. + */ +static void +xprSwitchWindow(RootlessWindowPtr pFrame, WindowPtr oldWin) +{ + DeleteProperty(serverClient, oldWin, xa_native_window_id()); + + TA_SERVER(); + + xprSetNativeProperty(pFrame); +} + + +/* + * Called to check if the frame should be reordered when it is restacked. + */ +static Bool xprDoReorderWindow(RootlessWindowPtr pFrame) +{ + WindowPtr pWin = pFrame->win; + + TA_SERVER(); + + return AppleWMDoReorderWindow(pWin); +} + + +/* + * Copy area in frame to another part of frame. + * Used to accelerate scrolling. + */ +static void +xprCopyWindow(RootlessFrameID wid, int dstNrects, const BoxRec *dstRects, + int dx, int dy) +{ + TA_SERVER(); + + xp_copy_window(x_cvt_vptr_to_uint(wid), x_cvt_vptr_to_uint(wid), + dstNrects, dstRects, dx, dy); +} + + +static RootlessFrameProcsRec xprRootlessProcs = { + xprCreateFrame, + xprDestroyFrame, + xprMoveFrame, + xprResizeFrame, + xprRestackFrame, + xprReshapeFrame, + xprUnmapFrame, + xprStartDrawing, + xprStopDrawing, + xprUpdateRegion, + xprDamageRects, + xprSwitchWindow, + xprDoReorderWindow, + xprHideWindow, + xprUpdateColormap, + xp_copy_bytes, + xprCopyWindow +}; + + +/* + * Initialize XPR implementation + */ +Bool +xprInit(ScreenPtr pScreen) +{ + RootlessInit(pScreen, &xprRootlessProcs); + + TA_SERVER(); + + rootless_CopyBytes_threshold = xp_copy_bytes_threshold; + rootless_CopyWindow_threshold = xp_scroll_area_threshold; + + return TRUE; +} + + +/* + * Given the id of a physical window, try to find the top-level (or root) + * X window that it represents. + */ +WindowPtr +xprGetXWindow(xp_window_id wid) +{ + RootlessWindowRec *winRec; + + if (window_hash == NULL) + return NULL; + + winRec = x_hash_table_lookup(window_hash, x_cvt_uint_to_vptr(wid), NULL); + + return winRec != NULL ? winRec->win : NULL; +} + +#ifdef UNUSED_CODE +/* + * Given the id of a physical window, try to find the top-level (or root) + * X window that it represents. + */ +WindowPtr +xprGetXWindowFromAppKit(int windowNumber) +{ + RootlessWindowRec *winRec; + Bool ret; + xp_window_id wid; + + if (window_hash == NULL) + return FALSE; + + /* need to lock, since this function can be called by any thread */ + + pthread_mutex_lock(&window_hash_mutex); + + if (xp_lookup_native_window(windowNumber, &wid)) + ret = xprGetXWindow(wid) != NULL; + else + ret = FALSE; + + pthread_mutex_unlock(&window_hash_mutex); + + if (!ret) return NULL; + winRec = x_hash_table_lookup(window_hash, x_cvt_uint_to_vptr(wid), NULL); + + return winRec != NULL ? winRec->win : NULL; +} +#endif + +/* + * The windowNumber is an AppKit window number. Returns TRUE if xpr is + * displaying a window with that number. + */ +Bool +xprIsX11Window(void *nsWindow, int windowNumber) +{ + Bool ret; + xp_window_id wid; + + if (window_hash == NULL) + return FALSE; + + /* need to lock, since this function can be called by any thread */ + + pthread_mutex_lock(&window_hash_mutex); + + if (xp_lookup_native_window(windowNumber, &wid)) + ret = xprGetXWindow(wid) != NULL; + else + ret = FALSE; + + pthread_mutex_unlock(&window_hash_mutex); + + return ret; +} + + +/* + * xprHideWindows + * Hide or unhide all top level windows. This is called for application hide/ + * unhide events if the window manager is not Apple-WM aware. Xplugin windows + * do not hide or unhide themselves. + */ +void +xprHideWindows(Bool hide) +{ + int screen; + WindowPtr pRoot, pWin; + + TA_SERVER(); + + for (screen = 0; screen < screenInfo.numScreens; screen++) { + RootlessFrameID prevWid = NULL; + pRoot = screenInfo.screens[screen]->root; + + for (pWin = pRoot->firstChild; pWin; pWin = pWin->nextSib) { + RootlessWindowRec *winRec = WINREC(pWin); + + if (winRec != NULL) { + if (hide) { + xprUnmapFrame(winRec->wid); + } else { + BoxRec box; + + xprRestackFrame(winRec->wid, prevWid); + prevWid = winRec->wid; + + box.x1 = 0; + box.y1 = 0; + box.x2 = winRec->width; + box.y2 = winRec->height; + + xprDamageRects(winRec->wid, 1, &box, 0, 0); + RootlessQueueRedisplay(screenInfo.screens[screen]); + } + } + } + } +} + +// XXX: identical to x_cvt_vptr_to_uint ? +#define MAKE_WINDOW_ID(x) ((xp_window_id)((size_t)(x))) + +Bool no_configure_window; + +static inline int +configure_window (xp_window_id id, unsigned int mask, + const xp_window_changes *values) +{ + if (!no_configure_window) + return xp_configure_window (id, mask, values); + else + return XP_Success; +} + + +static +void xprUpdateColormap(RootlessFrameID wid, ScreenPtr pScreen) +{ + /* This is how we tell xp that the colormap may have changed. */ + xp_window_changes wc; + wc.colormap = xprColormapCallback; + wc.colormap_data = pScreen; + + configure_window(MAKE_WINDOW_ID(wid), XP_COLORMAP, &wc); +} + +static +void xprHideWindow(RootlessFrameID wid) +{ + xp_window_changes wc; + wc.stack_mode = XP_UNMAPPED; + wc.sibling = 0; + configure_window(MAKE_WINDOW_ID(wid), XP_STACKING, &wc); +} diff --git a/xorg-server/hw/xquartz/xpr/xprScreen.c b/xorg-server/hw/xquartz/xpr/xprScreen.c index bd877d97c..972278b75 100644 --- a/xorg-server/hw/xquartz/xpr/xprScreen.c +++ b/xorg-server/hw/xquartz/xpr/xprScreen.c @@ -1,451 +1,483 @@ -/*
- * Xplugin rootless implementation screen functions
- *
- * Copyright (c) 2002 Apple Computer, Inc. All Rights Reserved.
- * Copyright (c) 2004 Torrey T. Lyons. All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Except as contained in this notice, the name(s) of the above copyright
- * holders shall not be used in advertising or otherwise to promote the sale,
- * use or other dealings in this Software without prior written authorization.
- */
-
-#include "sanitizedCarbon.h"
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#include "quartzCommon.h"
-#include "inputstr.h"
-#include "quartz.h"
-#include "quartzRandR.h"
-#include "xpr.h"
-#include "xprEvent.h"
-#include "pseudoramiX.h"
-#include "darwin.h"
-#include "darwinEvents.h"
-#include "rootless.h"
-#include "dri.h"
-#include "globals.h"
-#include <Xplugin.h>
-#include "applewmExt.h"
-#include "micmap.h"
-
-#include "rootlessCommon.h"
-
-#ifdef DAMAGE
-# include "damage.h"
-#endif
-
-/* 10.4's deferred update makes X slower.. have to live with the tearing
- for now.. */
-#define XP_NO_DEFERRED_UPDATES 8
-
-// Name of GLX bundle for native OpenGL
-static const char *xprOpenGLBundle = "glxCGL.bundle";
-
-/*
- * eventHandler
- * Callback handler for Xplugin events.
- */
-static void eventHandler(unsigned int type, const void *arg,
- unsigned int arg_size, void *data) {
-
- switch (type) {
- case XP_EVENT_DISPLAY_CHANGED:
- DEBUG_LOG("XP_EVENT_DISPLAY_CHANGED\n");
- DarwinSendDDXEvent(kXquartzDisplayChanged, 0);
- break;
-
- case XP_EVENT_WINDOW_STATE_CHANGED:
- if (arg_size >= sizeof(xp_window_state_event)) {
- const xp_window_state_event *ws_arg = arg;
-
- DEBUG_LOG("XP_EVENT_WINDOW_STATE_CHANGED: id=%d, state=%d\n", ws_arg->id, ws_arg->state);
- DarwinSendDDXEvent(kXquartzWindowState, 2,
- ws_arg->id, ws_arg->state);
- } else {
- DEBUG_LOG("XP_EVENT_WINDOW_STATE_CHANGED: ignored\n");
- }
- break;
-
- case XP_EVENT_WINDOW_MOVED:
- DEBUG_LOG("XP_EVENT_WINDOW_MOVED\n");
- if (arg_size == sizeof(xp_window_id)) {
- xp_window_id id = * (xp_window_id *) arg;
- DarwinSendDDXEvent(kXquartzWindowMoved, 1, id);
- }
- break;
-
- case XP_EVENT_SURFACE_DESTROYED:
- DEBUG_LOG("XP_EVENT_SURFACE_DESTROYED\n");
- case XP_EVENT_SURFACE_CHANGED:
- DEBUG_LOG("XP_EVENT_SURFACE_CHANGED\n");
- if (arg_size == sizeof(xp_surface_id)) {
- int kind;
-
- if (type == XP_EVENT_SURFACE_DESTROYED)
- kind = AppleDRISurfaceNotifyDestroyed;
- else
- kind = AppleDRISurfaceNotifyChanged;
-
- DRISurfaceNotify(*(xp_surface_id *) arg, kind);
- }
- break;
-#ifdef XP_EVENT_SPACE_CHANGED
- case XP_EVENT_SPACE_CHANGED:
- DEBUG_LOG("XP_EVENT_SPACE_CHANGED\n");
- if(arg_size == sizeof(uint32_t)) {
- uint32_t space_id = *(uint32_t *)arg;
- DarwinSendDDXEvent(kXquartzSpaceChanged, 1, space_id);
- }
- break;
-#endif
- default:
- ErrorF("Unknown XP_EVENT type (%d) in xprScreen:eventHandler\n", type);
- }
-}
-
-/*
- * displayAtIndex
- * Return the display ID for a particular display index.
- */
-static CGDirectDisplayID
-displayAtIndex(int index)
-{
- CGError err;
- CGDisplayCount cnt;
- CGDirectDisplayID dpy[index+1];
-
- err = CGGetActiveDisplayList(index + 1, dpy, &cnt);
- if (err == kCGErrorSuccess && cnt == index + 1)
- return dpy[index];
- else
- return kCGNullDirectDisplay;
-}
-
-/*
- * displayScreenBounds
- * Return the bounds of a particular display.
- */
-static CGRect
-displayScreenBounds(CGDirectDisplayID id)
-{
- CGRect frame;
-
- frame = CGDisplayBounds(id);
-
- DEBUG_LOG(" %dx%d @ (%d,%d).\n",
- (int)frame.size.width, (int)frame.size.height,
- (int)frame.origin.x, (int)frame.origin.y);
-
- /* Remove menubar to help standard X11 window managers. */
- if (XQuartzIsRootless &&
- frame.origin.x == 0 && frame.origin.y == 0) {
- frame.origin.y += aquaMenuBarHeight;
- frame.size.height -= aquaMenuBarHeight;
- }
-
- DEBUG_LOG(" %dx%d @ (%d,%d).\n",
- (int)frame.size.width, (int)frame.size.height,
- (int)frame.origin.x, (int)frame.origin.y);
-
- return frame;
-}
-
-/*
- * xprAddPseudoramiXScreens
- * Add a single virtual screen encompassing all the physical screens
- * with PseudoramiX.
- */
-static void
-xprAddPseudoramiXScreens(int *x, int *y, int *width, int *height, ScreenPtr pScreen)
-{
- CGDisplayCount i, displayCount;
- CGDirectDisplayID *displayList = NULL;
- CGRect unionRect = CGRectNull, frame;
-
- // Find all the CoreGraphics displays
- CGGetActiveDisplayList(0, NULL, &displayCount);
- DEBUG_LOG("displayCount: %d\n", (int)displayCount);
-
- if(!displayCount) {
- ErrorF("CoreGraphics has reported no connected displays. Creating a stub 800x600 display.\n");
- *x = *y = 0;
- *width = 800;
- *height = 600;
- PseudoramiXAddScreen(*x, *y, *width, *height);
- return;
- }
-
- displayList = malloc(displayCount * sizeof(CGDirectDisplayID));
- if(!displayList)
- FatalError("Unable to allocate memory for list of displays.\n");
- CGGetActiveDisplayList(displayCount, displayList, &displayCount);
- QuartzCopyDisplayIDs(pScreen, displayCount, displayList);
-
- /* Get the union of all screens */
- for (i = 0; i < displayCount; i++) {
- CGDirectDisplayID dpy = displayList[i];
- frame = displayScreenBounds(dpy);
- unionRect = CGRectUnion(unionRect, frame);
- }
-
- /* Use unionRect as the screen size for the X server. */
- *x = unionRect.origin.x;
- *y = unionRect.origin.y;
- *width = unionRect.size.width;
- *height = unionRect.size.height;
-
- DEBUG_LOG(" screen union origin: (%d,%d) size: (%d,%d).\n",
- *x, *y, *width, *height);
-
- /* Tell PseudoramiX about the real screens. */
- for (i = 0; i < displayCount; i++)
- {
- CGDirectDisplayID dpy = displayList[i];
-
- frame = displayScreenBounds(dpy);
- frame.origin.x -= unionRect.origin.x;
- frame.origin.y -= unionRect.origin.y;
-
- DEBUG_LOG(" placed at X11 coordinate (%d,%d).\n",
- (int)frame.origin.x, (int)frame.origin.y);
-
- PseudoramiXAddScreen(frame.origin.x, frame.origin.y,
- frame.size.width, frame.size.height);
- }
-
- free(displayList);
-}
-
-/*
- * xprDisplayInit
- * Find number of CoreGraphics displays and initialize Xplugin.
- */
-static void
-xprDisplayInit(void)
-{
- CGDisplayCount displayCount;
-
- DEBUG_LOG("");
-
- CGGetActiveDisplayList(0, NULL, &displayCount);
-
- /* With PseudoramiX, the X server only sees one screen; only PseudoramiX
- itself knows about all of the screens. */
-
- if (noPseudoramiXExtension)
- darwinScreensFound = displayCount;
- else
- darwinScreensFound = 1;
-
- if (xp_init(XP_BACKGROUND_EVENTS | XP_NO_DEFERRED_UPDATES) != Success)
- FatalError("Could not initialize the Xplugin library.");
-
- xp_select_events(XP_EVENT_DISPLAY_CHANGED
- | XP_EVENT_WINDOW_STATE_CHANGED
- | XP_EVENT_WINDOW_MOVED
-#ifdef XP_EVENT_SPACE_CHANGED
- | XP_EVENT_SPACE_CHANGED
-#endif
- | XP_EVENT_SURFACE_CHANGED
- | XP_EVENT_SURFACE_DESTROYED,
- eventHandler, NULL);
-
- AppleDRIExtensionInit();
- xprAppleWMInit();
-
- XQuartzIsRootless = XQuartzRootlessDefault;
- if (!XQuartzIsRootless)
- RootlessHideAllWindows();
-}
-
-/*
- * xprAddScreen
- * Init the framebuffer and record pixmap parameters for the screen.
- */
-static Bool
-xprAddScreen(int index, ScreenPtr pScreen)
-{
- DarwinFramebufferPtr dfb = SCREEN_PRIV(pScreen);
- int depth = darwinDesiredDepth;
-
- DEBUG_LOG("index=%d depth=%d\n", index, depth);
-
- if(depth == -1) {
- depth = CGDisplaySamplesPerPixel(kCGDirectMainDisplay) * CGDisplayBitsPerSample(kCGDirectMainDisplay);
- }
-
- switch(depth) {
- case 8: // pseudo-working
- dfb->visuals = PseudoColorMask;
- dfb->preferredCVC = PseudoColor;
- dfb->depth = 8;
- dfb->bitsPerRGB = 8;
- dfb->bitsPerPixel = 8;
- dfb->redMask = 0;
- dfb->greenMask = 0;
- dfb->blueMask = 0;
- break;
- case 15:
- dfb->visuals = TrueColorMask; //LARGE_VISUALS;
- dfb->preferredCVC = TrueColor;
- dfb->depth = 15;
- dfb->bitsPerRGB = 5;
- dfb->bitsPerPixel = 16;
- dfb->redMask = RM_ARGB(0,5,5,5);
- dfb->greenMask = GM_ARGB(0,5,5,5);
- dfb->blueMask = BM_ARGB(0,5,5,5);
- break;
-// case 24:
- default:
- if(depth != 24)
- ErrorF("Unsupported color depth requested. Defaulting to 24bit. (depth=%d darwinDesiredDepth=%d CGDisplaySamplesPerPixel=%d CGDisplayBitsPerSample=%d)\n", darwinDesiredDepth, depth, (int)CGDisplaySamplesPerPixel(kCGDirectMainDisplay), (int)CGDisplayBitsPerSample(kCGDirectMainDisplay));
- dfb->visuals = TrueColorMask; //LARGE_VISUALS;
- dfb->preferredCVC = TrueColor;
- dfb->depth = 24;
- dfb->bitsPerRGB = 8;
- dfb->bitsPerPixel = 32;
- dfb->redMask = RM_ARGB(0,8,8,8);
- dfb->greenMask = GM_ARGB(0,8,8,8);
- dfb->blueMask = BM_ARGB(0,8,8,8);
- break;
- }
-
- if (noPseudoramiXExtension)
- {
- CGDirectDisplayID dpy;
- CGRect frame;
-
- ErrorF("Warning: noPseudoramiXExtension!\n");
-
- dpy = displayAtIndex(index);
- QuartzCopyDisplayIDs(pScreen, 1, &dpy);
-
- frame = displayScreenBounds(dpy);
-
- dfb->x = frame.origin.x;
- dfb->y = frame.origin.y;
- dfb->width = frame.size.width;
- dfb->height = frame.size.height;
- }
- else
- {
- xprAddPseudoramiXScreens(&dfb->x, &dfb->y, &dfb->width, &dfb->height, pScreen);
- }
-
- /* Passing zero width (pitch) makes miCreateScreenResources set the
- screen pixmap to the framebuffer pointer, i.e. NULL. The generic
- rootless code takes care of making this work. */
- dfb->pitch = 0;
- dfb->framebuffer = NULL;
-
- DRIScreenInit(pScreen);
-
- return TRUE;
-}
-
-/*
- * xprSetupScreen
- * Setup the screen for rootless access.
- */
-static Bool
-xprSetupScreen(int index, ScreenPtr pScreen)
-{
-#ifdef DAMAGE
- // The Damage extension needs to wrap underneath the
- // generic rootless layer, so do it now.
- if (!DamageSetup(pScreen))
- return FALSE;
-#endif
-
- // Initialize generic rootless code
- if (!xprInit(pScreen))
- return FALSE;
-
- return DRIFinishScreenInit(pScreen);
-}
-
-/*
- * xprUpdateScreen
- * Update screen after configuation change.
- */
-static void
-xprUpdateScreen(ScreenPtr pScreen)
-{
- rootlessGlobalOffsetX = darwinMainScreenX;
- rootlessGlobalOffsetY = darwinMainScreenY;
-
- AppleWMSetScreenOrigin(pScreen->root);
-
- RootlessRepositionWindows(pScreen);
- RootlessUpdateScreenPixmap(pScreen);
-}
-
-/*
- * xprInitInput
- * Finalize xpr specific setup.
- */
-static void
-xprInitInput(int argc, char **argv)
-{
- int i;
-
- rootlessGlobalOffsetX = darwinMainScreenX;
- rootlessGlobalOffsetY = darwinMainScreenY;
-
- for (i = 0; i < screenInfo.numScreens; i++)
- AppleWMSetScreenOrigin(screenInfo.screens[i]->root);
-}
-
-/*
- * Quartz display mode function list.
- */
-static QuartzModeProcsRec xprModeProcs = {
- xprDisplayInit,
- xprAddScreen,
- xprSetupScreen,
- xprInitInput,
- QuartzInitCursor,
- QuartzSuspendXCursor,
- QuartzResumeXCursor,
- xprAddPseudoramiXScreens,
- xprUpdateScreen,
- xprIsX11Window,
- xprHideWindows,
- RootlessFrameForWindow,
- TopLevelParent,
- DRICreateSurface,
- DRIDestroySurface
-};
-
-/*
- * QuartzModeBundleInit
- * Initialize the display mode bundle after loading.
- */
-Bool
-QuartzModeBundleInit(void)
-{
- quartzProcs = &xprModeProcs;
- quartzOpenGLBundle = xprOpenGLBundle;
- return TRUE;
-}
+/* + * Xplugin rootless implementation screen functions + * + * Copyright (c) 2002 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2004 Torrey T. Lyons. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name(s) of the above copyright + * holders shall not be used in advertising or otherwise to promote the sale, + * use or other dealings in this Software without prior written authorization. + */ + +#include "sanitizedCarbon.h" + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include "quartzCommon.h" +#include "inputstr.h" +#include "quartz.h" +#include "quartzRandR.h" +#include "xpr.h" +#include "xprEvent.h" +#include "pseudoramiX.h" +#include "darwin.h" +#include "darwinEvents.h" +#include "rootless.h" +#include "dri.h" +#include "globals.h" +#include <Xplugin.h> +#include "applewmExt.h" +#include "micmap.h" + +#include "rootlessCommon.h" + +#ifdef DAMAGE +# include "damage.h" +#endif + +/* 10.4's deferred update makes X slower.. have to live with the tearing + for now.. */ +#define XP_NO_DEFERRED_UPDATES 8 + +// Name of GLX bundle for native OpenGL +static const char *xprOpenGLBundle = "glxCGL.bundle"; + +/* + * eventHandler + * Callback handler for Xplugin events. + */ +static void eventHandler(unsigned int type, const void *arg, + unsigned int arg_size, void *data) { + + switch (type) { + case XP_EVENT_DISPLAY_CHANGED: + DEBUG_LOG("XP_EVENT_DISPLAY_CHANGED\n"); + DarwinSendDDXEvent(kXquartzDisplayChanged, 0); + break; + + case XP_EVENT_WINDOW_STATE_CHANGED: + if (arg_size >= sizeof(xp_window_state_event)) { + const xp_window_state_event *ws_arg = arg; + + DEBUG_LOG("XP_EVENT_WINDOW_STATE_CHANGED: id=%d, state=%d\n", ws_arg->id, ws_arg->state); + DarwinSendDDXEvent(kXquartzWindowState, 2, + ws_arg->id, ws_arg->state); + } else { + DEBUG_LOG("XP_EVENT_WINDOW_STATE_CHANGED: ignored\n"); + } + break; + + case XP_EVENT_WINDOW_MOVED: + DEBUG_LOG("XP_EVENT_WINDOW_MOVED\n"); + if (arg_size == sizeof(xp_window_id)) { + xp_window_id id = * (xp_window_id *) arg; + DarwinSendDDXEvent(kXquartzWindowMoved, 1, id); + } + break; + + case XP_EVENT_SURFACE_DESTROYED: + DEBUG_LOG("XP_EVENT_SURFACE_DESTROYED\n"); + case XP_EVENT_SURFACE_CHANGED: + DEBUG_LOG("XP_EVENT_SURFACE_CHANGED\n"); + if (arg_size == sizeof(xp_surface_id)) { + int kind; + + if (type == XP_EVENT_SURFACE_DESTROYED) + kind = AppleDRISurfaceNotifyDestroyed; + else + kind = AppleDRISurfaceNotifyChanged; + + DRISurfaceNotify(*(xp_surface_id *) arg, kind); + } + break; +#ifdef XP_EVENT_SPACE_CHANGED + case XP_EVENT_SPACE_CHANGED: + DEBUG_LOG("XP_EVENT_SPACE_CHANGED\n"); + if(arg_size == sizeof(uint32_t)) { + uint32_t space_id = *(uint32_t *)arg; + DarwinSendDDXEvent(kXquartzSpaceChanged, 1, space_id); + } + break; +#endif + default: + ErrorF("Unknown XP_EVENT type (%d) in xprScreen:eventHandler\n", type); + } +} + +/* + * displayAtIndex + * Return the display ID for a particular display index. + */ +static CGDirectDisplayID +displayAtIndex(int index) +{ + CGError err; + CGDisplayCount cnt; + CGDirectDisplayID dpy[index+1]; + + err = CGGetActiveDisplayList(index + 1, dpy, &cnt); + if (err == kCGErrorSuccess && cnt == index + 1) + return dpy[index]; + else + return kCGNullDirectDisplay; +} + +/* + * displayScreenBounds + * Return the bounds of a particular display. + */ +static CGRect +displayScreenBounds(CGDirectDisplayID id) +{ + CGRect frame; + + frame = CGDisplayBounds(id); + + DEBUG_LOG(" %dx%d @ (%d,%d).\n", + (int)frame.size.width, (int)frame.size.height, + (int)frame.origin.x, (int)frame.origin.y); + + /* Remove menubar to help standard X11 window managers. */ + if (XQuartzIsRootless && + frame.origin.x == 0 && frame.origin.y == 0) { + frame.origin.y += aquaMenuBarHeight; + frame.size.height -= aquaMenuBarHeight; + } + + DEBUG_LOG(" %dx%d @ (%d,%d).\n", + (int)frame.size.width, (int)frame.size.height, + (int)frame.origin.x, (int)frame.origin.y); + + return frame; +} + +/* + * xprAddPseudoramiXScreens + * Add a single virtual screen encompassing all the physical screens + * with PseudoramiX. + */ +static void +xprAddPseudoramiXScreens(int *x, int *y, int *width, int *height, ScreenPtr pScreen) +{ + CGDisplayCount i, displayCount; + CGDirectDisplayID *displayList = NULL; + CGRect unionRect = CGRectNull, frame; + + // Find all the CoreGraphics displays + CGGetActiveDisplayList(0, NULL, &displayCount); + DEBUG_LOG("displayCount: %d\n", (int)displayCount); + + if(!displayCount) { + ErrorF("CoreGraphics has reported no connected displays. Creating a stub 800x600 display.\n"); + *x = *y = 0; + *width = 800; + *height = 600; + PseudoramiXAddScreen(*x, *y, *width, *height); + return; + } + + /* If the displays are captured, we are in a RandR game mode + * on the primary display, so we only want to include the first + * display. The others are covered by the shield window. + */ + if (CGDisplayIsCaptured(kCGDirectMainDisplay)) + displayCount = 1; + + displayList = malloc(displayCount * sizeof(CGDirectDisplayID)); + if(!displayList) + FatalError("Unable to allocate memory for list of displays.\n"); + CGGetActiveDisplayList(displayCount, displayList, &displayCount); + QuartzCopyDisplayIDs(pScreen, displayCount, displayList); + + /* Get the union of all screens */ + for (i = 0; i < displayCount; i++) { + CGDirectDisplayID dpy = displayList[i]; + frame = displayScreenBounds(dpy); + unionRect = CGRectUnion(unionRect, frame); + } + + /* Use unionRect as the screen size for the X server. */ + *x = unionRect.origin.x; + *y = unionRect.origin.y; + *width = unionRect.size.width; + *height = unionRect.size.height; + + DEBUG_LOG(" screen union origin: (%d,%d) size: (%d,%d).\n", + *x, *y, *width, *height); + + /* Tell PseudoramiX about the real screens. */ + for (i = 0; i < displayCount; i++) + { + CGDirectDisplayID dpy = displayList[i]; + + frame = displayScreenBounds(dpy); + frame.origin.x -= unionRect.origin.x; + frame.origin.y -= unionRect.origin.y; + + DEBUG_LOG(" placed at X11 coordinate (%d,%d).\n", + (int)frame.origin.x, (int)frame.origin.y); + + PseudoramiXAddScreen(frame.origin.x, frame.origin.y, + frame.size.width, frame.size.height); + } + + free(displayList); +} + +/* + * xprDisplayInit + * Find number of CoreGraphics displays and initialize Xplugin. + */ +static void +xprDisplayInit(void) +{ + CGDisplayCount displayCount; + + DEBUG_LOG(""); + + CGGetActiveDisplayList(0, NULL, &displayCount); + + /* With PseudoramiX, the X server only sees one screen; only PseudoramiX + itself knows about all of the screens. */ + + if (noPseudoramiXExtension) + darwinScreensFound = displayCount; + else + darwinScreensFound = 1; + + if (xp_init(XP_BACKGROUND_EVENTS | XP_NO_DEFERRED_UPDATES) != Success) + FatalError("Could not initialize the Xplugin library."); + + xp_select_events(XP_EVENT_DISPLAY_CHANGED + | XP_EVENT_WINDOW_STATE_CHANGED + | XP_EVENT_WINDOW_MOVED +#ifdef XP_EVENT_SPACE_CHANGED + | XP_EVENT_SPACE_CHANGED +#endif + | XP_EVENT_SURFACE_CHANGED + | XP_EVENT_SURFACE_DESTROYED, + eventHandler, NULL); + + AppleDRIExtensionInit(); + xprAppleWMInit(); + + XQuartzIsRootless = XQuartzRootlessDefault; + if (!XQuartzIsRootless) + RootlessHideAllWindows(); +} + +/* + * xprAddScreen + * Init the framebuffer and record pixmap parameters for the screen. + */ +static Bool +xprAddScreen(int index, ScreenPtr pScreen) +{ + DarwinFramebufferPtr dfb = SCREEN_PRIV(pScreen); + int depth = darwinDesiredDepth; + + DEBUG_LOG("index=%d depth=%d\n", index, depth); + + if(depth == -1) { +#if MAC_OS_X_VERSION_MIN_REQUIRED < 1060 + depth = CGDisplaySamplesPerPixel(kCGDirectMainDisplay) * CGDisplayBitsPerSample(kCGDirectMainDisplay); +#else + CGDisplayModeRef modeRef; + CFStringRef encStrRef; + + modeRef = CGDisplayCopyDisplayMode(kCGDirectMainDisplay); + if(!modeRef) + goto have_depth; + + encStrRef = CGDisplayModeCopyPixelEncoding(modeRef); + CFRelease(modeRef); + if(!encStrRef) + goto have_depth; + + if(CFStringCompare(encStrRef, CFSTR(IO32BitDirectPixels), kCFCompareCaseInsensitive) == kCFCompareEqualTo) { + depth = 24; + } else if(CFStringCompare(encStrRef, CFSTR(IO16BitDirectPixels), kCFCompareCaseInsensitive) == kCFCompareEqualTo) { + depth = 15; + } else if(CFStringCompare(encStrRef, CFSTR(IO8BitIndexedPixels), kCFCompareCaseInsensitive) == kCFCompareEqualTo) { + depth = 8; + } + + CFRelease(encStrRef); +#endif + } + +have_depth: + switch(depth) { + case 8: // pseudo-working + dfb->visuals = PseudoColorMask; + dfb->preferredCVC = PseudoColor; + dfb->depth = 8; + dfb->bitsPerRGB = 8; + dfb->bitsPerPixel = 8; + dfb->redMask = 0; + dfb->greenMask = 0; + dfb->blueMask = 0; + break; + case 15: + dfb->visuals = TrueColorMask; //LARGE_VISUALS; + dfb->preferredCVC = TrueColor; + dfb->depth = 15; + dfb->bitsPerRGB = 5; + dfb->bitsPerPixel = 16; + dfb->redMask = RM_ARGB(0,5,5,5); + dfb->greenMask = GM_ARGB(0,5,5,5); + dfb->blueMask = BM_ARGB(0,5,5,5); + break; +// case 24: + default: + if(depth != 24) + ErrorF("Unsupported color depth requested. Defaulting to 24bit. (depth=%d darwinDesiredDepth=%d)\n", depth, darwinDesiredDepth); + dfb->visuals = TrueColorMask; //LARGE_VISUALS; + dfb->preferredCVC = TrueColor; + dfb->depth = 24; + dfb->bitsPerRGB = 8; + dfb->bitsPerPixel = 32; + dfb->redMask = RM_ARGB(0,8,8,8); + dfb->greenMask = GM_ARGB(0,8,8,8); + dfb->blueMask = BM_ARGB(0,8,8,8); + break; + } + + if (noPseudoramiXExtension) + { + CGDirectDisplayID dpy; + CGRect frame; + + ErrorF("Warning: noPseudoramiXExtension!\n"); + + dpy = displayAtIndex(index); + QuartzCopyDisplayIDs(pScreen, 1, &dpy); + + frame = displayScreenBounds(dpy); + + dfb->x = frame.origin.x; + dfb->y = frame.origin.y; + dfb->width = frame.size.width; + dfb->height = frame.size.height; + } + else + { + xprAddPseudoramiXScreens(&dfb->x, &dfb->y, &dfb->width, &dfb->height, pScreen); + } + + /* Passing zero width (pitch) makes miCreateScreenResources set the + screen pixmap to the framebuffer pointer, i.e. NULL. The generic + rootless code takes care of making this work. */ + dfb->pitch = 0; + dfb->framebuffer = NULL; + + DRIScreenInit(pScreen); + + return TRUE; +} + +/* + * xprSetupScreen + * Setup the screen for rootless access. + */ +static Bool +xprSetupScreen(int index, ScreenPtr pScreen) +{ +#ifdef DAMAGE + // The Damage extension needs to wrap underneath the + // generic rootless layer, so do it now. + if (!DamageSetup(pScreen)) + return FALSE; +#endif + + // Initialize generic rootless code + if (!xprInit(pScreen)) + return FALSE; + + return DRIFinishScreenInit(pScreen); +} + +/* + * xprUpdateScreen + * Update screen after configuation change. + */ +static void +xprUpdateScreen(ScreenPtr pScreen) +{ + rootlessGlobalOffsetX = darwinMainScreenX; + rootlessGlobalOffsetY = darwinMainScreenY; + + AppleWMSetScreenOrigin(pScreen->root); + + RootlessRepositionWindows(pScreen); + RootlessUpdateScreenPixmap(pScreen); +} + +/* + * xprInitInput + * Finalize xpr specific setup. + */ +static void +xprInitInput(int argc, char **argv) +{ + int i; + + rootlessGlobalOffsetX = darwinMainScreenX; + rootlessGlobalOffsetY = darwinMainScreenY; + + for (i = 0; i < screenInfo.numScreens; i++) + AppleWMSetScreenOrigin(screenInfo.screens[i]->root); +} + +/* + * Quartz display mode function list. + */ +static QuartzModeProcsRec xprModeProcs = { + xprDisplayInit, + xprAddScreen, + xprSetupScreen, + xprInitInput, + QuartzInitCursor, + QuartzSuspendXCursor, + QuartzResumeXCursor, + xprAddPseudoramiXScreens, + xprUpdateScreen, + xprIsX11Window, + xprHideWindows, + RootlessFrameForWindow, + TopLevelParent, + DRICreateSurface, + DRIDestroySurface +}; + +/* + * QuartzModeBundleInit + * Initialize the display mode bundle after loading. + */ +Bool +QuartzModeBundleInit(void) +{ + quartzProcs = &xprModeProcs; + quartzOpenGLBundle = xprOpenGLBundle; + return TRUE; +} diff --git a/xorg-server/include/Makefile.am b/xorg-server/include/Makefile.am index 2b5ee4ddb..6f63c764f 100644 --- a/xorg-server/include/Makefile.am +++ b/xorg-server/include/Makefile.am @@ -1,71 +1,72 @@ -if XORG
-sdk_HEADERS = \
- XIstubs.h \
- Xprintf.h \
- callback.h \
- closestr.h \
- closure.h \
- colormap.h \
- colormapst.h \
- hotplug.h \
- cursor.h \
- cursorstr.h \
- dix.h \
- dixaccess.h \
- dixevents.h \
- dixfont.h \
- dixfontstr.h \
- dixgrabs.h \
- dixstruct.h \
- events.h \
- exevents.h \
- extension.h \
- extinit.h \
- extnsionst.h \
- gc.h \
- gcstruct.h \
- globals.h \
- input.h \
- inputstr.h \
- list.h \
- misc.h \
- miscstruct.h \
- opaque.h \
- os.h \
- pixmap.h \
- pixmapstr.h \
- privates.h \
- property.h \
- propertyst.h \
- ptrveloc.h \
- region.h \
- regionstr.h \
- registry.h \
- resource.h \
- rgb.h \
- screenint.h \
- scrnintstr.h \
- selection.h \
- servermd.h \
- site.h \
- swaprep.h \
- swapreq.h \
- validate.h \
- window.h \
- windowstr.h \
- xkbfile.h \
- xkbsrv.h \
- xkbstr.h \
- xkbrules.h \
- xserver-properties.h
-
-nodist_sdk_HEADERS = xorg-server.h
-endif
-
-AM_CFLAGS = $(DIX_CFLAGS)
-
-EXTRA_DIST = \
- dix-config-apple-verbatim.h \
- eventconvert.h eventstr.h inpututils.h \
- protocol-versions.h \
- xsha1.h
+if XORG +sdk_HEADERS = \ + XIstubs.h \ + Xprintf.h \ + callback.h \ + client.h \ + closestr.h \ + closure.h \ + colormap.h \ + colormapst.h \ + hotplug.h \ + cursor.h \ + cursorstr.h \ + dix.h \ + dixaccess.h \ + dixevents.h \ + dixfont.h \ + dixfontstr.h \ + dixgrabs.h \ + dixstruct.h \ + events.h \ + exevents.h \ + extension.h \ + extinit.h \ + extnsionst.h \ + gc.h \ + gcstruct.h \ + globals.h \ + input.h \ + inputstr.h \ + list.h \ + misc.h \ + miscstruct.h \ + opaque.h \ + os.h \ + pixmap.h \ + pixmapstr.h \ + privates.h \ + property.h \ + propertyst.h \ + ptrveloc.h \ + region.h \ + regionstr.h \ + registry.h \ + resource.h \ + rgb.h \ + screenint.h \ + scrnintstr.h \ + selection.h \ + servermd.h \ + site.h \ + swaprep.h \ + swapreq.h \ + validate.h \ + window.h \ + windowstr.h \ + xkbfile.h \ + xkbsrv.h \ + xkbstr.h \ + xkbrules.h \ + xserver-properties.h + +nodist_sdk_HEADERS = xorg-server.h +endif + +AM_CFLAGS = $(DIX_CFLAGS) + +EXTRA_DIST = \ + dix-config-apple-verbatim.h \ + eventconvert.h eventstr.h inpututils.h \ + protocol-versions.h \ + xsha1.h diff --git a/xorg-server/include/client.h b/xorg-server/include/client.h new file mode 100644 index 000000000..aaafc7da6 --- /dev/null +++ b/xorg-server/include/client.h @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). All + * rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +/* Author: Rami Ylimäki <rami.ylimaki@vincit.fi> */ + +#ifndef CLIENT_H +#define CLIENT_H + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif /* HAVE_DIX_CONFIG_H */ +#include <X11/Xfuncproto.h> +#include <sys/types.h> + +/* Client IDs. Use GetClientPid, GetClientCmdName and GetClientCmdArgs + * instead of accessing the fields directly. */ +typedef struct { + pid_t pid; /* process ID, -1 if not available */ + const char *cmdname; /* process name, NULL if not available */ + const char *cmdargs; /* process arguments, NULL if not available */ +} ClientIdRec, *ClientIdPtr; + +struct _Client; + +/* Initialize and clean up. */ +void ReserveClientIds(struct _Client *client); +void ReleaseClientIds(struct _Client *client); + +/* Determine client IDs for caching. Exported on purpose for + * extensions such as SELinux. */ +extern _X_EXPORT pid_t DetermineClientPid(struct _Client *client); +extern _X_EXPORT void DetermineClientCmd(pid_t, const char **cmdname, const char **cmdargs); + +/* Query cached client IDs. Exported on purpose for drivers. */ +extern _X_EXPORT pid_t GetClientPid(struct _Client *client); +extern _X_EXPORT const char *GetClientCmdName(struct _Client *client); +extern _X_EXPORT const char *GetClientCmdArgs(struct _Client *client); + +#endif /* CLIENT_H */ diff --git a/xorg-server/include/dix-config.h.in b/xorg-server/include/dix-config.h.in index 64eb296c8..fc93f3ec1 100644 --- a/xorg-server/include/dix-config.h.in +++ b/xorg-server/include/dix-config.h.in @@ -1,449 +1,452 @@ -/* dix-config.h.in: not at all generated. -*- c -*- */
-
-#ifndef _DIX_CONFIG_H_
-#define _DIX_CONFIG_H_
-
-/* Support BigRequests extension */
-#undef BIGREQS
-
-/* Builder address */
-#undef BUILDERADDR
-
-/* Operating System Name */
-#undef OSNAME
-
-/* Operating System Vendor */
-#undef OSVENDOR
-
-/* Builder string */
-#undef BUILDERSTRING
-
-/* Default font path */
-#undef COMPILEDDEFAULTFONTPATH
-
-/* Miscellaneous server configuration files path */
-#undef SERVER_MISC_CONFIG_PATH
-
-/* Support Composite Extension */
-#undef COMPOSITE
-
-/* Support Damage extension */
-#undef DAMAGE
-
-/* Build for darwin with Quartz support */
-#undef DARWIN_WITH_QUARTZ
-
-/* Use OsVendorVErrorF */
-#undef DDXOSVERRORF
-
-/* Use ddxBeforeReset */
-#undef DDXBEFORERESET
-
-/* Build DPMS extension */
-#undef DPMSExtension
-
-/* Build GLX extension */
-#undef GLXEXT
-
-/* Build GLX DRI loader */
-#undef GLX_DRI
-
-/* Path to DRI drivers */
-#undef DRI_DRIVER_PATH
-
-/* Support XDM-AUTH*-1 */
-#undef HASXDMAUTH
-
-/* Define to 1 if you have the `getdtablesize' function. */
-#undef HAS_GETDTABLESIZE
-
-/* Define to 1 if you have the `getifaddrs' function. */
-#undef HAS_GETIFADDRS
-
-/* Define to 1 if you have the `getpeereid' function. */
-#undef HAS_GETPEEREID
-
-/* Define to 1 if you have the `getpeerucred' function. */
-#undef HAS_GETPEERUCRED
-
-/* Define to 1 if you have the `mmap' function. */
-#undef HAS_MMAP
-
-/* Support SHM */
-#undef HAS_SHM
-
-/* Have the 'strlcpy' function */
-#undef HAS_STRLCPY
-
-/* Define to 1 if you have the <asm/mtrr.h> header file. */
-#undef HAVE_ASM_MTRR_H
-
-/* Has backtrace support */
-#undef HAVE_BACKTRACE
-
-/* Define to 1 if you have the <byteswap.h> header file. */
-#undef HAVE_BYTESWAP_H
-
-/* Define to 1 if you have cbrt */
-#undef HAVE_CBRT
-
-/* Define to 1 if you have the <dbm.h> header file. */
-#undef HAVE_DBM_H
-
-/* Define to 1 if you have the <dirent.h> header file, and it defines `DIR'.
- */
-#undef HAVE_DIRENT_H
-
-/* Define to 1 if you have the <dlfcn.h> header file. */
-#undef HAVE_DLFCN_H
-
-/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */
-#undef HAVE_DOPRNT
-
-/* Have execinfo.h */
-#undef HAVE_EXECINFO_H
-
-/* Define to 1 if you have the <fcntl.h> header file. */
-#undef HAVE_FCNTL_H
-
-/* Define to 1 if you have the `geteuid' function. */
-#undef HAVE_GETEUID
-
-/* Define to 1 if you have the `getisax' function. */
-#undef HAVE_GETISAX
-
-/* Define to 1 if you have the `getuid' function. */
-#undef HAVE_GETUID
-
-/* Define to 1 if you have the `getzoneid' function. */
-#undef HAVE_GETZONEID
-
-/* Define to 1 if you have the <inttypes.h> header file. */
-#undef HAVE_INTTYPES_H
-
-/* Have Quartz */
-#undef XQUARTZ
-
-/* Support application updating through sparkle. */
-#undef XQUARTZ_SPARKLE
-
-/* Prefix to use for launchd identifiers */
-#undef LAUNCHD_ID_PREFIX
-
-/* Build a standalone xpbproxy */
-#undef STANDALONE_XPBPROXY
-
-/* Define to 1 if you have the `m' library (-lm). */
-#undef HAVE_LIBM
-
-/* Define to 1 if you have the `link' function. */
-#undef HAVE_LINK
-
-/* Define to 1 if you have the <linux/agpgart.h> header file. */
-#undef HAVE_LINUX_AGPGART_H
-
-/* Define to 1 if you have the <linux/apm_bios.h> header file. */
-#undef HAVE_LINUX_APM_BIOS_H
-
-/* Define to 1 if you have the <linux/fb.h> header file. */
-#undef HAVE_LINUX_FB_H
-
-/* Define to 1 if you have the `mkstemp' function. */
-#undef HAVE_MKSTEMP
-
-/* Define to 1 if you have the <ndbm.h> header file. */
-#undef HAVE_NDBM_H
-
-/* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */
-#undef HAVE_NDIR_H
-
-/* Define to 1 if you have the <rpcsvc/dbm.h> header file. */
-#undef HAVE_RPCSVC_DBM_H
-
-/* Define to use libc SHA1 functions */
-#undef HAVE_SHA1_IN_LIBC
-
-/* Define to use CommonCrypto SHA1 functions */
-#undef HAVE_SHA1_IN_COMMONCRYPTO
-
-/* Define to use libmd SHA1 functions */
-#undef HAVE_SHA1_IN_LIBMD
-
-/* Define to use libgcrypt SHA1 functions */
-#undef HAVE_SHA1_IN_LIBGCRYPT
-
-/* Define to use libsha1 for SHA1 */
-#undef HAVE_SHA1_IN_LIBSHA1
-
-/* Define to 1 if you have the `shmctl64' function. */
-#undef HAVE_SHMCTL64
-
-/* Define to 1 if you have the <stdint.h> header file. */
-#undef HAVE_STDINT_H
-
-/* Define to 1 if you have the <stdlib.h> header file. */
-#undef HAVE_STDLIB_H
-
-/* Define to 1 if you have the `strchr' function. */
-#undef HAVE_STRCHR
-
-/* Define to 1 if you have the <strings.h> header file. */
-#undef HAVE_STRINGS_H
-
-/* Define to 1 if you have the <string.h> header file. */
-#undef HAVE_STRING_H
-
-/* Define to 1 if you have the `strrchr' function. */
-#undef HAVE_STRRCHR
-
-/* Define to 1 if you have the `strtol' function. */
-#undef HAVE_STRTOL
-
-/* Define to 1 if SYSV IPC is available */
-#undef HAVE_SYSV_IPC
-
-/* Define to 1 if you have the <sys/agpio.h> header file. */
-#undef HAVE_SYS_AGPIO_H
-
-/* Define to 1 if you have the <sys/dir.h> header file, and it defines `DIR'.
- */
-#undef HAVE_SYS_DIR_H
-
-/* Define to 1 if you have the <sys/io.h> header file. */
-#undef HAVE_SYS_IO_H
-
-/* Define to 1 if you have the <sys/ndir.h> header file, and it defines `DIR'.
- */
-#undef HAVE_SYS_NDIR_H
-
-/* Define to 1 if you have the <sys/stat.h> header file. */
-#undef HAVE_SYS_STAT_H
-
-/* Define to 1 if you have the <sys/types.h> header file. */
-#undef HAVE_SYS_TYPES_H
-
-/* Define to 1 if you have the <sys/utsname.h> header file. */
-#undef HAVE_SYS_UTSNAME_H
-
-/* Define to 1 if you have the <sys/vm86.h> header file. */
-#undef HAVE_SYS_VM86_H
-
-/* Define to 1 if you have the <tslib.h> header file. */
-#undef HAVE_TSLIB_H
-
-/* Define to 1 if you have the <unistd.h> header file. */
-#undef HAVE_UNISTD_H
-
-/* Define to 1 if you have the <fnmatch.h> header file. */
-#undef HAVE_FNMATCH_H
-
-/* Have /dev/urandom */
-#undef HAVE_URANDOM
-
-/* Define to 1 if you have the `vprintf' function. */
-#undef HAVE_VPRINTF
-
-/* Define to 1 if you have the `vasprintf' function. */
-#undef HAVE_VASPRINTF
-
-/* Support IPv6 for TCP connections */
-#undef IPv6
-
-/* Support os-specific local connections */
-#undef LOCALCONN
-
-/* Support MIT-SHM Extension */
-#undef MITSHM
-
-/* Enable some debugging code */
-#undef DEBUG
-
-/* Name of package */
-#undef PACKAGE
-
-/* Internal define for Xinerama */
-#undef PANORAMIX
-
-/* Overall prefix */
-#undef PROJECTROOT
-
-/* Support RANDR extension */
-#undef RANDR
-
-/* Support Record extension */
-#undef XRECORD
-
-/* Support RENDER extension */
-#undef RENDER
-
-/* Support X resource extension */
-#undef RES
-
-/* Support MIT-SCREEN-SAVER extension */
-#undef SCREENSAVER
-
-/* Support Secure RPC ("SUN-DES-1") authentication for X11 clients */
-#undef SECURE_RPC
-
-/* Support SHAPE extension */
-#undef SHAPE
-
-/* Define to 1 on systems derived from System V Release 4 */
-#undef SVR4
-
-/* Support TCP socket connections */
-#undef TCPCONN
-
-/* Enable touchscreen support */
-#undef TOUCHSCREEN
-
-/* Support tslib touchscreen abstraction library */
-#undef TSLIB
-
-/* Support UNIX socket connections */
-#undef UNIXCONN
-
-/* Define to use byteswap macros from <sys/endian.h> */
-#undef USE_SYS_ENDIAN_H
-
-/* unaligned word accesses behave as expected */
-#undef WORKING_UNALIGNED_INT
-
-/* Build X string registry */
-#undef XREGISTRY
-
-/* Build X-ACE extension */
-#undef XACE
-
-/* Build SELinux extension */
-#undef XSELINUX
-
-/* Support XCMisc extension */
-#undef XCMISC
-
-/* Build Security extension */
-#undef XCSECURITY
-
-/* Support Xdmcp */
-#undef XDMCP
-
-/* Build XFree86 BigFont extension */
-#undef XF86BIGFONT
-
-/* Support XFree86 Video Mode extension */
-#undef XF86VIDMODE
-
-/* Support XFixes extension */
-#undef XFIXES
-
-/* Build XDGA support */
-#undef XFreeXDGA
-
-/* Support Xinerama extension */
-#undef XINERAMA
-
-/* Vendor release */
-#undef XORG_RELEASE
-
-/* Current Xorg version */
-#undef XORG_VERSION_CURRENT
-
-/* Xorg release date */
-#undef XORG_DATE
-
-/* Build Xv Extension */
-#undef XvExtension
-
-/* Build XvMC Extension */
-#undef XvMCExtension
-
-/* Support XSync extension */
-#undef XSYNC
-
-/* Support XTest extension */
-#undef XTEST
-
-/* Support Xv extension */
-#undef XV
-
-/* Support DRI extension */
-#undef XF86DRI
-
-/* Build DRI2 extension */
-#undef DRI2
-
-/* Build DBE support */
-#undef DBE
-
-/* Vendor name */
-#undef XVENDORNAME
-
-/* Enable GNU and other extensions to the C environment for GLIBC */
-#undef _GNU_SOURCE
-
-/* Define to empty if `const' does not conform to ANSI C. */
-#undef const
-
-/* Define to `int' if <sys/types.h> does not define. */
-#undef pid_t
-
-/* Build Rootless code */
-#undef ROOTLESS
-
-/* Define to 1 if unsigned long is 64 bits. */
-#undef _XSERVER64
-
-/* System is BSD-like */
-#undef CSRG_BASED
-
-/* Define to 1 if `struct sockaddr_in' has a `sin_len' member */
-#undef BSD44SOCKETS
-
-/* Support D-Bus */
-#undef HAVE_DBUS
-
-/* Use libudev for input hotplug */
-#undef CONFIG_UDEV
-
-/* Use D-Bus for input hotplug */
-#undef CONFIG_NEED_DBUS
-
-/* Support the D-Bus hotplug API */
-#undef CONFIG_DBUS_API
-
-/* Support HAL for hotplug */
-#undef CONFIG_HAL
-
-/* Have a monotonic clock from clock_gettime() */
-#undef MONOTONIC_CLOCK
-
-/* Define to 1 if the DTrace Xserver provider probes should be built in */
-#undef XSERVER_DTRACE
-
-/* Define to 16-bit byteswap macro */
-#undef bswap_16
-
-/* Define to 32-bit byteswap macro */
-#undef bswap_32
-
-/* Define to 64-bit byteswap macro */
-#undef bswap_64
-
-/* Need the strcasecmp function. */
-#undef NEED_STRCASECMP
-
-/* Need the strncasecmp function. */
-#undef NEED_STRNCASECMP
-
-/* Need the strcasestr function. */
-#undef NEED_STRCASESTR
-
-/* Define to 1 if you have the `ffs' function. */
-#undef HAVE_FFS
-
-/* Correctly set _XSERVER64 for OSX fat binaries */
-#ifdef __APPLE__
-#include "dix-config-apple-verbatim.h"
-#endif
-
-#endif /* _DIX_CONFIG_H_ */
+/* dix-config.h.in: not at all generated. -*- c -*- */ + +#ifndef _DIX_CONFIG_H_ +#define _DIX_CONFIG_H_ + +/* Support BigRequests extension */ +#undef BIGREQS + +/* Builder address */ +#undef BUILDERADDR + +/* Operating System Name */ +#undef OSNAME + +/* Operating System Vendor */ +#undef OSVENDOR + +/* Builder string */ +#undef BUILDERSTRING + +/* Default font path */ +#undef COMPILEDDEFAULTFONTPATH + +/* Miscellaneous server configuration files path */ +#undef SERVER_MISC_CONFIG_PATH + +/* Support Composite Extension */ +#undef COMPOSITE + +/* Support Damage extension */ +#undef DAMAGE + +/* Build for darwin with Quartz support */ +#undef DARWIN_WITH_QUARTZ + +/* Use OsVendorVErrorF */ +#undef DDXOSVERRORF + +/* Use ddxBeforeReset */ +#undef DDXBEFORERESET + +/* Build DPMS extension */ +#undef DPMSExtension + +/* Build GLX extension */ +#undef GLXEXT + +/* Build GLX DRI loader */ +#undef GLX_DRI + +/* Path to DRI drivers */ +#undef DRI_DRIVER_PATH + +/* Support XDM-AUTH*-1 */ +#undef HASXDMAUTH + +/* Define to 1 if you have the `getdtablesize' function. */ +#undef HAS_GETDTABLESIZE + +/* Define to 1 if you have the `getifaddrs' function. */ +#undef HAS_GETIFADDRS + +/* Define to 1 if you have the `getpeereid' function. */ +#undef HAS_GETPEEREID + +/* Define to 1 if you have the `getpeerucred' function. */ +#undef HAS_GETPEERUCRED + +/* Define to 1 if you have the `mmap' function. */ +#undef HAS_MMAP + +/* Support SHM */ +#undef HAS_SHM + +/* Have the 'strlcpy' function */ +#undef HAS_STRLCPY + +/* Define to 1 if you have the <asm/mtrr.h> header file. */ +#undef HAVE_ASM_MTRR_H + +/* Has backtrace support */ +#undef HAVE_BACKTRACE + +/* Define to 1 if you have the <byteswap.h> header file. */ +#undef HAVE_BYTESWAP_H + +/* Define to 1 if you have cbrt */ +#undef HAVE_CBRT + +/* Define to 1 if you have the <dbm.h> header file. */ +#undef HAVE_DBM_H + +/* Define to 1 if you have the <dirent.h> header file, and it defines `DIR'. + */ +#undef HAVE_DIRENT_H + +/* Define to 1 if you have the <dlfcn.h> header file. */ +#undef HAVE_DLFCN_H + +/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */ +#undef HAVE_DOPRNT + +/* Have execinfo.h */ +#undef HAVE_EXECINFO_H + +/* Define to 1 if you have the <fcntl.h> header file. */ +#undef HAVE_FCNTL_H + +/* Define to 1 if you have the `geteuid' function. */ +#undef HAVE_GETEUID + +/* Define to 1 if you have the `getisax' function. */ +#undef HAVE_GETISAX + +/* Define to 1 if you have the `getuid' function. */ +#undef HAVE_GETUID + +/* Define to 1 if you have the `getzoneid' function. */ +#undef HAVE_GETZONEID + +/* Define to 1 if you have the <inttypes.h> header file. */ +#undef HAVE_INTTYPES_H + +/* Have Quartz */ +#undef XQUARTZ + +/* Support application updating through sparkle. */ +#undef XQUARTZ_SPARKLE + +/* Prefix to use for launchd identifiers */ +#undef LAUNCHD_ID_PREFIX + +/* Build a standalone xpbproxy */ +#undef STANDALONE_XPBPROXY + +/* Define to 1 if you have the `m' library (-lm). */ +#undef HAVE_LIBM + +/* Define to 1 if you have the `link' function. */ +#undef HAVE_LINK + +/* Define to 1 if you have the <linux/agpgart.h> header file. */ +#undef HAVE_LINUX_AGPGART_H + +/* Define to 1 if you have the <linux/apm_bios.h> header file. */ +#undef HAVE_LINUX_APM_BIOS_H + +/* Define to 1 if you have the <linux/fb.h> header file. */ +#undef HAVE_LINUX_FB_H + +/* Define to 1 if you have the `mkstemp' function. */ +#undef HAVE_MKSTEMP + +/* Define to 1 if you have the <ndbm.h> header file. */ +#undef HAVE_NDBM_H + +/* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */ +#undef HAVE_NDIR_H + +/* Define to 1 if you have the <rpcsvc/dbm.h> header file. */ +#undef HAVE_RPCSVC_DBM_H + +/* Define to use libc SHA1 functions */ +#undef HAVE_SHA1_IN_LIBC + +/* Define to use CommonCrypto SHA1 functions */ +#undef HAVE_SHA1_IN_COMMONCRYPTO + +/* Define to use libmd SHA1 functions */ +#undef HAVE_SHA1_IN_LIBMD + +/* Define to use libgcrypt SHA1 functions */ +#undef HAVE_SHA1_IN_LIBGCRYPT + +/* Define to use libsha1 for SHA1 */ +#undef HAVE_SHA1_IN_LIBSHA1 + +/* Define to 1 if you have the `shmctl64' function. */ +#undef HAVE_SHMCTL64 + +/* Define to 1 if you have the <stdint.h> header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the <stdlib.h> header file. */ +#undef HAVE_STDLIB_H + +/* Define to 1 if you have the `strchr' function. */ +#undef HAVE_STRCHR + +/* Define to 1 if you have the <strings.h> header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the <string.h> header file. */ +#undef HAVE_STRING_H + +/* Define to 1 if you have the `strrchr' function. */ +#undef HAVE_STRRCHR + +/* Define to 1 if you have the `strtol' function. */ +#undef HAVE_STRTOL + +/* Define to 1 if SYSV IPC is available */ +#undef HAVE_SYSV_IPC + +/* Define to 1 if you have the <sys/agpio.h> header file. */ +#undef HAVE_SYS_AGPIO_H + +/* Define to 1 if you have the <sys/dir.h> header file, and it defines `DIR'. + */ +#undef HAVE_SYS_DIR_H + +/* Define to 1 if you have the <sys/io.h> header file. */ +#undef HAVE_SYS_IO_H + +/* Define to 1 if you have the <sys/ndir.h> header file, and it defines `DIR'. + */ +#undef HAVE_SYS_NDIR_H + +/* Define to 1 if you have the <sys/stat.h> header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the <sys/types.h> header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define to 1 if you have the <sys/utsname.h> header file. */ +#undef HAVE_SYS_UTSNAME_H + +/* Define to 1 if you have the <sys/vm86.h> header file. */ +#undef HAVE_SYS_VM86_H + +/* Define to 1 if you have the <tslib.h> header file. */ +#undef HAVE_TSLIB_H + +/* Define to 1 if you have the <unistd.h> header file. */ +#undef HAVE_UNISTD_H + +/* Define to 1 if you have the <fnmatch.h> header file. */ +#undef HAVE_FNMATCH_H + +/* Have /dev/urandom */ +#undef HAVE_URANDOM + +/* Define to 1 if you have the `vprintf' function. */ +#undef HAVE_VPRINTF + +/* Define to 1 if you have the `vasprintf' function. */ +#undef HAVE_VASPRINTF + +/* Support IPv6 for TCP connections */ +#undef IPv6 + +/* Support os-specific local connections */ +#undef LOCALCONN + +/* Support MIT-SHM Extension */ +#undef MITSHM + +/* Enable some debugging code */ +#undef DEBUG + +/* Name of package */ +#undef PACKAGE + +/* Internal define for Xinerama */ +#undef PANORAMIX + +/* Overall prefix */ +#undef PROJECTROOT + +/* Support RANDR extension */ +#undef RANDR + +/* Support Record extension */ +#undef XRECORD + +/* Support RENDER extension */ +#undef RENDER + +/* Support X resource extension */ +#undef RES + +/* Support client ID tracking in X resource extension */ +#undef CLIENTIDS + +/* Support MIT-SCREEN-SAVER extension */ +#undef SCREENSAVER + +/* Support Secure RPC ("SUN-DES-1") authentication for X11 clients */ +#undef SECURE_RPC + +/* Support SHAPE extension */ +#undef SHAPE + +/* Define to 1 on systems derived from System V Release 4 */ +#undef SVR4 + +/* Support TCP socket connections */ +#undef TCPCONN + +/* Enable touchscreen support */ +#undef TOUCHSCREEN + +/* Support tslib touchscreen abstraction library */ +#undef TSLIB + +/* Support UNIX socket connections */ +#undef UNIXCONN + +/* Define to use byteswap macros from <sys/endian.h> */ +#undef USE_SYS_ENDIAN_H + +/* unaligned word accesses behave as expected */ +#undef WORKING_UNALIGNED_INT + +/* Build X string registry */ +#undef XREGISTRY + +/* Build X-ACE extension */ +#undef XACE + +/* Build SELinux extension */ +#undef XSELINUX + +/* Support XCMisc extension */ +#undef XCMISC + +/* Build Security extension */ +#undef XCSECURITY + +/* Support Xdmcp */ +#undef XDMCP + +/* Build XFree86 BigFont extension */ +#undef XF86BIGFONT + +/* Support XFree86 Video Mode extension */ +#undef XF86VIDMODE + +/* Support XFixes extension */ +#undef XFIXES + +/* Build XDGA support */ +#undef XFreeXDGA + +/* Support Xinerama extension */ +#undef XINERAMA + +/* Vendor release */ +#undef XORG_RELEASE + +/* Current Xorg version */ +#undef XORG_VERSION_CURRENT + +/* Xorg release date */ +#undef XORG_DATE + +/* Build Xv Extension */ +#undef XvExtension + +/* Build XvMC Extension */ +#undef XvMCExtension + +/* Support XSync extension */ +#undef XSYNC + +/* Support XTest extension */ +#undef XTEST + +/* Support Xv extension */ +#undef XV + +/* Support DRI extension */ +#undef XF86DRI + +/* Build DRI2 extension */ +#undef DRI2 + +/* Build DBE support */ +#undef DBE + +/* Vendor name */ +#undef XVENDORNAME + +/* Enable GNU and other extensions to the C environment for GLIBC */ +#undef _GNU_SOURCE + +/* Define to empty if `const' does not conform to ANSI C. */ +#undef const + +/* Define to `int' if <sys/types.h> does not define. */ +#undef pid_t + +/* Build Rootless code */ +#undef ROOTLESS + +/* Define to 1 if unsigned long is 64 bits. */ +#undef _XSERVER64 + +/* System is BSD-like */ +#undef CSRG_BASED + +/* Define to 1 if `struct sockaddr_in' has a `sin_len' member */ +#undef BSD44SOCKETS + +/* Support D-Bus */ +#undef HAVE_DBUS + +/* Use libudev for input hotplug */ +#undef CONFIG_UDEV + +/* Use D-Bus for input hotplug */ +#undef CONFIG_NEED_DBUS + +/* Support the D-Bus hotplug API */ +#undef CONFIG_DBUS_API + +/* Support HAL for hotplug */ +#undef CONFIG_HAL + +/* Have a monotonic clock from clock_gettime() */ +#undef MONOTONIC_CLOCK + +/* Define to 1 if the DTrace Xserver provider probes should be built in */ +#undef XSERVER_DTRACE + +/* Define to 16-bit byteswap macro */ +#undef bswap_16 + +/* Define to 32-bit byteswap macro */ +#undef bswap_32 + +/* Define to 64-bit byteswap macro */ +#undef bswap_64 + +/* Need the strcasecmp function. */ +#undef NEED_STRCASECMP + +/* Need the strncasecmp function. */ +#undef NEED_STRNCASECMP + +/* Need the strcasestr function. */ +#undef NEED_STRCASESTR + +/* Define to 1 if you have the `ffs' function. */ +#undef HAVE_FFS + +/* Correctly set _XSERVER64 for OSX fat binaries */ +#ifdef __APPLE__ +#include "dix-config-apple-verbatim.h" +#endif + +#endif /* _DIX_CONFIG_H_ */ diff --git a/xorg-server/include/dix.h b/xorg-server/include/dix.h index 12e4b5977..3f99098a2 100644 --- a/xorg-server/include/dix.h +++ b/xorg-server/include/dix.h @@ -570,6 +570,7 @@ extern Bool _X_EXPORT IsPointerDevice( DeviceIntPtr dev); extern Bool _X_EXPORT IsKeyboardDevice(DeviceIntPtr dev); extern Bool IsPointerEvent(InternalEvent *event); extern _X_EXPORT Bool IsMaster(DeviceIntPtr dev); +extern _X_EXPORT Bool IsFloating(DeviceIntPtr dev); extern _X_HIDDEN void CopyKeyClass(DeviceIntPtr device, DeviceIntPtr master); extern _X_HIDDEN int CorePointerProc(DeviceIntPtr dev, int what); diff --git a/xorg-server/include/dixstruct.h b/xorg-server/include/dixstruct.h index 92d68d332..443e8b0ae 100644 --- a/xorg-server/include/dixstruct.h +++ b/xorg-server/include/dixstruct.h @@ -1,190 +1,192 @@ -/***********************************************************
-Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
-
- All Rights Reserved
-
-Permission 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 that
-both that copyright notice and this permission notice appear in
-supporting documentation, and that the name of Digital not be
-used in advertising or publicity pertaining to distribution of the
-software without specific, written prior permission.
-
-DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
-ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
-DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
-ANY 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 THIS
-SOFTWARE.
-
-******************************************************************/
-
-#ifndef DIXSTRUCT_H
-#define DIXSTRUCT_H
-
-#include "dix.h"
-#include "resource.h"
-#include "cursor.h"
-#include "gc.h"
-#include "pixmap.h"
-#include "privates.h"
-#include <X11/Xmd.h>
-
-/*
- * direct-mapped hash table, used by resource manager to store
- * translation from client ids to server addresses.
- */
-
-extern _X_EXPORT CallbackListPtr ClientStateCallback;
-
-typedef struct {
- ClientPtr client;
- xConnSetupPrefix *prefix;
- xConnSetup *setup;
-} NewClientInfoRec;
-
-typedef void (*ReplySwapPtr) (
- ClientPtr /* pClient */,
- int /* size */,
- void * /* pbuf */);
-
-extern _X_EXPORT void ReplyNotSwappd (
- ClientPtr /* pClient */,
- int /* size */,
- void * /* pbuf */) _X_NORETURN;
-
-typedef enum {ClientStateInitial,
- ClientStateAuthenticating,
- ClientStateRunning,
- ClientStateRetained,
- ClientStateGone,
- ClientStateCheckingSecurity,
- ClientStateCheckedSecurity} ClientState;
-
-#ifdef XFIXES
-typedef struct _saveSet {
- struct _Window *windowPtr;
- Bool toRoot;
- Bool map;
-} SaveSetElt;
-#define SaveSetWindow(ss) ((ss).windowPtr)
-#define SaveSetToRoot(ss) ((ss).toRoot)
-#define SaveSetShouldMap(ss) ((ss).map)
-#define SaveSetAssignWindow(ss,w) ((ss).windowPtr = (w))
-#define SaveSetAssignToRoot(ss,tr) ((ss).toRoot = (tr))
-#define SaveSetAssignMap(ss,m) ((ss).map = (m))
-#else
-typedef struct _Window *SaveSetElt;
-#define SaveSetWindow(ss) (ss)
-#define SaveSetToRoot(ss) FALSE
-#define SaveSetShouldMap(ss) TRUE
-#define SaveSetAssignWindow(ss,w) ((ss) = (w))
-#define SaveSetAssignToRoot(ss,tr)
-#define SaveSetAssignMap(ss,m)
-#endif
-
-typedef struct _Client {
- int index;
- Mask clientAsMask;
- pointer requestBuffer;
- pointer osPrivate; /* for OS layer, including scheduler */
- Bool swapped;
- ReplySwapPtr pSwapReplyFunc;
- XID errorValue;
- int sequence;
- int closeDownMode;
- int clientGone;
- int noClientException; /* this client died or needs to be
- * killed */
- int ignoreCount; /* count for Attend/IgnoreClient */
- SaveSetElt *saveSet;
- int numSaved;
- int (**requestVector) (
- ClientPtr /* pClient */);
- CARD32 req_len; /* length of current request */
- Bool big_requests; /* supports large requests */
- int priority;
- ClientState clientState;
- PrivateRec *devPrivates;
- unsigned short xkbClientFlags;
- unsigned short mapNotifyMask;
- unsigned short newKeyboardNotifyMask;
- unsigned short vMajor,vMinor;
- KeyCode minKC,maxKC;
-
- unsigned long replyBytesRemaining;
- int smart_priority;
- long smart_start_tick;
- long smart_stop_tick;
- long smart_check_tick;
-
- DeviceIntPtr clientPtr;
-} ClientRec;
-
-/*
- * Scheduling interface
- */
-extern _X_EXPORT long SmartScheduleTime;
-extern _X_EXPORT long SmartScheduleInterval;
-extern _X_EXPORT long SmartScheduleSlice;
-extern _X_EXPORT long SmartScheduleMaxSlice;
-extern _X_EXPORT Bool SmartScheduleDisable;
-extern _X_EXPORT void SmartScheduleStartTimer(void);
-extern _X_EXPORT void SmartScheduleStopTimer(void);
-#define SMART_MAX_PRIORITY (20)
-#define SMART_MIN_PRIORITY (-20)
-
-extern _X_EXPORT void SmartScheduleInit(void);
-
-
-/* This prototype is used pervasively in Xext, dix */
-#define DISPATCH_PROC(func) int func(ClientPtr /* client */)
-
-typedef struct _WorkQueue {
- struct _WorkQueue *next;
- Bool (*function) (
- ClientPtr /* pClient */,
- pointer /* closure */
-);
- ClientPtr client;
- pointer closure;
-} WorkQueueRec;
-
-extern _X_EXPORT TimeStamp currentTime;
-extern _X_EXPORT TimeStamp lastDeviceEventTime;
-
-extern _X_EXPORT int CompareTimeStamps(
- TimeStamp /*a*/,
- TimeStamp /*b*/);
-
-extern _X_EXPORT TimeStamp ClientTimeToServerTime(CARD32 /*c*/);
-
-typedef struct _CallbackRec {
- CallbackProcPtr proc;
- pointer data;
- Bool deleted;
- struct _CallbackRec *next;
-} CallbackRec, *CallbackPtr;
-
-typedef struct _CallbackList {
- int inCallback;
- Bool deleted;
- int numDeleted;
- CallbackPtr list;
-} CallbackListRec;
-
-/* proc vectors */
-
-extern _X_EXPORT int (* InitialVector[3]) (ClientPtr /*client*/);
-
-extern _X_EXPORT int (* ProcVector[256]) (ClientPtr /*client*/);
-
-extern _X_EXPORT int (* SwappedProcVector[256]) (ClientPtr /*client*/);
-
-extern _X_EXPORT ReplySwapPtr ReplySwapVector[256];
-
-extern _X_EXPORT int ProcBadRequest(ClientPtr /*client*/);
-
-#endif /* DIXSTRUCT_H */
+/*********************************************************** +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission 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 that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY 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 THIS +SOFTWARE. + +******************************************************************/ + +#ifndef DIXSTRUCT_H +#define DIXSTRUCT_H + +#include "client.h" +#include "dix.h" +#include "resource.h" +#include "cursor.h" +#include "gc.h" +#include "pixmap.h" +#include "privates.h" +#include <X11/Xmd.h> + +/* + * direct-mapped hash table, used by resource manager to store + * translation from client ids to server addresses. + */ + +extern _X_EXPORT CallbackListPtr ClientStateCallback; + +typedef struct { + ClientPtr client; + xConnSetupPrefix *prefix; + xConnSetup *setup; +} NewClientInfoRec; + +typedef void (*ReplySwapPtr) ( + ClientPtr /* pClient */, + int /* size */, + void * /* pbuf */); + +extern _X_EXPORT void ReplyNotSwappd ( + ClientPtr /* pClient */, + int /* size */, + void * /* pbuf */) _X_NORETURN; + +typedef enum {ClientStateInitial, + ClientStateAuthenticating, + ClientStateRunning, + ClientStateRetained, + ClientStateGone, + ClientStateCheckingSecurity, + ClientStateCheckedSecurity} ClientState; + +#ifdef XFIXES +typedef struct _saveSet { + struct _Window *windowPtr; + Bool toRoot; + Bool map; +} SaveSetElt; +#define SaveSetWindow(ss) ((ss).windowPtr) +#define SaveSetToRoot(ss) ((ss).toRoot) +#define SaveSetShouldMap(ss) ((ss).map) +#define SaveSetAssignWindow(ss,w) ((ss).windowPtr = (w)) +#define SaveSetAssignToRoot(ss,tr) ((ss).toRoot = (tr)) +#define SaveSetAssignMap(ss,m) ((ss).map = (m)) +#else +typedef struct _Window *SaveSetElt; +#define SaveSetWindow(ss) (ss) +#define SaveSetToRoot(ss) FALSE +#define SaveSetShouldMap(ss) TRUE +#define SaveSetAssignWindow(ss,w) ((ss) = (w)) +#define SaveSetAssignToRoot(ss,tr) +#define SaveSetAssignMap(ss,m) +#endif + +typedef struct _Client { + int index; + Mask clientAsMask; + pointer requestBuffer; + pointer osPrivate; /* for OS layer, including scheduler */ + Bool swapped; + ReplySwapPtr pSwapReplyFunc; + XID errorValue; + int sequence; + int closeDownMode; + int clientGone; + int noClientException; /* this client died or needs to be + * killed */ + int ignoreCount; /* count for Attend/IgnoreClient */ + SaveSetElt *saveSet; + int numSaved; + int (**requestVector) ( + ClientPtr /* pClient */); + CARD32 req_len; /* length of current request */ + Bool big_requests; /* supports large requests */ + int priority; + ClientState clientState; + PrivateRec *devPrivates; + unsigned short xkbClientFlags; + unsigned short mapNotifyMask; + unsigned short newKeyboardNotifyMask; + unsigned short vMajor,vMinor; + KeyCode minKC,maxKC; + + unsigned long replyBytesRemaining; + int smart_priority; + long smart_start_tick; + long smart_stop_tick; + long smart_check_tick; + + DeviceIntPtr clientPtr; + ClientIdPtr clientIds; +} ClientRec; + +/* + * Scheduling interface + */ +extern _X_EXPORT long SmartScheduleTime; +extern _X_EXPORT long SmartScheduleInterval; +extern _X_EXPORT long SmartScheduleSlice; +extern _X_EXPORT long SmartScheduleMaxSlice; +extern _X_EXPORT Bool SmartScheduleDisable; +extern _X_EXPORT void SmartScheduleStartTimer(void); +extern _X_EXPORT void SmartScheduleStopTimer(void); +#define SMART_MAX_PRIORITY (20) +#define SMART_MIN_PRIORITY (-20) + +extern _X_EXPORT void SmartScheduleInit(void); + + +/* This prototype is used pervasively in Xext, dix */ +#define DISPATCH_PROC(func) int func(ClientPtr /* client */) + +typedef struct _WorkQueue { + struct _WorkQueue *next; + Bool (*function) ( + ClientPtr /* pClient */, + pointer /* closure */ +); + ClientPtr client; + pointer closure; +} WorkQueueRec; + +extern _X_EXPORT TimeStamp currentTime; +extern _X_EXPORT TimeStamp lastDeviceEventTime; + +extern _X_EXPORT int CompareTimeStamps( + TimeStamp /*a*/, + TimeStamp /*b*/); + +extern _X_EXPORT TimeStamp ClientTimeToServerTime(CARD32 /*c*/); + +typedef struct _CallbackRec { + CallbackProcPtr proc; + pointer data; + Bool deleted; + struct _CallbackRec *next; +} CallbackRec, *CallbackPtr; + +typedef struct _CallbackList { + int inCallback; + Bool deleted; + int numDeleted; + CallbackPtr list; +} CallbackListRec; + +/* proc vectors */ + +extern _X_EXPORT int (* InitialVector[3]) (ClientPtr /*client*/); + +extern _X_EXPORT int (* ProcVector[256]) (ClientPtr /*client*/); + +extern _X_EXPORT int (* SwappedProcVector[256]) (ClientPtr /*client*/); + +extern _X_EXPORT ReplySwapPtr ReplySwapVector[256]; + +extern _X_EXPORT int ProcBadRequest(ClientPtr /*client*/); + +#endif /* DIXSTRUCT_H */ diff --git a/xorg-server/include/eventconvert.h b/xorg-server/include/eventconvert.h index b1196a00e..b000abc4b 100644 --- a/xorg-server/include/eventconvert.h +++ b/xorg-server/include/eventconvert.h @@ -30,7 +30,7 @@ #define FP1616(integral, frac) ((integral) * (1 << 16) + (frac) * (1 << 16)) -_X_EXPORT int EventToCore(InternalEvent *event, xEvent *core); +_X_EXPORT int EventToCore(InternalEvent *event, xEvent **core, int *count); _X_EXPORT int EventToXI(InternalEvent *ev, xEvent **xi, int *count); _X_EXPORT int EventToXI2(InternalEvent *ev, xEvent **xi); _X_INTERNAL int GetCoreType(InternalEvent* ev); diff --git a/xorg-server/include/input.h b/xorg-server/include/input.h index f96a0a988..643866f98 100644 --- a/xorg-server/include/input.h +++ b/xorg-server/include/input.h @@ -150,6 +150,11 @@ typedef void (*PointerAccelSchemeProc)( typedef void (*DeviceCallbackProc)( DeviceIntPtr /*pDev*/); +struct _ValuatorAccelerationRec; +typedef Bool (*PointerAccelSchemeInitProc)( + DeviceIntPtr /*dev*/, + struct _ValuatorAccelerationRec* /*protoScheme*/); + typedef struct _DeviceRec { pointer devicePrivate; ProcessInputProc processInputProc; /* current */ @@ -538,14 +543,15 @@ extern WindowPtr XYToWindow(SpritePtr pSprite, int x, int y); extern int EventIsDeliverable(DeviceIntPtr dev, InternalEvent* event, WindowPtr win); /** - * Return masks for EventIsDeliverable. + * Masks specifying the type of event to deliver for an InternalEvent; used + * by EventIsDeliverable. * @defgroup EventIsDeliverable return flags * @{ */ -#define XI_MASK (1 << 0) /**< XI mask set on window */ -#define CORE_MASK (1 << 1) /**< Core mask set on window */ -#define DONT_PROPAGATE_MASK (1 << 2) /**< DontPropagate mask set on window */ -#define XI2_MASK (1 << 3) /**< XI2 mask set on window */ +#define EVENT_XI1_MASK (1 << 0) /**< XI1.x event */ +#define EVENT_CORE_MASK (1 << 1) /**< Core event */ +#define EVENT_DONT_PROPAGATE_MASK (1 << 2) /**< DontPropagate mask set */ +#define EVENT_XI2_MASK (1 << 3) /**< XI2 mask set on window */ /* @} */ /* Implemented by the DDX. */ diff --git a/xorg-server/include/inputstr.h b/xorg-server/include/inputstr.h index b74ee0454..8509eb024 100644 --- a/xorg-server/include/inputstr.h +++ b/xorg-server/include/inputstr.h @@ -266,6 +266,7 @@ typedef struct _ValuatorAccelerationRec { int number; PointerAccelSchemeProc AccelSchemeProc; void *accelData; /* at disposal of AccelScheme */ + PointerAccelSchemeInitProc AccelInitProc; DeviceCallbackProc AccelCleanupProc; } ValuatorAccelerationRec, *ValuatorAccelerationPtr; @@ -493,6 +494,7 @@ typedef struct _SpriteInfoRec { #define MASTER_POINTER 1 #define MASTER_KEYBOARD 2 #define SLAVE 3 +#define MASTER_ATTACHED 4 /* special type for GetMaster */ typedef struct _DeviceIntRec { DeviceRec public; @@ -529,10 +531,8 @@ typedef struct _DeviceIntRec { PrivateRec *devPrivates; DeviceUnwrapProc unwrapProc; SpriteInfoPtr spriteInfo; - union { - DeviceIntPtr master; /* master device */ - DeviceIntPtr lastSlave; /* last slave device used */ - } u; + DeviceIntPtr master; /* master device */ + DeviceIntPtr lastSlave; /* last slave device used */ /* last valuator values recorded, not posted to client; * for slave devices, valuators is in device coordinates diff --git a/xorg-server/include/list.h b/xorg-server/include/list.h index 9479d2d92..5933b973d 100644 --- a/xorg-server/include/list.h +++ b/xorg-server/include/list.h @@ -1,103 +1,281 @@ -/*
- * Copyright © 2010 Intel Corporation
- * Copyright © 2010 Francisco Jerez <currojerez@riseup.net>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- *
- */
-
-#ifndef _LIST_H_
-#define _LIST_H_
-
-/* classic doubly-link circular list */
-struct list {
- struct list *next, *prev;
-};
-
-static void
-list_init(struct list *list)
-{
- list->next = list->prev = list;
-}
-
-static inline void
-__list_add(struct list *entry,
- struct list *prev,
- struct list *next)
-{
- next->prev = entry;
- entry->next = next;
- entry->prev = prev;
- prev->next = entry;
-}
-
-static inline void
-list_add(struct list *entry, struct list *head)
-{
- __list_add(entry, head, head->next);
-}
-
-static inline void
-__list_del(struct list *prev, struct list *next)
-{
- next->prev = prev;
- prev->next = next;
-}
-
-static inline void
-list_del(struct list *entry)
-{
- __list_del(entry->prev, entry->next);
- list_init(entry);
-}
-
-static inline Bool
-list_is_empty(struct list *head)
-{
- return head->next == head;
-}
-
-#ifndef container_of
-#define container_of(ptr, type, member) \
- (type *)((char *)(ptr) - (char *) &((type *)0)->member)
-#endif
-
-#define list_entry(ptr, type, member) \
- container_of(ptr, type, member)
-
-#define list_first_entry(ptr, type, member) \
- list_entry((ptr)->next, type, member)
-
-#define __container_of(ptr, sample, member) \
- (void *)((char *)(ptr) \
- - ((char *)&(sample)->member - (char *)(sample)))
-
-#define list_for_each_entry(pos, head, member) \
- for (pos = __container_of((head)->next, pos, member); \
- &pos->member != (head); \
- pos = __container_of(pos->member.next, pos, member))
-
-#define list_for_each_entry_safe(pos, tmp, head, member) \
- for (pos = __container_of((head)->next, pos, member), \
- tmp = __container_of(pos->member.next, pos, member); \
- &pos->member != (head); \
- pos = tmp, tmp = __container_of(pos->member.next, tmp, member))
-
-#endif
+/* + * Copyright © 2010 Intel Corporation + * Copyright © 2010 Francisco Jerez <currojerez@riseup.net> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + */ + +#ifndef _LIST_H_ +#define _LIST_H_ + +/** + * @file Classic doubly-link circular list implementation. + * + * Example: + * We need to keep a list of struct foo in the parent struct bar, i.e. what + * we want is something like this. + * + * struct bar { + * ... + * struct foo *foos; -----> struct foo {}, struct foo {}, struct foo{} + * ... + * } + * + * We need one list head in bar and a list element in all foos (both are of + * data type 'struct list'). + * + * struct bar { + * ... + * struct list foos; + * ... + * } + * + * struct foo { + * ... + * struct list entry; + * ... + * } + * + * Now we initialize the list head: + * + * struct bar bar; + * ... + * list_init(&bar.foos); + * + * Then we create the first element and add it to this list: + * + * struct foo *foo = malloc(...); + * .... + * list_add(&foo->entry, &bar.foos); + * + * Repeat the above for each element you want to add to the list. Deleting + * works with the element itself. + * list_del(&foo->entry); + * free(foo); + * + * Note: calling list_del(&bar.foos) will set bar.foos to an empty + * list again. + * + * Looping through the list requires a 'struct foo' as iterator and the + * name of the field the subnodes use. + * + * struct foo *iterator; + * list_for_each_entry(iterator, &bar.foos, entry) { + * if (iterator->something == ...) + * ... + * } + * + * Note: You must not call list_del() on the iterator if you continue the + * loop. You need to run the safe for-each loop instead: + * + * struct foo *iterator, *next; + * list_for_each_entry_safe(iterator, next, &bar.foos, entry) { + * if (...) + * list_del(&iterator->entry); + * } + * + */ + +/** + * The linkage struct for list nodes. This struct must be part of your + * to-be-linked struct. + * + * Example: + * struct foo { + * int a; + * void *b; + * struct list *mylist; + * } + * + * Position and name of the struct list field is irrelevant. + * There are no requirements that elements of a list are of the same type. + * There are no requirements for a list head, any struct list can be a list + * head. + */ +struct list { + struct list *next, *prev; +}; + +/** + * Initialize the list as an empty list. + * + * Example: + * list_init(&foo->mylist); + * + * @param The list to initialized. + */ +static void +list_init(struct list *list) +{ + list->next = list->prev = list; +} + +static inline void +__list_add(struct list *entry, + struct list *prev, + struct list *next) +{ + next->prev = entry; + entry->next = next; + entry->prev = prev; + prev->next = entry; +} + +/** + * Insert a new element after the given list head. + * The list changes from: + * head → some element → ... + * to + * head → new element → older element → ... + * + * Example: + * struct foo *newfoo = malloc(...); + * list_add(&newfoo->mylist, &foo->mylist); + * + * @param entry The new element to prepend to the list. + * @param head The existing list. + */ +static inline void +list_add(struct list *entry, struct list *head) +{ + __list_add(entry, head, head->next); +} + +static inline void +__list_del(struct list *prev, struct list *next) +{ + next->prev = prev; + prev->next = next; +} + +/** + * Remove the element from the list it is in. Using this function will reset + * the pointers to/from this element so it is removed from the list. It does + * NOT free the element itself or manipulate it otherwise. + * + * Using list_del on a pure list head (like in the example at the top of + * this file) will NOT remove the first element from + * the list but rather reset the list as empty list. + * + * Example: + * list_del(&newfoo->mylist); + * + * @param entry The element to remove. + */ +static inline void +list_del(struct list *entry) +{ + __list_del(entry->prev, entry->next); + list_init(entry); +} + +/** + * Check if the list is empty. + * + * Example: + * list_is_empty(&foo->mylist); + * + * @return True if the list contains one or more elements or False otherwise. + */ +static inline Bool +list_is_empty(struct list *head) +{ + return head->next == head; +} + +/** + * Returns a pointer to the container of this list element. + * + * Example: + * struct foo* f; + * f = container_of(&foo->mylist, struct foo, mylist); + * assert(f == foo); + * + * @param ptr Pointer to the struct list. + * @param type Data type of the list element. + * @param member Member name of the struct list field in the list element. + * @return A pointer to the data struct containing the list head. + */ +#ifndef container_of +#define container_of(ptr, type, member) \ + (type *)((char *)(ptr) - (char *) &((type *)0)->member) +#endif + +/** + * Alias of container_of + */ +#define list_entry(ptr, type, member) \ + container_of(ptr, type, member) + +/** + * Retrieve the first list entry for the given list pointer. + * + * Example: + * struct foo *first; + * first = list_first_entry(&foo->mylist, struct foo, mylist); + * + * @param ptr The list head + * @param type Data type of the list element to retrieve + * @param member Member name of the struct list field in the list element. + * @return A pointer to the first list element. + */ +#define list_first_entry(ptr, type, member) \ + list_entry((ptr)->next, type, member) + +#define __container_of(ptr, sample, member) \ + (void *)((char *)(ptr) \ + - ((char *)&(sample)->member - (char *)(sample))) +/** + * Loop through the list given by head and set pos to struct in the list. + * + * Example: + * struct foo *iterator; + * list_for_each_entry(iterator, &foo->mylist, mylist) { + * [modify iterator] + * } + * + * This macro is not safe for node deletion. Use list_for_each_entry_safe + * instead. + * + * @param pos Iterator variable of the type of the list elements. + * @param head List head + * @param member Member name of the struct list in the list elements. + * + */ +#define list_for_each_entry(pos, head, member) \ + for (pos = __container_of((head)->next, pos, member); \ + &pos->member != (head); \ + pos = __container_of(pos->member.next, pos, member)) + +/** + * Loop through the list, keeping a backup pointer to the element. This + * macro allows for the deletion of a list element while looping through the + * list. + * + * See list_for_each_entry for more details. + */ +#define list_for_each_entry_safe(pos, tmp, head, member) \ + for (pos = __container_of((head)->next, pos, member), \ + tmp = __container_of(pos->member.next, pos, member); \ + &pos->member != (head); \ + pos = tmp, tmp = __container_of(pos->member.next, tmp, member)) + +#endif diff --git a/xorg-server/include/protocol-versions.h b/xorg-server/include/protocol-versions.h index 1d33bddcf..8692ded8a 100644 --- a/xorg-server/include/protocol-versions.h +++ b/xorg-server/include/protocol-versions.h @@ -104,10 +104,6 @@ #define SERVER_WINDOWSWM_MINOR_VERSION 0 #define SERVER_WINDOWSWM_PATCH_VERSION 0 -/* Xcalibrate */ -#define SERVER_XCALIBRATE_MAJOR_VERSION 0 -#define SERVER_XCALIBRATE_MINOR_VERSION 1 - /* DGA */ #define SERVER_XDGA_MAJOR_VERSION 2 #define SERVER_XDGA_MINOR_VERSION 0 diff --git a/xorg-server/include/ptrveloc.h b/xorg-server/include/ptrveloc.h index 6f999a88f..8c59c0361 100644 --- a/xorg-server/include/ptrveloc.h +++ b/xorg-server/include/ptrveloc.h @@ -110,12 +110,6 @@ BasicComputeAcceleration(DeviceIntPtr dev, DeviceVelocityPtr vel, extern _X_EXPORT void FreeVelocityData(DeviceVelocityPtr vel); -extern _X_INTERNAL BOOL -InitializePredictableAccelerationProperties(DeviceIntPtr dev); - -extern _X_INTERNAL BOOL -DeletePredictableAccelerationProperties(DeviceIntPtr dev); - extern _X_EXPORT int SetAccelerationProfile(DeviceVelocityPtr vel, int profile_num); @@ -129,6 +123,10 @@ SetDeviceSpecificAccelerationProfile(DeviceVelocityPtr vel, extern _X_INTERNAL void AccelerationDefaultCleanup(DeviceIntPtr dev); +extern _X_INTERNAL Bool +InitPredictableAccelerationScheme(DeviceIntPtr dev, + struct _ValuatorAccelerationRec* protoScheme); + extern _X_INTERNAL void acceleratePointerPredictable(DeviceIntPtr dev, int first_valuator, int num_valuators, int *valuators, int evtime); diff --git a/xorg-server/include/regionstr.h b/xorg-server/include/regionstr.h index 92f4ca9f2..3759fe17b 100644 --- a/xorg-server/include/regionstr.h +++ b/xorg-server/include/regionstr.h @@ -1,370 +1,360 @@ -/***********************************************************
-
-Copyright 1987, 1998 The Open Group
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation.
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
-AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of The Open Group shall not be
-used in advertising or otherwise to promote the sale, use or other dealings
-in this Software without prior written authorization from The Open Group.
-
-
-Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
-
- All Rights Reserved
-
-Permission 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 that
-both that copyright notice and this permission notice appear in
-supporting documentation, and that the name of Digital not be
-used in advertising or publicity pertaining to distribution of the
-software without specific, written prior permission.
-
-DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
-ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
-DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
-ANY 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 THIS
-SOFTWARE.
-
-******************************************************************/
-
-#ifndef REGIONSTRUCT_H
-#define REGIONSTRUCT_H
-
-typedef struct pixman_region16 RegionRec, *RegionPtr;
-
-#include "miscstruct.h"
-
-/* Return values from RectIn() */
-
-#define rgnOUT 0
-#define rgnIN 1
-#define rgnPART 2
-
-#define NullRegion ((RegionPtr)0)
-
-/*
- * clip region
- */
-
-typedef struct pixman_region16_data RegDataRec, *RegDataPtr;
-
-extern _X_EXPORT BoxRec RegionEmptyBox;
-extern _X_EXPORT RegDataRec RegionEmptyData;
-extern _X_EXPORT RegDataRec RegionBrokenData;
-static inline Bool RegionNil(RegionPtr reg) {
- return ((reg)->data && !(reg)->data->numRects);
-}
-
-/* not a region */
-
-static inline Bool RegionNar(RegionPtr reg) {
- return ((reg)->data == &RegionBrokenData);
-}
-
-static inline int RegionNumRects(RegionPtr reg) {
- return ((reg)->data ? (reg)->data->numRects : 1);
-}
-
-static inline int RegionSize(RegionPtr reg) {
- return ((reg)->data ? (reg)->data->size : 0);
-}
-
-static inline BoxPtr RegionRects(RegionPtr reg) {
- return ((reg)->data ? (BoxPtr)((reg)->data + 1) : &(reg)->extents);
-}
-
-static inline BoxPtr RegionBoxptr(RegionPtr reg) {
- return ((BoxPtr)((reg)->data + 1));
-}
-
-static inline BoxPtr RegionBox(RegionPtr reg, int i) {
- return (&RegionBoxptr(reg)[i]);
-}
-
-static inline BoxPtr RegionTop(RegionPtr reg) {
- return RegionBox(reg, (reg)->data->numRects);
-}
-
-static inline BoxPtr RegionEnd(RegionPtr reg) {
- return RegionBox(reg, (reg)->data->numRects - 1);
-}
-
-static inline size_t RegionSizeof(int n) {
- return (sizeof(RegDataRec) + ((n) * sizeof(BoxRec)));
-}
-
-static inline void RegionInit(RegionPtr _pReg, BoxPtr _rect, int _size)
-{
- if ((_rect) != NULL)
- {
- (_pReg)->extents = *(_rect);
- (_pReg)->data = (RegDataPtr)NULL;
- }
- else
- {
- (_pReg)->extents = RegionEmptyBox;
- if (((_size) > 1) && ((_pReg)->data =
- (RegDataPtr)malloc(RegionSizeof(_size))))
- {
- (_pReg)->data->size = (_size);
- (_pReg)->data->numRects = 0;
- }
- else
- (_pReg)->data = &RegionEmptyData;
- }
-}
-
-static inline void RegionUninit(RegionPtr _pReg)
-{
- if ((_pReg)->data && (_pReg)->data->size) {
- free((_pReg)->data);
- (_pReg)->data = NULL;
- }
-}
-
-static inline void RegionReset(RegionPtr _pReg, BoxPtr _pBox)
-{
- (_pReg)->extents = *(_pBox);
- RegionUninit(_pReg);
- (_pReg)->data = (RegDataPtr)NULL;
-}
-
-static inline Bool RegionNotEmpty(RegionPtr _pReg) {
- return !RegionNil(_pReg);
-}
-
-static inline Bool RegionBroken(RegionPtr _pReg) {
- return RegionNar(_pReg);
-}
-
-static inline void RegionEmpty(RegionPtr _pReg)
-{
- RegionUninit(_pReg);
- (_pReg)->extents.x2 = (_pReg)->extents.x1;
- (_pReg)->extents.y2 = (_pReg)->extents.y1;
- (_pReg)->data = &RegionEmptyData;
-}
-
-static inline BoxPtr RegionExtents(RegionPtr _pReg)
-{
- return (&(_pReg)->extents);
-}
-
-static inline void RegionNull(RegionPtr _pReg)
-{
- (_pReg)->extents = RegionEmptyBox;
- (_pReg)->data = &RegionEmptyData;
-}
-
-extern _X_EXPORT void InitRegions(void);
-
-extern _X_EXPORT RegionPtr RegionCreate(
- BoxPtr /*rect*/,
- int /*size*/);
-
-extern _X_EXPORT void RegionDestroy(
- RegionPtr /*pReg*/);
-
-static inline Bool
-RegionCopy(RegionPtr dst, RegionPtr src)
-{
- return pixman_region_copy (dst, src);
-}
-
-static inline Bool
-RegionIntersect(
- RegionPtr newReg, /* destination Region */
- RegionPtr reg1,
- RegionPtr reg2 /* source regions */
- )
-{
- return pixman_region_intersect (newReg, reg1, reg2);
-}
-
-static inline Bool
-RegionUnion(
- RegionPtr newReg, /* destination Region */
- RegionPtr reg1,
- RegionPtr reg2 /* source regions */
- )
-{
- return pixman_region_union (newReg, reg1, reg2);
-}
-
-extern _X_EXPORT Bool RegionAppend(
- RegionPtr /*dstrgn*/,
- RegionPtr /*rgn*/);
-
-extern _X_EXPORT Bool RegionValidate(
- RegionPtr /*badreg*/,
- Bool * /*pOverlap*/);
-
-extern _X_EXPORT RegionPtr RegionFromRects(
- int /*nrects*/,
- xRectanglePtr /*prect*/,
- int /*ctype*/);
-
-/*-
- *-----------------------------------------------------------------------
- * Subtract --
- * Subtract regS from regM and leave the result in regD.
- * S stands for subtrahend, M for minuend and D for difference.
- *
- * Results:
- * TRUE if successful.
- *
- * Side Effects:
- * regD is overwritten.
- *
- *-----------------------------------------------------------------------
- */
-static inline Bool
-RegionSubtract(RegionPtr regD, RegionPtr regM, RegionPtr regS)
-{
- return pixman_region_subtract (regD, regM, regS);
-}
-
-/*-
- *-----------------------------------------------------------------------
- * Inverse --
- * Take a region and a box and return a region that is everything
- * in the box but not in the region. The careful reader will note
- * that this is the same as subtracting the region from the box...
- *
- * Results:
- * TRUE.
- *
- * Side Effects:
- * newReg is overwritten.
- *
- *-----------------------------------------------------------------------
- */
-
-static inline Bool
-RegionInverse(
- RegionPtr newReg, /* Destination region */
- RegionPtr reg1, /* Region to invert */
- BoxPtr invRect /* Bounding box for inversion */
- )
-{
- return pixman_region_inverse (newReg, reg1, invRect);
-}
-
-static inline int
-RegionContainsRect(RegionPtr region, BoxPtr prect)
-{
- return pixman_region_contains_rectangle (region, prect);
-}
-
-/* TranslateRegion(pReg, x, y)
- translates in place
-*/
-
-static inline void
-RegionTranslate(RegionPtr pReg, int x, int y)
-{
- pixman_region_translate (pReg, x, y);
-}
-
-extern _X_EXPORT Bool RegionBreak(
- RegionPtr /*pReg*/);
-
-static inline Bool
-RegionContainsPoint(
- RegionPtr pReg,
- int x,
- int y,
- BoxPtr box /* "return" value */
- )
-{
- return pixman_region_contains_point (pReg, x, y, box);
-}
-
-static inline Bool
-RegionEqual(RegionPtr reg1, RegionPtr reg2)
-{
- return pixman_region_equal (reg1, reg2);
-}
-
-extern _X_EXPORT Bool RegionRectAlloc(
- RegionPtr /*pRgn*/,
- int /*n*/
-);
-
-#ifdef DEBUG
-extern _X_EXPORT Bool RegionIsValid(
- RegionPtr /*prgn*/
-);
-#endif
-
-extern _X_EXPORT void RegionPrint(
- RegionPtr /*pReg*/);
-
-extern _X_EXPORT int RegionClipSpans(
- RegionPtr /*prgnDst*/,
- DDXPointPtr /*ppt*/,
- int * /*pwidth*/,
- int /*nspans*/,
- DDXPointPtr /*pptNew*/,
- int * /*pwidthNew*/,
- int /*fSorted*/
-);
-
-#define INCLUDE_LEGACY_REGION_DEFINES
-#ifdef INCLUDE_LEGACY_REGION_DEFINES
-
-#define REGION_NIL RegionNil
-#define REGION_NAR RegionNar
-#define REGION_NUM_RECTS RegionNumRects
-#define REGION_SIZE RegionSize
-#define REGION_RECTS RegionRects
-#define REGION_BOXPTR RegionBoxptr
-#define REGION_BOX RegionBox
-#define REGION_TOP RegionTop
-#define REGION_END RegionEnd
-#define REGION_SZOF RegionSizeof
-#define BITMAP_TO_REGION BitmapToRegion
-#define REGION_CREATE(pScreen, r, s) RegionCreate(r,s)
-#define REGION_COPY(pScreen, d, r) RegionCopy(d, r)
-#define REGION_DESTROY(pScreen, r) RegionDestroy(r)
-#define REGION_INTERSECT(pScreen, res, r1, r2) RegionIntersect(res, r1, r2)
-#define REGION_UNION(pScreen, res, r1, r2) RegionUnion(res, r1, r2)
-#define REGION_SUBTRACT(pScreen, res, r1, r2) RegionSubtract(res, r1, r2)
-#define REGION_INVERSE(pScreen, n, r, b) RegionInverse(n, r, b)
-#define REGION_TRANSLATE(pScreen, r, x, y) RegionTranslate(r, x, y)
-#define RECT_IN_REGION(pScreen, r, b) RegionContainsRect(r, b)
-#define POINT_IN_REGION(pScreen, r, x, y, b) RegionContainsPoint(r, x, y, b)
-#define REGION_EQUAL(pScreen, r1, r2) RegionEqual(r1, r2)
-#define REGION_APPEND(pScreen, d, r) RegionAppend(d, r)
-#define REGION_VALIDATE(pScreen, r, o) RegionValidate(r, o)
-#define RECTS_TO_REGION(pScreen, n, r, c) RegionFromRects(n, r, c)
-#define REGION_BREAK(pScreen, r) RegionBreak(r)
-#define REGION_INIT(pScreen, r, b, s) RegionInit(r, b, s)
-#define REGION_UNINIT(pScreen, r) RegionUninit(r)
-#define REGION_RESET(pScreen, r, b) RegionReset(r, b)
-#define REGION_NOTEMPTY(pScreen, r) RegionNotEmpty(r)
-#define REGION_BROKEN(pScreen, r) RegionBroken(r)
-#define REGION_EMPTY(pScreen, r) RegionEmpty(r)
-#define REGION_EXTENTS(pScreen, r) RegionExtents(r)
-#define REGION_NULL(pScreen, r) RegionNull(r)
-
-#endif /* INCLUDE_LEGACY_REGION_DEFINES */
-#endif /* REGIONSTRUCT_H */
+/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission 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 that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY 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 THIS +SOFTWARE. + +******************************************************************/ + +#ifndef REGIONSTRUCT_H +#define REGIONSTRUCT_H + +typedef struct pixman_region16 RegionRec, *RegionPtr; + +#include "miscstruct.h" + +/* Return values from RectIn() */ + +#define rgnOUT 0 +#define rgnIN 1 +#define rgnPART 2 + +#define NullRegion ((RegionPtr)0) + +/* + * clip region + */ + +typedef struct pixman_region16_data RegDataRec, *RegDataPtr; + +extern _X_EXPORT BoxRec RegionEmptyBox; +extern _X_EXPORT RegDataRec RegionEmptyData; +extern _X_EXPORT RegDataRec RegionBrokenData; +static inline Bool RegionNil(RegionPtr reg) { + return ((reg)->data && !(reg)->data->numRects); +} + +/* not a region */ + +static inline Bool RegionNar(RegionPtr reg) { + return ((reg)->data == &RegionBrokenData); +} + +static inline int RegionNumRects(RegionPtr reg) { + return ((reg)->data ? (reg)->data->numRects : 1); +} + +static inline int RegionSize(RegionPtr reg) { + return ((reg)->data ? (reg)->data->size : 0); +} + +static inline BoxPtr RegionRects(RegionPtr reg) { + return ((reg)->data ? (BoxPtr)((reg)->data + 1) : &(reg)->extents); +} + +static inline BoxPtr RegionBoxptr(RegionPtr reg) { + return ((BoxPtr)((reg)->data + 1)); +} + +static inline BoxPtr RegionBox(RegionPtr reg, int i) { + return (&RegionBoxptr(reg)[i]); +} + +static inline BoxPtr RegionTop(RegionPtr reg) { + return RegionBox(reg, (reg)->data->numRects); +} + +static inline BoxPtr RegionEnd(RegionPtr reg) { + return RegionBox(reg, (reg)->data->numRects - 1); +} + +static inline size_t RegionSizeof(int n) { + return (sizeof(RegDataRec) + ((n) * sizeof(BoxRec))); +} + +static inline void RegionInit(RegionPtr _pReg, BoxPtr _rect, int _size) +{ + if ((_rect) != NULL) + { + (_pReg)->extents = *(_rect); + (_pReg)->data = (RegDataPtr)NULL; + } + else + { + (_pReg)->extents = RegionEmptyBox; + if (((_size) > 1) && ((_pReg)->data = + (RegDataPtr)malloc(RegionSizeof(_size)))) + { + (_pReg)->data->size = (_size); + (_pReg)->data->numRects = 0; + } + else + (_pReg)->data = &RegionEmptyData; + } +} + +static inline void RegionUninit(RegionPtr _pReg) +{ + if ((_pReg)->data && (_pReg)->data->size) { + free((_pReg)->data); + (_pReg)->data = NULL; + } +} + +static inline void RegionReset(RegionPtr _pReg, BoxPtr _pBox) +{ + (_pReg)->extents = *(_pBox); + RegionUninit(_pReg); + (_pReg)->data = (RegDataPtr)NULL; +} + +static inline Bool RegionNotEmpty(RegionPtr _pReg) { + return !RegionNil(_pReg); +} + +static inline Bool RegionBroken(RegionPtr _pReg) { + return RegionNar(_pReg); +} + +static inline void RegionEmpty(RegionPtr _pReg) +{ + RegionUninit(_pReg); + (_pReg)->extents.x2 = (_pReg)->extents.x1; + (_pReg)->extents.y2 = (_pReg)->extents.y1; + (_pReg)->data = &RegionEmptyData; +} + +static inline BoxPtr RegionExtents(RegionPtr _pReg) +{ + return (&(_pReg)->extents); +} + +static inline void RegionNull(RegionPtr _pReg) +{ + (_pReg)->extents = RegionEmptyBox; + (_pReg)->data = &RegionEmptyData; +} + +extern _X_EXPORT void InitRegions(void); + +extern _X_EXPORT RegionPtr RegionCreate( + BoxPtr /*rect*/, + int /*size*/); + +extern _X_EXPORT void RegionDestroy( + RegionPtr /*pReg*/); + +static inline Bool +RegionCopy(RegionPtr dst, RegionPtr src) +{ + return pixman_region_copy (dst, src); +} + +static inline Bool +RegionIntersect( + RegionPtr newReg, /* destination Region */ + RegionPtr reg1, + RegionPtr reg2 /* source regions */ + ) +{ + return pixman_region_intersect (newReg, reg1, reg2); +} + +static inline Bool +RegionUnion( + RegionPtr newReg, /* destination Region */ + RegionPtr reg1, + RegionPtr reg2 /* source regions */ + ) +{ + return pixman_region_union (newReg, reg1, reg2); +} + +extern _X_EXPORT Bool RegionAppend( + RegionPtr /*dstrgn*/, + RegionPtr /*rgn*/); + +extern _X_EXPORT Bool RegionValidate( + RegionPtr /*badreg*/, + Bool * /*pOverlap*/); + +extern _X_EXPORT RegionPtr RegionFromRects( + int /*nrects*/, + xRectanglePtr /*prect*/, + int /*ctype*/); + +/*- + *----------------------------------------------------------------------- + * Subtract -- + * Subtract regS from regM and leave the result in regD. + * S stands for subtrahend, M for minuend and D for difference. + * + * Results: + * TRUE if successful. + * + * Side Effects: + * regD is overwritten. + * + *----------------------------------------------------------------------- + */ +static inline Bool +RegionSubtract(RegionPtr regD, RegionPtr regM, RegionPtr regS) +{ + return pixman_region_subtract (regD, regM, regS); +} + +/*- + *----------------------------------------------------------------------- + * Inverse -- + * Take a region and a box and return a region that is everything + * in the box but not in the region. The careful reader will note + * that this is the same as subtracting the region from the box... + * + * Results: + * TRUE. + * + * Side Effects: + * newReg is overwritten. + * + *----------------------------------------------------------------------- + */ + +static inline Bool +RegionInverse( + RegionPtr newReg, /* Destination region */ + RegionPtr reg1, /* Region to invert */ + BoxPtr invRect /* Bounding box for inversion */ + ) +{ + return pixman_region_inverse (newReg, reg1, invRect); +} + +static inline int +RegionContainsRect(RegionPtr region, BoxPtr prect) +{ + return pixman_region_contains_rectangle (region, prect); +} + +/* TranslateRegion(pReg, x, y) + translates in place +*/ + +static inline void +RegionTranslate(RegionPtr pReg, int x, int y) +{ + pixman_region_translate (pReg, x, y); +} + +extern _X_EXPORT Bool RegionBreak( + RegionPtr /*pReg*/); + +static inline Bool +RegionContainsPoint( + RegionPtr pReg, + int x, + int y, + BoxPtr box /* "return" value */ + ) +{ + return pixman_region_contains_point (pReg, x, y, box); +} + +static inline Bool +RegionEqual(RegionPtr reg1, RegionPtr reg2) +{ + return pixman_region_equal (reg1, reg2); +} + +extern _X_EXPORT Bool RegionRectAlloc( + RegionPtr /*pRgn*/, + int /*n*/ +); + +#ifdef DEBUG +extern _X_EXPORT Bool RegionIsValid( + RegionPtr /*prgn*/ +); +#endif + +extern _X_EXPORT void RegionPrint( + RegionPtr /*pReg*/); + +#define INCLUDE_LEGACY_REGION_DEFINES +#ifdef INCLUDE_LEGACY_REGION_DEFINES + +#define REGION_NIL RegionNil +#define REGION_NAR RegionNar +#define REGION_NUM_RECTS RegionNumRects +#define REGION_SIZE RegionSize +#define REGION_RECTS RegionRects +#define REGION_BOXPTR RegionBoxptr +#define REGION_BOX RegionBox +#define REGION_TOP RegionTop +#define REGION_END RegionEnd +#define REGION_SZOF RegionSizeof +#define BITMAP_TO_REGION BitmapToRegion +#define REGION_CREATE(pScreen, r, s) RegionCreate(r,s) +#define REGION_COPY(pScreen, d, r) RegionCopy(d, r) +#define REGION_DESTROY(pScreen, r) RegionDestroy(r) +#define REGION_INTERSECT(pScreen, res, r1, r2) RegionIntersect(res, r1, r2) +#define REGION_UNION(pScreen, res, r1, r2) RegionUnion(res, r1, r2) +#define REGION_SUBTRACT(pScreen, res, r1, r2) RegionSubtract(res, r1, r2) +#define REGION_INVERSE(pScreen, n, r, b) RegionInverse(n, r, b) +#define REGION_TRANSLATE(pScreen, r, x, y) RegionTranslate(r, x, y) +#define RECT_IN_REGION(pScreen, r, b) RegionContainsRect(r, b) +#define POINT_IN_REGION(pScreen, r, x, y, b) RegionContainsPoint(r, x, y, b) +#define REGION_EQUAL(pScreen, r1, r2) RegionEqual(r1, r2) +#define REGION_APPEND(pScreen, d, r) RegionAppend(d, r) +#define REGION_VALIDATE(pScreen, r, o) RegionValidate(r, o) +#define RECTS_TO_REGION(pScreen, n, r, c) RegionFromRects(n, r, c) +#define REGION_BREAK(pScreen, r) RegionBreak(r) +#define REGION_INIT(pScreen, r, b, s) RegionInit(r, b, s) +#define REGION_UNINIT(pScreen, r) RegionUninit(r) +#define REGION_RESET(pScreen, r, b) RegionReset(r, b) +#define REGION_NOTEMPTY(pScreen, r) RegionNotEmpty(r) +#define REGION_BROKEN(pScreen, r) RegionBroken(r) +#define REGION_EMPTY(pScreen, r) RegionEmpty(r) +#define REGION_EXTENTS(pScreen, r) RegionExtents(r) +#define REGION_NULL(pScreen, r) RegionNull(r) + +#endif /* INCLUDE_LEGACY_REGION_DEFINES */ +#endif /* REGIONSTRUCT_H */ diff --git a/xorg-server/include/xkbsrv.h b/xorg-server/include/xkbsrv.h index a7f17d44c..422bae014 100644 --- a/xorg-server/include/xkbsrv.h +++ b/xorg-server/include/xkbsrv.h @@ -1,986 +1,982 @@ -/************************************************************
-Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc.
-
-Permission 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 that both that copyright
-notice and this permission notice appear in supporting
-documentation, and that the name of Silicon Graphics not be
-used in advertising or publicity pertaining to distribution
-of the software without specific prior written permission.
-Silicon Graphics makes no representation about the suitability
-of this software for any purpose. It is provided "as is"
-without any express or implied warranty.
-
-SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
-SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
-AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
-GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
-DAMAGES OR ANY 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 THIS SOFTWARE.
-
-********************************************************/
-
-#ifndef _XKBSRV_H_
-#define _XKBSRV_H_
-
-#define XkbAllocClientMap SrvXkbAllocClientMap
-#define XkbAllocServerMap SrvXkbAllocServerMap
-#define XkbChangeTypesOfKey SrvXkbChangeTypesOfKey
-#define XkbCopyKeyTypes SrvXkbCopyKeyTypes
-#define XkbFreeClientMap SrvXkbFreeClientMap
-#define XkbFreeServerMap SrvXkbFreeServerMap
-#define XkbKeyTypesForCoreSymbols SrvXkbKeyTypesForCoreSymbols
-#define XkbApplyCompatMapToKey SrvXkbApplyCompatMapToKey
-#define XkbResizeKeyActions SrvXkbResizeKeyActions
-#define XkbResizeKeySyms SrvXkbResizeKeySyms
-#define XkbResizeKeyType SrvXkbResizeKeyType
-#define XkbAllocCompatMap SrvXkbAllocCompatMap
-#define XkbAllocControls SrvXkbAllocControls
-#define XkbAllocIndicatorMaps SrvXkbAllocIndicatorMaps
-#define XkbAllocKeyboard SrvXkbAllocKeyboard
-#define XkbAllocNames SrvXkbAllocNames
-#define XkbFreeCompatMap SrvXkbFreeCompatMap
-#define XkbFreeKeyboard SrvXkbFreeKeyboard
-#define XkbFreeNames SrvXkbFreeNames
-#define XkbLatchModifiers SrvXkbLatchModifiers
-#define XkbLatchGroup SrvXkbLatchGroup
-#define XkbVirtualModsToReal SrvXkbVirtualModsToReal
-#define XkbChangeKeycodeRange SrvXkbChangeKeycodeRange
-#define XkbApplyVirtualModChanges SrvXkbApplyVirtualModChanges
-
-#include <X11/extensions/XKBproto.h>
-#include "xkbstr.h"
-#include "xkbrules.h"
-#include "inputstr.h"
-#include "events.h"
-
-typedef struct _XkbInterest {
- DeviceIntPtr dev;
- ClientPtr client;
- XID resource;
- struct _XkbInterest * next;
- CARD16 extDevNotifyMask;
- CARD16 stateNotifyMask;
- CARD16 namesNotifyMask;
- CARD32 ctrlsNotifyMask;
- CARD8 compatNotifyMask;
- BOOL bellNotifyMask;
- BOOL actionMessageMask;
- CARD16 accessXNotifyMask;
- CARD32 iStateNotifyMask;
- CARD32 iMapNotifyMask;
- CARD16 altSymsNotifyMask;
- CARD32 autoCtrls;
- CARD32 autoCtrlValues;
-} XkbInterestRec,*XkbInterestPtr;
-
-typedef struct _XkbRadioGroup {
- CARD8 flags;
- CARD8 nMembers;
- CARD8 dfltDown;
- CARD8 currentDown;
- CARD8 members[XkbRGMaxMembers];
-} XkbRadioGroupRec, *XkbRadioGroupPtr;
-
-typedef struct _XkbEventCause {
- CARD8 kc;
- CARD8 event;
- CARD8 mjr;
- CARD8 mnr;
- ClientPtr client;
-} XkbEventCauseRec,*XkbEventCausePtr;
-#define XkbSetCauseKey(c,k,e) { (c)->kc= (k),(c)->event= (e),\
- (c)->mjr= (c)->mnr= 0; \
- (c)->client= NULL; }
-#define XkbSetCauseReq(c,j,n,cl) { (c)->kc= (c)->event= 0,\
- (c)->mjr= (j),(c)->mnr= (n);\
- (c)->client= (cl); }
-#define XkbSetCauseCoreReq(c,e,cl) XkbSetCauseReq(c,e,0,cl)
-#define XkbSetCauseXkbReq(c,e,cl) XkbSetCauseReq(c,XkbReqCode,e,cl)
-#define XkbSetCauseUnknown(c) XkbSetCauseKey(c,0,0)
-
-#define _OFF_TIMER 0
-#define _KRG_WARN_TIMER 1
-#define _KRG_TIMER 2
-#define _SK_TIMEOUT_TIMER 3
-#define _ALL_TIMEOUT_TIMER 4
-
-#define _BEEP_NONE 0
-#define _BEEP_FEATURE_ON 1
-#define _BEEP_FEATURE_OFF 2
-#define _BEEP_FEATURE_CHANGE 3
-#define _BEEP_SLOW_WARN 4
-#define _BEEP_SLOW_PRESS 5
-#define _BEEP_SLOW_ACCEPT 6
-#define _BEEP_SLOW_REJECT 7
-#define _BEEP_SLOW_RELEASE 8
-#define _BEEP_STICKY_LATCH 9
-#define _BEEP_STICKY_LOCK 10
-#define _BEEP_STICKY_UNLOCK 11
-#define _BEEP_LED_ON 12
-#define _BEEP_LED_OFF 13
-#define _BEEP_LED_CHANGE 14
-#define _BEEP_BOUNCE_REJECT 15
-
-typedef struct _XkbFilter {
- CARD16 keycode;
- CARD8 what;
- CARD8 active;
- CARD8 filterOthers;
- CARD32 priv;
- XkbAction upAction;
- int (*filter)(
- struct _XkbSrvInfo* /* xkbi */,
- struct _XkbFilter * /* filter */,
- unsigned /* keycode */,
- XkbAction * /* action */
- );
- struct _XkbFilter *next;
-} XkbFilterRec,*XkbFilterPtr;
-
-typedef struct _XkbSrvInfo {
- XkbStateRec prev_state;
- XkbStateRec state;
- XkbDescPtr desc;
-
- DeviceIntPtr device;
- KbdCtrlProcPtr kbdProc;
-
- XkbRadioGroupPtr radioGroups;
- CARD8 nRadioGroups;
- CARD8 clearMods;
- CARD8 setMods;
- INT16 groupChange;
-
- CARD16 dfltPtrDelta;
-
- double mouseKeysCurve;
- double mouseKeysCurveFactor;
- INT16 mouseKeysDX;
- INT16 mouseKeysDY;
- CARD8 mouseKeysFlags;
- Bool mouseKeysAccel;
- CARD8 mouseKeysCounter;
-
- CARD8 lockedPtrButtons;
- CARD8 shiftKeyCount;
- KeyCode mouseKey;
- KeyCode inactiveKey;
- KeyCode slowKey;
- KeyCode repeatKey;
- CARD8 krgTimerActive;
- CARD8 beepType;
- CARD8 beepCount;
-
- CARD32 flags;
- CARD32 lastPtrEventTime;
- CARD32 lastShiftEventTime;
- OsTimerPtr beepTimer;
- OsTimerPtr mouseKeyTimer;
- OsTimerPtr slowKeysTimer;
- OsTimerPtr bounceKeysTimer;
- OsTimerPtr repeatKeyTimer;
- OsTimerPtr krgTimer;
-
- int szFilters;
- XkbFilterPtr filters;
-} XkbSrvInfoRec, *XkbSrvInfoPtr;
-
-#define XkbSLI_IsDefault (1L<<0)
-#define XkbSLI_HasOwnState (1L<<1)
-
-typedef struct _XkbSrvLedInfo {
- CARD16 flags;
- CARD16 class;
- CARD16 id;
- union {
- KbdFeedbackPtr kf;
- LedFeedbackPtr lf;
- } fb;
-
- CARD32 physIndicators;
- CARD32 autoState;
- CARD32 explicitState;
- CARD32 effectiveState;
-
- CARD32 mapsPresent;
- CARD32 namesPresent;
- XkbIndicatorMapPtr maps;
- Atom * names;
-
- CARD32 usesBase;
- CARD32 usesLatched;
- CARD32 usesLocked;
- CARD32 usesEffective;
- CARD32 usesCompat;
- CARD32 usesControls;
-
- CARD32 usedComponents;
-} XkbSrvLedInfoRec, *XkbSrvLedInfoPtr;
-
-/*
- * Settings for xkbClientFlags field (used by DIX)
- * These flags _must_ not overlap with XkbPCF_*
- */
-#define _XkbClientInitialized (1<<15)
-
-#define _XkbWantsDetectableAutoRepeat(c)\
- ((c)->xkbClientFlags&XkbPCF_DetectableAutoRepeatMask)
-
-/*
- * Settings for flags field
- */
-#define _XkbStateNotifyInProgress (1<<0)
-
-typedef struct
-{
- ProcessInputProc processInputProc;
- /* If processInputProc is set to something different than realInputProc,
- * UNWRAP and COND_WRAP will not touch processInputProc and update only
- * realInputProc. This ensures that
- * processInputProc == (frozen ? EnqueueEvent : realInputProc)
- *
- * WRAP_PROCESS_INPUT_PROC should only be called during initialization,
- * since it may destroy this invariant.
- */
- ProcessInputProc realInputProc;
- DeviceUnwrapProc unwrapProc;
-} xkbDeviceInfoRec, *xkbDeviceInfoPtr;
-
-#define WRAP_PROCESS_INPUT_PROC(device, oldprocs, proc, unwrapproc) \
- device->public.processInputProc = proc; \
- oldprocs->processInputProc = \
- oldprocs->realInputProc = device->public.realInputProc; \
- device->public.realInputProc = proc; \
- oldprocs->unwrapProc = device->unwrapProc; \
- device->unwrapProc = unwrapproc;
-
-#define COND_WRAP_PROCESS_INPUT_PROC(device, oldprocs, proc, unwrapproc) \
- if (device->public.processInputProc == device->public.realInputProc)\
- device->public.processInputProc = proc; \
- oldprocs->processInputProc = \
- oldprocs->realInputProc = device->public.realInputProc; \
- device->public.realInputProc = proc; \
- oldprocs->unwrapProc = device->unwrapProc; \
- device->unwrapProc = unwrapproc;
-
-#define UNWRAP_PROCESS_INPUT_PROC(device, oldprocs, backupproc) \
- backupproc = device->public.realInputProc; \
- if (device->public.processInputProc == device->public.realInputProc)\
- device->public.processInputProc = oldprocs->realInputProc; \
- device->public.realInputProc = oldprocs->realInputProc; \
- device->unwrapProc = oldprocs->unwrapProc;
-
-extern _X_EXPORT DevPrivateKeyRec xkbDevicePrivateKeyRec;
-#define xkbDevicePrivateKey (&xkbDevicePrivateKeyRec)
-
-#define XKBDEVICEINFO(dev) ((xkbDeviceInfoPtr)dixLookupPrivate(&(dev)->devPrivates, xkbDevicePrivateKey))
-
-extern void xkbUnwrapProc(DeviceIntPtr, DeviceHandleProc, pointer);
-
-/***====================================================================***/
-
-
-/***====================================================================***/
-
-#define XkbAX_KRGMask (XkbSlowKeysMask|XkbBounceKeysMask)
-#define XkbAllFilteredEventsMask \
- (XkbAccessXKeysMask|XkbRepeatKeysMask|XkbMouseKeysAccelMask|XkbAX_KRGMask)
-
-/***====================================================================***/
-
-extern _X_EXPORT int XkbReqCode;
-extern _X_EXPORT int XkbEventBase;
-extern _X_EXPORT int XkbKeyboardErrorCode;
-extern _X_EXPORT char * XkbBaseDirectory;
-extern _X_EXPORT char * XkbBinDirectory;
-
-extern _X_EXPORT CARD32 xkbDebugFlags;
-
-#define _XkbLibError(c,l,d) /* Epoch fail */
-#define _XkbErrCode2(a,b) ((XID)((((unsigned int)(a))<<24)|((b)&0xffffff)))
-#define _XkbErrCode3(a,b,c) _XkbErrCode2(a,(((unsigned int)(b))<<16)|(c))
-#define _XkbErrCode4(a,b,c,d) _XkbErrCode3(a,b,((((unsigned int)(c))<<8)|(d)))
-
-extern _X_EXPORT int DeviceKeyPress,DeviceKeyRelease,DeviceMotionNotify;
-extern _X_EXPORT int DeviceButtonPress,DeviceButtonRelease;
-
-#define Status int
-
-extern _X_EXPORT void XkbUseMsg(
- void
-);
-
-extern _X_EXPORT int XkbProcessArguments(
- int /* argc */,
- char ** /* argv */,
- int /* i */
-);
-
-extern _X_EXPORT Bool XkbInitPrivates(void);
-
-extern _X_EXPORT void XkbSetExtension(DeviceIntPtr device, ProcessInputProc proc);
-
-extern _X_EXPORT void XkbFreeCompatMap(
- XkbDescPtr /* xkb */,
- unsigned int /* which */,
- Bool /* freeMap */
-);
-
-extern _X_EXPORT void XkbFreeNames(
- XkbDescPtr /* xkb */,
- unsigned int /* which */,
- Bool /* freeMap */
-);
-
-extern _X_EXPORT int _XkbLookupAnyDevice(
- DeviceIntPtr *pDev,
- int id,
- ClientPtr client,
- Mask access_mode,
- int *xkb_err
-);
-
-extern _X_EXPORT int _XkbLookupKeyboard(
- DeviceIntPtr *pDev,
- int id,
- ClientPtr client,
- Mask access_mode,
- int *xkb_err
-);
-
-extern _X_EXPORT int _XkbLookupBellDevice(
- DeviceIntPtr *pDev,
- int id,
- ClientPtr client,
- Mask access_mode,
- int *xkb_err
-);
-
-extern _X_EXPORT int _XkbLookupLedDevice(
- DeviceIntPtr *pDev,
- int id,
- ClientPtr client,
- Mask access_mode,
- int *xkb_err
-);
-
-extern _X_EXPORT int _XkbLookupButtonDevice(
- DeviceIntPtr *pDev,
- int id,
- ClientPtr client,
- Mask access_mode,
- int *xkb_err
-);
-
-extern _X_EXPORT XkbDescPtr XkbAllocKeyboard(
- void
-);
-
-extern _X_EXPORT Status XkbAllocClientMap(
- XkbDescPtr /* xkb */,
- unsigned int /* which */,
- unsigned int /* nTypes */
-);
-
-extern _X_EXPORT Status XkbAllocServerMap(
- XkbDescPtr /* xkb */,
- unsigned int /* which */,
- unsigned int /* nNewActions */
-);
-
-extern _X_EXPORT void XkbFreeClientMap(
- XkbDescPtr /* xkb */,
- unsigned int /* what */,
- Bool /* freeMap */
-);
-
-extern _X_EXPORT void XkbFreeServerMap(
- XkbDescPtr /* xkb */,
- unsigned int /* what */,
- Bool /* freeMap */
-);
-
-extern _X_EXPORT Status XkbAllocIndicatorMaps(
- XkbDescPtr /* xkb */
-);
-
-extern _X_EXPORT Status XkbAllocCompatMap(
- XkbDescPtr /* xkb */,
- unsigned int /* which */,
- unsigned int /* nInterpret */
-);
-
-extern _X_EXPORT Status XkbAllocNames(
- XkbDescPtr /* xkb */,
- unsigned int /* which */,
- int /* nTotalRG */,
- int /* nTotalAliases */
-);
-
-extern _X_EXPORT Status XkbAllocControls(
- XkbDescPtr /* xkb */,
- unsigned int /* which*/
-);
-
-extern _X_EXPORT Status XkbCopyKeyTypes(
- XkbKeyTypePtr /* from */,
- XkbKeyTypePtr /* into */,
- int /* num_types */
-);
-
-extern _X_EXPORT Status XkbResizeKeyType(
- XkbDescPtr /* xkb */,
- int /* type_ndx */,
- int /* map_count */,
- Bool /* want_preserve */,
- int /* new_num_lvls */
-);
-
-extern _X_EXPORT void XkbFreeKeyboard(
- XkbDescPtr /* xkb */,
- unsigned int /* which */,
- Bool /* freeDesc */
-);
-
-extern _X_EXPORT void XkbSetActionKeyMods(
- XkbDescPtr /* xkb */,
- XkbAction * /* act */,
- unsigned int /* mods */
-);
-
-extern _X_EXPORT unsigned int XkbMaskForVMask(
- XkbDescPtr /* xkb */,
- unsigned int /* vmask */
-);
-
-extern _X_EXPORT Bool XkbVirtualModsToReal(
- XkbDescPtr /* xkb */,
- unsigned int /* virtua_mask */,
- unsigned int * /* mask_rtrn */
-);
-
-extern _X_EXPORT unsigned int XkbAdjustGroup(
- int /* group */,
- XkbControlsPtr /* ctrls */
-);
-
-extern _X_EXPORT KeySym *XkbResizeKeySyms(
- XkbDescPtr /* xkb */,
- int /* key */,
- int /* needed */
-);
-
-extern _X_EXPORT XkbAction *XkbResizeKeyActions(
- XkbDescPtr /* xkb */,
- int /* key */,
- int /* needed */
-);
-
-extern _X_EXPORT void XkbUpdateKeyTypesFromCore(
- DeviceIntPtr /* pXDev */,
- KeySymsPtr /* syms */,
- KeyCode /* first */,
- CARD8 /* num */,
- XkbChangesPtr /* pChanges */
-);
-
-extern _X_EXPORT void XkbUpdateDescActions(
- XkbDescPtr /* xkb */,
- KeyCode /* first */,
- CARD8 /* num */,
- XkbChangesPtr /* changes */
-);
-
-extern _X_EXPORT void XkbUpdateActions(
- DeviceIntPtr /* pXDev */,
- KeyCode /* first */,
- CARD8 /* num */,
- XkbChangesPtr /* pChanges */,
- unsigned int * /* needChecksRtrn */,
- XkbEventCausePtr /* cause */
-);
-
-extern _X_EXPORT KeySymsPtr XkbGetCoreMap(
- DeviceIntPtr /* keybd */
-);
-
-extern _X_EXPORT void XkbApplyMappingChange(
- DeviceIntPtr /* pXDev */,
- KeySymsPtr /* map */,
- KeyCode /* firstKey */,
- CARD8 /* num */,
- CARD8 * /* modmap */,
- ClientPtr /* client */
-);
-
-extern _X_EXPORT void XkbSetIndicators(
- DeviceIntPtr /* pXDev */,
- CARD32 /* affect */,
- CARD32 /* values */,
- XkbEventCausePtr /* cause */
-);
-
-extern _X_EXPORT void XkbUpdateIndicators(
- DeviceIntPtr /* keybd */,
- CARD32 /* changed */,
- Bool /* check_edevs */,
- XkbChangesPtr /* pChanges */,
- XkbEventCausePtr /* cause */
-);
-
-extern _X_EXPORT XkbSrvLedInfoPtr XkbAllocSrvLedInfo(
- DeviceIntPtr /* dev */,
- KbdFeedbackPtr /* kf */,
- LedFeedbackPtr /* lf */,
- unsigned int /* needed_parts */
-);
-
-extern _X_EXPORT XkbSrvLedInfoPtr XkbCopySrvLedInfo(
- DeviceIntPtr /* dev */,
- XkbSrvLedInfoPtr /* src */,
- KbdFeedbackPtr /* kf */,
- LedFeedbackPtr /* lf */
-);
-
-
-extern _X_EXPORT XkbSrvLedInfoPtr XkbFindSrvLedInfo(
- DeviceIntPtr /* dev */,
- unsigned int /* class */,
- unsigned int /* id */,
- unsigned int /* needed_parts */
-);
-
-extern _X_EXPORT void XkbApplyLedNameChanges(
- DeviceIntPtr /* dev */,
- XkbSrvLedInfoPtr /* sli */,
- unsigned int /* changed_names */,
- xkbExtensionDeviceNotify * /* ed */,
- XkbChangesPtr /* changes */,
- XkbEventCausePtr /* cause */
-);
-
-extern _X_EXPORT void XkbApplyLedMapChanges(
- DeviceIntPtr /* dev */,
- XkbSrvLedInfoPtr /* sli */,
- unsigned int /* changed_maps */,
- xkbExtensionDeviceNotify * /* ed */,
- XkbChangesPtr /* changes */,
- XkbEventCausePtr /* cause */
-);
-
-extern _X_EXPORT void XkbApplyLedStateChanges(
- DeviceIntPtr /* dev */,
- XkbSrvLedInfoPtr /* sli */,
- unsigned int /* changed_leds */,
- xkbExtensionDeviceNotify * /* ed */,
- XkbChangesPtr /* changes */,
- XkbEventCausePtr /* cause */
-);
-
-extern _X_EXPORT void XkbFlushLedEvents(
- DeviceIntPtr /* dev */,
- DeviceIntPtr /* kbd */,
- XkbSrvLedInfoPtr /* sli */,
- xkbExtensionDeviceNotify * /* ed */,
- XkbChangesPtr /* changes */,
- XkbEventCausePtr /* cause */
-);
-
-extern _X_EXPORT unsigned int XkbIndicatorsToUpdate(
- DeviceIntPtr /* dev */,
- unsigned long /* state_changes */,
- Bool /* enabled_ctrl_changes */
-);
-
-extern _X_EXPORT void XkbComputeDerivedState(
- XkbSrvInfoPtr /* xkbi */
-);
-
-extern _X_EXPORT void XkbCheckSecondaryEffects(
- XkbSrvInfoPtr /* xkbi */,
- unsigned int /* which */,
- XkbChangesPtr /* changes */,
- XkbEventCausePtr /* cause */
-);
-
-extern _X_EXPORT void XkbCheckIndicatorMaps(
- DeviceIntPtr /* dev */,
- XkbSrvLedInfoPtr /* sli */,
- unsigned int /* which */
-);
-
-extern _X_EXPORT unsigned int XkbStateChangedFlags(
- XkbStatePtr /* old */,
- XkbStatePtr /* new */
-);
-
-extern _X_EXPORT void XkbSendStateNotify(
- DeviceIntPtr /* kbd */,
- xkbStateNotify * /* pSN */
-);
-
-extern _X_EXPORT void XkbSendMapNotify(
- DeviceIntPtr /* kbd */,
- xkbMapNotify * /* ev */
-);
-
-extern _X_EXPORT int XkbComputeControlsNotify(
- DeviceIntPtr /* kbd */,
- XkbControlsPtr /* old */,
- XkbControlsPtr /* new */,
- xkbControlsNotify * /* pCN */,
- Bool /* forceCtrlProc */
-);
-
-extern _X_EXPORT void XkbSendControlsNotify(
- DeviceIntPtr /* kbd */,
- xkbControlsNotify * /* ev */
-);
-
-extern _X_EXPORT void XkbSendCompatMapNotify(
- DeviceIntPtr /* kbd */,
- xkbCompatMapNotify * /* ev */
-);
-
-extern _X_EXPORT void XkbHandleBell(
- BOOL /* force */,
- BOOL /* eventOnly */,
- DeviceIntPtr /* kbd */,
- CARD8 /* percent */,
- pointer /* ctrl */,
- CARD8 /* class */,
- Atom /* name */,
- WindowPtr /* pWin */,
- ClientPtr /* pClient */
-);
-
-extern _X_EXPORT void XkbSendAccessXNotify(
- DeviceIntPtr /* kbd */,
- xkbAccessXNotify * /* pEv */
-);
-
-extern _X_EXPORT void XkbSendNamesNotify(
- DeviceIntPtr /* kbd */,
- xkbNamesNotify * /* ev */
-);
-
-extern _X_EXPORT void XkbSendActionMessage(
- DeviceIntPtr /* kbd */,
- xkbActionMessage * /* ev */
-);
-
-extern _X_EXPORT void XkbSendExtensionDeviceNotify(
- DeviceIntPtr /* kbd */,
- ClientPtr /* client */,
- xkbExtensionDeviceNotify * /* ev */
-);
-
-extern _X_EXPORT void XkbSendNotification(
- DeviceIntPtr /* kbd */,
- XkbChangesPtr /* pChanges */,
- XkbEventCausePtr /* cause */
-);
-
-extern _X_EXPORT void XkbProcessKeyboardEvent(
- DeviceEvent* /* event */,
- DeviceIntPtr /* keybd */
-);
-
-extern _X_EXPORT void XkbHandleActions(
- DeviceIntPtr /* dev */,
- DeviceIntPtr /* kbd */,
- DeviceEvent* /* event */
-);
-
-extern _X_EXPORT Bool XkbEnableDisableControls(
- XkbSrvInfoPtr /* xkbi */,
- unsigned long /* change */,
- unsigned long /* newValues */,
- XkbChangesPtr /* changes */,
- XkbEventCausePtr /* cause */
-);
-
-extern _X_EXPORT void AccessXInit(
- DeviceIntPtr /* dev */
-);
-
-extern _X_EXPORT Bool AccessXFilterPressEvent(
- DeviceEvent* /* event */,
- DeviceIntPtr /* keybd */
-);
-
-extern _X_EXPORT Bool AccessXFilterReleaseEvent(
- DeviceEvent* /* event */,
- DeviceIntPtr /* keybd */
-);
-
-extern _X_EXPORT void AccessXCancelRepeatKey(
- XkbSrvInfoPtr /* xkbi */,
- KeyCode /* key */
-);
-
-extern _X_EXPORT void AccessXComputeCurveFactor(
- XkbSrvInfoPtr /* xkbi */,
- XkbControlsPtr /* ctrls */
-);
-
-extern _X_EXPORT XkbInterestPtr XkbFindClientResource(
- DevicePtr /* inDev */,
- ClientPtr /* client */
-);
-
-extern _X_EXPORT XkbInterestPtr XkbAddClientResource(
- DevicePtr /* inDev */,
- ClientPtr /* client */,
- XID /* id */
-);
-
-extern _X_EXPORT int XkbRemoveResourceClient(
- DevicePtr /* inDev */,
- XID /* id */
-);
-
-extern _X_EXPORT int XkbDDXAccessXBeep(
- DeviceIntPtr /* dev */,
- unsigned int /* what */,
- unsigned int /* which */
-);
-
-extern _X_EXPORT int XkbDDXUsesSoftRepeat(
- DeviceIntPtr /* dev */
-);
-
-extern _X_EXPORT void XkbDDXKeybdCtrlProc(
- DeviceIntPtr /* dev */,
- KeybdCtrl * /* ctrl */
-);
-
-extern _X_EXPORT void XkbDDXChangeControls(
- DeviceIntPtr /* dev */,
- XkbControlsPtr /* old */,
- XkbControlsPtr /* new */
-);
-
-extern _X_EXPORT void XkbDDXUpdateDeviceIndicators(
- DeviceIntPtr /* dev */,
- XkbSrvLedInfoPtr /* sli */,
- CARD32 /* newState */
-);
-
-extern _X_EXPORT int XkbDDXTerminateServer(
- DeviceIntPtr /* dev */,
- KeyCode /* key */,
- XkbAction * /* act */
-);
-
-extern _X_EXPORT int XkbDDXSwitchScreen(
- DeviceIntPtr /* dev */,
- KeyCode /* key */,
- XkbAction * /* act */
-);
-
-extern _X_EXPORT int XkbDDXPrivate(
- DeviceIntPtr /* dev */,
- KeyCode /* key */,
- XkbAction * /* act */
-);
-
-extern _X_EXPORT void XkbDisableComputedAutoRepeats(
- DeviceIntPtr /* pXDev */,
- unsigned int /* key */
-);
-
-extern _X_EXPORT void XkbSetRepeatKeys(
- DeviceIntPtr /* pXDev */,
- int /* key */,
- int /* onoff */
-);
-
-extern _X_EXPORT int XkbLatchModifiers(
- DeviceIntPtr /* pXDev */,
- CARD8 /* mask */,
- CARD8 /* latches */
-);
-
-extern _X_EXPORT int XkbLatchGroup(
- DeviceIntPtr /* pXDev */,
- int /* group */
-);
-
-extern _X_EXPORT void XkbClearAllLatchesAndLocks(
- DeviceIntPtr /* dev */,
- XkbSrvInfoPtr /* xkbi */,
- Bool /* genEv */,
- XkbEventCausePtr /* cause */
-);
-
-extern _X_EXPORT void XkbGetRulesDflts(
- XkbRMLVOSet * /* rmlvo */
-);
-
-extern _X_EXPORT void XkbFreeRMLVOSet(
- XkbRMLVOSet * /* rmlvo */,
- Bool /* freeRMLVO */
-);
-
-extern _X_EXPORT void XkbSetRulesDflts(
- XkbRMLVOSet * /* rmlvo */
-);
-
-extern _X_EXPORT void XkbDeleteRulesDflts(
- void
-);
-
-extern _X_EXPORT int SProcXkbDispatch(
- ClientPtr /* client */
-);
-
-extern _X_EXPORT XkbGeometryPtr XkbLookupNamedGeometry(
- DeviceIntPtr /* dev */,
- Atom /* name */,
- Bool * /* shouldFree */
-);
-
-extern _X_EXPORT char * _XkbDupString(
- const char * /* str */
-);
-
-extern _X_EXPORT void XkbConvertCase(
- KeySym /* sym */,
- KeySym * /* lower */,
- KeySym * /* upper */
-);
-
-extern _X_EXPORT Status XkbChangeKeycodeRange(
- XkbDescPtr /* xkb */,
- int /* minKC */,
- int /* maxKC */,
- XkbChangesPtr /* changes */
-);
-
-extern _X_EXPORT void XkbFreeSrvLedInfo(
- XkbSrvLedInfoPtr /* sli */
-);
-
-extern _X_EXPORT void XkbFreeInfo(
- XkbSrvInfoPtr /* xkbi */
-);
-
-extern _X_EXPORT Status XkbChangeTypesOfKey(
- XkbDescPtr /* xkb */,
- int /* key */,
- int /* nGroups */,
- unsigned int /* groups */,
- int * /* newTypesIn */,
- XkbMapChangesPtr /* changes */
-);
-
-extern _X_EXPORT int XkbKeyTypesForCoreSymbols(
- XkbDescPtr /* xkb */,
- int /* map_width */,
- KeySym * /* core_syms */,
- unsigned int /* protected */,
- int * /* types_inout */,
- KeySym * /* xkb_syms_rtrn */
-);
-
-extern _X_EXPORT Bool XkbApplyCompatMapToKey(
- XkbDescPtr /* xkb */,
- KeyCode /* key */,
- XkbChangesPtr /* changes */
-);
-
-extern _X_EXPORT Bool XkbApplyVirtualModChanges(
- XkbDescPtr /* xkb */,
- unsigned int /* changed */,
- XkbChangesPtr /* changes */
-);
-
-extern _X_EXPORT void XkbSendNewKeyboardNotify(
- DeviceIntPtr /* kbd */,
- xkbNewKeyboardNotify * /* pNKN */
-);
-
-extern Bool XkbCopyKeymap(
- XkbDescPtr /* dst */,
- XkbDescPtr /* src */);
-
-extern _X_EXPORT Bool XkbCopyDeviceKeymap(
- DeviceIntPtr /* dst */,
- DeviceIntPtr /* src */);
-
-extern void XkbFilterEvents(
- ClientPtr /* pClient */,
- int /* nEvents */,
- xEvent* /* xE */);
-
-extern int XkbGetEffectiveGroup(
- XkbSrvInfoPtr /* xkbi */,
- XkbStatePtr /* xkbstate */,
- CARD8 /* keycode */);
-
-extern void XkbMergeLockedPtrBtns(
- DeviceIntPtr /* master */);
-
-extern void XkbFakeDeviceButton(
- DeviceIntPtr /* dev */,
- int /* press */,
- int /* button */);
-
-
-#include "xkbfile.h"
-#include "xkbrules.h"
-
-#define _XkbListKeycodes 0
-#define _XkbListTypes 1
-#define _XkbListCompat 2
-#define _XkbListSymbols 3
-#define _XkbListGeometry 4
-#define _XkbListNumComponents 5
-
-typedef struct _XkbSrvListInfo {
- int szPool;
- int nPool;
- char * pool;
-
- int maxRtrn;
- int nTotal;
-
- char * pattern[_XkbListNumComponents];
- int nFound[_XkbListNumComponents];
-} XkbSrvListInfoRec,*XkbSrvListInfoPtr;
-
-extern _X_EXPORT Status XkbDDXList(
- DeviceIntPtr /* dev */,
- XkbSrvListInfoPtr /* listing */,
- ClientPtr /* client */
-);
-
-extern _X_EXPORT unsigned int XkbDDXLoadKeymapByNames(
- DeviceIntPtr /* keybd */,
- XkbComponentNamesPtr /* names */,
- unsigned int /* want */,
- unsigned int /* need */,
- XkbDescPtr * /* finfoRtrn */,
- char * /* keymapNameRtrn */,
- int /* keymapNameRtrnLen */
-);
-
-extern _X_EXPORT Bool XkbDDXNamesFromRules(
- DeviceIntPtr /* keybd */,
- char * /* rules */,
- XkbRF_VarDefsPtr /* defs */,
- XkbComponentNamesPtr /* names */
-);
-
-extern _X_EXPORT XkbDescPtr XkbCompileKeymap(
- DeviceIntPtr /* dev */,
- XkbRMLVOSet * /* rmlvo */
-);
-
-#endif /* _XKBSRV_H_ */
+/************************************************************ +Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc. + +Permission 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 that both that copyright +notice and this permission notice appear in supporting +documentation, and that the name of Silicon Graphics not be +used in advertising or publicity pertaining to distribution +of the software without specific prior written permission. +Silicon Graphics makes no representation about the suitability +of this software for any purpose. It is provided "as is" +without any express or implied warranty. + +SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS +SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON +GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL +DAMAGES OR ANY 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 THIS SOFTWARE. + +********************************************************/ + +#ifndef _XKBSRV_H_ +#define _XKBSRV_H_ + +#define XkbAllocClientMap SrvXkbAllocClientMap +#define XkbAllocServerMap SrvXkbAllocServerMap +#define XkbChangeTypesOfKey SrvXkbChangeTypesOfKey +#define XkbCopyKeyTypes SrvXkbCopyKeyTypes +#define XkbFreeClientMap SrvXkbFreeClientMap +#define XkbFreeServerMap SrvXkbFreeServerMap +#define XkbKeyTypesForCoreSymbols SrvXkbKeyTypesForCoreSymbols +#define XkbApplyCompatMapToKey SrvXkbApplyCompatMapToKey +#define XkbResizeKeyActions SrvXkbResizeKeyActions +#define XkbResizeKeySyms SrvXkbResizeKeySyms +#define XkbResizeKeyType SrvXkbResizeKeyType +#define XkbAllocCompatMap SrvXkbAllocCompatMap +#define XkbAllocControls SrvXkbAllocControls +#define XkbAllocIndicatorMaps SrvXkbAllocIndicatorMaps +#define XkbAllocKeyboard SrvXkbAllocKeyboard +#define XkbAllocNames SrvXkbAllocNames +#define XkbFreeCompatMap SrvXkbFreeCompatMap +#define XkbFreeKeyboard SrvXkbFreeKeyboard +#define XkbFreeNames SrvXkbFreeNames +#define XkbLatchModifiers SrvXkbLatchModifiers +#define XkbLatchGroup SrvXkbLatchGroup +#define XkbVirtualModsToReal SrvXkbVirtualModsToReal +#define XkbChangeKeycodeRange SrvXkbChangeKeycodeRange +#define XkbApplyVirtualModChanges SrvXkbApplyVirtualModChanges + +#include <X11/extensions/XKBproto.h> +#include "xkbstr.h" +#include "xkbrules.h" +#include "inputstr.h" +#include "events.h" + +typedef struct _XkbInterest { + DeviceIntPtr dev; + ClientPtr client; + XID resource; + struct _XkbInterest * next; + CARD16 extDevNotifyMask; + CARD16 stateNotifyMask; + CARD16 namesNotifyMask; + CARD32 ctrlsNotifyMask; + CARD8 compatNotifyMask; + BOOL bellNotifyMask; + BOOL actionMessageMask; + CARD16 accessXNotifyMask; + CARD32 iStateNotifyMask; + CARD32 iMapNotifyMask; + CARD16 altSymsNotifyMask; + CARD32 autoCtrls; + CARD32 autoCtrlValues; +} XkbInterestRec,*XkbInterestPtr; + +typedef struct _XkbRadioGroup { + CARD8 flags; + CARD8 nMembers; + CARD8 dfltDown; + CARD8 currentDown; + CARD8 members[XkbRGMaxMembers]; +} XkbRadioGroupRec, *XkbRadioGroupPtr; + +typedef struct _XkbEventCause { + CARD8 kc; + CARD8 event; + CARD8 mjr; + CARD8 mnr; + ClientPtr client; +} XkbEventCauseRec,*XkbEventCausePtr; +#define XkbSetCauseKey(c,k,e) { (c)->kc= (k),(c)->event= (e),\ + (c)->mjr= (c)->mnr= 0; \ + (c)->client= NULL; } +#define XkbSetCauseReq(c,j,n,cl) { (c)->kc= (c)->event= 0,\ + (c)->mjr= (j),(c)->mnr= (n);\ + (c)->client= (cl); } +#define XkbSetCauseCoreReq(c,e,cl) XkbSetCauseReq(c,e,0,cl) +#define XkbSetCauseXkbReq(c,e,cl) XkbSetCauseReq(c,XkbReqCode,e,cl) +#define XkbSetCauseUnknown(c) XkbSetCauseKey(c,0,0) + +#define _OFF_TIMER 0 +#define _KRG_WARN_TIMER 1 +#define _KRG_TIMER 2 +#define _SK_TIMEOUT_TIMER 3 +#define _ALL_TIMEOUT_TIMER 4 + +#define _BEEP_NONE 0 +#define _BEEP_FEATURE_ON 1 +#define _BEEP_FEATURE_OFF 2 +#define _BEEP_FEATURE_CHANGE 3 +#define _BEEP_SLOW_WARN 4 +#define _BEEP_SLOW_PRESS 5 +#define _BEEP_SLOW_ACCEPT 6 +#define _BEEP_SLOW_REJECT 7 +#define _BEEP_SLOW_RELEASE 8 +#define _BEEP_STICKY_LATCH 9 +#define _BEEP_STICKY_LOCK 10 +#define _BEEP_STICKY_UNLOCK 11 +#define _BEEP_LED_ON 12 +#define _BEEP_LED_OFF 13 +#define _BEEP_LED_CHANGE 14 +#define _BEEP_BOUNCE_REJECT 15 + +typedef struct _XkbFilter { + CARD16 keycode; + CARD8 what; + CARD8 active; + CARD8 filterOthers; + CARD32 priv; + XkbAction upAction; + int (*filter)( + struct _XkbSrvInfo* /* xkbi */, + struct _XkbFilter * /* filter */, + unsigned /* keycode */, + XkbAction * /* action */ + ); + struct _XkbFilter *next; +} XkbFilterRec,*XkbFilterPtr; + +typedef struct _XkbSrvInfo { + XkbStateRec prev_state; + XkbStateRec state; + XkbDescPtr desc; + + DeviceIntPtr device; + KbdCtrlProcPtr kbdProc; + + XkbRadioGroupPtr radioGroups; + CARD8 nRadioGroups; + CARD8 clearMods; + CARD8 setMods; + INT16 groupChange; + + CARD16 dfltPtrDelta; + + double mouseKeysCurve; + double mouseKeysCurveFactor; + INT16 mouseKeysDX; + INT16 mouseKeysDY; + CARD8 mouseKeysFlags; + Bool mouseKeysAccel; + CARD8 mouseKeysCounter; + + CARD8 lockedPtrButtons; + CARD8 shiftKeyCount; + KeyCode mouseKey; + KeyCode inactiveKey; + KeyCode slowKey; + KeyCode repeatKey; + CARD8 krgTimerActive; + CARD8 beepType; + CARD8 beepCount; + + CARD32 flags; + CARD32 lastPtrEventTime; + CARD32 lastShiftEventTime; + OsTimerPtr beepTimer; + OsTimerPtr mouseKeyTimer; + OsTimerPtr slowKeysTimer; + OsTimerPtr bounceKeysTimer; + OsTimerPtr repeatKeyTimer; + OsTimerPtr krgTimer; + + int szFilters; + XkbFilterPtr filters; +} XkbSrvInfoRec, *XkbSrvInfoPtr; + +#define XkbSLI_IsDefault (1L<<0) +#define XkbSLI_HasOwnState (1L<<1) + +typedef struct _XkbSrvLedInfo { + CARD16 flags; + CARD16 class; + CARD16 id; + union { + KbdFeedbackPtr kf; + LedFeedbackPtr lf; + } fb; + + CARD32 physIndicators; + CARD32 autoState; + CARD32 explicitState; + CARD32 effectiveState; + + CARD32 mapsPresent; + CARD32 namesPresent; + XkbIndicatorMapPtr maps; + Atom * names; + + CARD32 usesBase; + CARD32 usesLatched; + CARD32 usesLocked; + CARD32 usesEffective; + CARD32 usesCompat; + CARD32 usesControls; + + CARD32 usedComponents; +} XkbSrvLedInfoRec, *XkbSrvLedInfoPtr; + +/* + * Settings for xkbClientFlags field (used by DIX) + * These flags _must_ not overlap with XkbPCF_* + */ +#define _XkbClientInitialized (1<<15) + +#define _XkbWantsDetectableAutoRepeat(c)\ + ((c)->xkbClientFlags&XkbPCF_DetectableAutoRepeatMask) + +/* + * Settings for flags field + */ +#define _XkbStateNotifyInProgress (1<<0) + +typedef struct +{ + ProcessInputProc processInputProc; + /* If processInputProc is set to something different than realInputProc, + * UNWRAP and COND_WRAP will not touch processInputProc and update only + * realInputProc. This ensures that + * processInputProc == (frozen ? EnqueueEvent : realInputProc) + * + * WRAP_PROCESS_INPUT_PROC should only be called during initialization, + * since it may destroy this invariant. + */ + ProcessInputProc realInputProc; + DeviceUnwrapProc unwrapProc; +} xkbDeviceInfoRec, *xkbDeviceInfoPtr; + +#define WRAP_PROCESS_INPUT_PROC(device, oldprocs, proc, unwrapproc) \ + device->public.processInputProc = proc; \ + oldprocs->processInputProc = \ + oldprocs->realInputProc = device->public.realInputProc; \ + device->public.realInputProc = proc; \ + oldprocs->unwrapProc = device->unwrapProc; \ + device->unwrapProc = unwrapproc; + +#define COND_WRAP_PROCESS_INPUT_PROC(device, oldprocs, proc, unwrapproc) \ + if (device->public.processInputProc == device->public.realInputProc)\ + device->public.processInputProc = proc; \ + oldprocs->processInputProc = \ + oldprocs->realInputProc = device->public.realInputProc; \ + device->public.realInputProc = proc; \ + oldprocs->unwrapProc = device->unwrapProc; \ + device->unwrapProc = unwrapproc; + +#define UNWRAP_PROCESS_INPUT_PROC(device, oldprocs, backupproc) \ + backupproc = device->public.realInputProc; \ + if (device->public.processInputProc == device->public.realInputProc)\ + device->public.processInputProc = oldprocs->realInputProc; \ + device->public.realInputProc = oldprocs->realInputProc; \ + device->unwrapProc = oldprocs->unwrapProc; + +extern _X_EXPORT DevPrivateKeyRec xkbDevicePrivateKeyRec; +#define xkbDevicePrivateKey (&xkbDevicePrivateKeyRec) + +#define XKBDEVICEINFO(dev) ((xkbDeviceInfoPtr)dixLookupPrivate(&(dev)->devPrivates, xkbDevicePrivateKey)) + +extern void xkbUnwrapProc(DeviceIntPtr, DeviceHandleProc, pointer); + +/***====================================================================***/ + + +/***====================================================================***/ + +#define XkbAX_KRGMask (XkbSlowKeysMask|XkbBounceKeysMask) +#define XkbAllFilteredEventsMask \ + (XkbAccessXKeysMask|XkbRepeatKeysMask|XkbMouseKeysAccelMask|XkbAX_KRGMask) + +/***====================================================================***/ + +extern _X_EXPORT int XkbReqCode; +extern _X_EXPORT int XkbEventBase; +extern _X_EXPORT int XkbKeyboardErrorCode; +extern _X_EXPORT char * XkbBaseDirectory; +extern _X_EXPORT char * XkbBinDirectory; + +extern _X_EXPORT CARD32 xkbDebugFlags; + +#define _XkbLibError(c,l,d) /* Epoch fail */ +#define _XkbErrCode2(a,b) ((XID)((((unsigned int)(a))<<24)|((b)&0xffffff))) +#define _XkbErrCode3(a,b,c) _XkbErrCode2(a,(((unsigned int)(b))<<16)|(c)) +#define _XkbErrCode4(a,b,c,d) _XkbErrCode3(a,b,((((unsigned int)(c))<<8)|(d))) + +extern _X_EXPORT int DeviceKeyPress,DeviceKeyRelease,DeviceMotionNotify; +extern _X_EXPORT int DeviceButtonPress,DeviceButtonRelease; + +#define Status int + +extern _X_EXPORT void XkbUseMsg( + void +); + +extern _X_EXPORT int XkbProcessArguments( + int /* argc */, + char ** /* argv */, + int /* i */ +); + +extern _X_EXPORT Bool XkbInitPrivates(void); + +extern _X_EXPORT void XkbSetExtension(DeviceIntPtr device, ProcessInputProc proc); + +extern _X_EXPORT void XkbFreeCompatMap( + XkbDescPtr /* xkb */, + unsigned int /* which */, + Bool /* freeMap */ +); + +extern _X_EXPORT void XkbFreeNames( + XkbDescPtr /* xkb */, + unsigned int /* which */, + Bool /* freeMap */ +); + +extern _X_EXPORT int _XkbLookupAnyDevice( + DeviceIntPtr *pDev, + int id, + ClientPtr client, + Mask access_mode, + int *xkb_err +); + +extern _X_EXPORT int _XkbLookupKeyboard( + DeviceIntPtr *pDev, + int id, + ClientPtr client, + Mask access_mode, + int *xkb_err +); + +extern _X_EXPORT int _XkbLookupBellDevice( + DeviceIntPtr *pDev, + int id, + ClientPtr client, + Mask access_mode, + int *xkb_err +); + +extern _X_EXPORT int _XkbLookupLedDevice( + DeviceIntPtr *pDev, + int id, + ClientPtr client, + Mask access_mode, + int *xkb_err +); + +extern _X_EXPORT int _XkbLookupButtonDevice( + DeviceIntPtr *pDev, + int id, + ClientPtr client, + Mask access_mode, + int *xkb_err +); + +extern _X_EXPORT XkbDescPtr XkbAllocKeyboard( + void +); + +extern _X_EXPORT Status XkbAllocClientMap( + XkbDescPtr /* xkb */, + unsigned int /* which */, + unsigned int /* nTypes */ +); + +extern _X_EXPORT Status XkbAllocServerMap( + XkbDescPtr /* xkb */, + unsigned int /* which */, + unsigned int /* nNewActions */ +); + +extern _X_EXPORT void XkbFreeClientMap( + XkbDescPtr /* xkb */, + unsigned int /* what */, + Bool /* freeMap */ +); + +extern _X_EXPORT void XkbFreeServerMap( + XkbDescPtr /* xkb */, + unsigned int /* what */, + Bool /* freeMap */ +); + +extern _X_EXPORT Status XkbAllocIndicatorMaps( + XkbDescPtr /* xkb */ +); + +extern _X_EXPORT Status XkbAllocCompatMap( + XkbDescPtr /* xkb */, + unsigned int /* which */, + unsigned int /* nInterpret */ +); + +extern _X_EXPORT Status XkbAllocNames( + XkbDescPtr /* xkb */, + unsigned int /* which */, + int /* nTotalRG */, + int /* nTotalAliases */ +); + +extern _X_EXPORT Status XkbAllocControls( + XkbDescPtr /* xkb */, + unsigned int /* which*/ +); + +extern _X_EXPORT Status XkbCopyKeyTypes( + XkbKeyTypePtr /* from */, + XkbKeyTypePtr /* into */, + int /* num_types */ +); + +extern _X_EXPORT Status XkbResizeKeyType( + XkbDescPtr /* xkb */, + int /* type_ndx */, + int /* map_count */, + Bool /* want_preserve */, + int /* new_num_lvls */ +); + +extern _X_EXPORT void XkbFreeKeyboard( + XkbDescPtr /* xkb */, + unsigned int /* which */, + Bool /* freeDesc */ +); + +extern _X_EXPORT void XkbSetActionKeyMods( + XkbDescPtr /* xkb */, + XkbAction * /* act */, + unsigned int /* mods */ +); + +extern _X_EXPORT unsigned int XkbMaskForVMask( + XkbDescPtr /* xkb */, + unsigned int /* vmask */ +); + +extern _X_EXPORT Bool XkbVirtualModsToReal( + XkbDescPtr /* xkb */, + unsigned int /* virtua_mask */, + unsigned int * /* mask_rtrn */ +); + +extern _X_EXPORT unsigned int XkbAdjustGroup( + int /* group */, + XkbControlsPtr /* ctrls */ +); + +extern _X_EXPORT KeySym *XkbResizeKeySyms( + XkbDescPtr /* xkb */, + int /* key */, + int /* needed */ +); + +extern _X_EXPORT XkbAction *XkbResizeKeyActions( + XkbDescPtr /* xkb */, + int /* key */, + int /* needed */ +); + +extern _X_EXPORT void XkbUpdateKeyTypesFromCore( + DeviceIntPtr /* pXDev */, + KeySymsPtr /* syms */, + KeyCode /* first */, + CARD8 /* num */, + XkbChangesPtr /* pChanges */ +); + +extern _X_EXPORT void XkbUpdateDescActions( + XkbDescPtr /* xkb */, + KeyCode /* first */, + CARD8 /* num */, + XkbChangesPtr /* changes */ +); + +extern _X_EXPORT void XkbUpdateActions( + DeviceIntPtr /* pXDev */, + KeyCode /* first */, + CARD8 /* num */, + XkbChangesPtr /* pChanges */, + unsigned int * /* needChecksRtrn */, + XkbEventCausePtr /* cause */ +); + +extern _X_EXPORT KeySymsPtr XkbGetCoreMap( + DeviceIntPtr /* keybd */ +); + +extern _X_EXPORT void XkbApplyMappingChange( + DeviceIntPtr /* pXDev */, + KeySymsPtr /* map */, + KeyCode /* firstKey */, + CARD8 /* num */, + CARD8 * /* modmap */, + ClientPtr /* client */ +); + +extern _X_EXPORT void XkbSetIndicators( + DeviceIntPtr /* pXDev */, + CARD32 /* affect */, + CARD32 /* values */, + XkbEventCausePtr /* cause */ +); + +extern _X_EXPORT void XkbUpdateIndicators( + DeviceIntPtr /* keybd */, + CARD32 /* changed */, + Bool /* check_edevs */, + XkbChangesPtr /* pChanges */, + XkbEventCausePtr /* cause */ +); + +extern _X_EXPORT XkbSrvLedInfoPtr XkbAllocSrvLedInfo( + DeviceIntPtr /* dev */, + KbdFeedbackPtr /* kf */, + LedFeedbackPtr /* lf */, + unsigned int /* needed_parts */ +); + +extern _X_EXPORT XkbSrvLedInfoPtr XkbCopySrvLedInfo( + DeviceIntPtr /* dev */, + XkbSrvLedInfoPtr /* src */, + KbdFeedbackPtr /* kf */, + LedFeedbackPtr /* lf */ +); + + +extern _X_EXPORT XkbSrvLedInfoPtr XkbFindSrvLedInfo( + DeviceIntPtr /* dev */, + unsigned int /* class */, + unsigned int /* id */, + unsigned int /* needed_parts */ +); + +extern _X_EXPORT void XkbApplyLedNameChanges( + DeviceIntPtr /* dev */, + XkbSrvLedInfoPtr /* sli */, + unsigned int /* changed_names */, + xkbExtensionDeviceNotify * /* ed */, + XkbChangesPtr /* changes */, + XkbEventCausePtr /* cause */ +); + +extern _X_EXPORT void XkbApplyLedMapChanges( + DeviceIntPtr /* dev */, + XkbSrvLedInfoPtr /* sli */, + unsigned int /* changed_maps */, + xkbExtensionDeviceNotify * /* ed */, + XkbChangesPtr /* changes */, + XkbEventCausePtr /* cause */ +); + +extern _X_EXPORT void XkbApplyLedStateChanges( + DeviceIntPtr /* dev */, + XkbSrvLedInfoPtr /* sli */, + unsigned int /* changed_leds */, + xkbExtensionDeviceNotify * /* ed */, + XkbChangesPtr /* changes */, + XkbEventCausePtr /* cause */ +); + +extern _X_EXPORT void XkbFlushLedEvents( + DeviceIntPtr /* dev */, + DeviceIntPtr /* kbd */, + XkbSrvLedInfoPtr /* sli */, + xkbExtensionDeviceNotify * /* ed */, + XkbChangesPtr /* changes */, + XkbEventCausePtr /* cause */ +); + +extern _X_EXPORT unsigned int XkbIndicatorsToUpdate( + DeviceIntPtr /* dev */, + unsigned long /* state_changes */, + Bool /* enabled_ctrl_changes */ +); + +extern _X_EXPORT void XkbComputeDerivedState( + XkbSrvInfoPtr /* xkbi */ +); + +extern _X_EXPORT void XkbCheckSecondaryEffects( + XkbSrvInfoPtr /* xkbi */, + unsigned int /* which */, + XkbChangesPtr /* changes */, + XkbEventCausePtr /* cause */ +); + +extern _X_EXPORT void XkbCheckIndicatorMaps( + DeviceIntPtr /* dev */, + XkbSrvLedInfoPtr /* sli */, + unsigned int /* which */ +); + +extern _X_EXPORT unsigned int XkbStateChangedFlags( + XkbStatePtr /* old */, + XkbStatePtr /* new */ +); + +extern _X_EXPORT void XkbSendStateNotify( + DeviceIntPtr /* kbd */, + xkbStateNotify * /* pSN */ +); + +extern _X_EXPORT void XkbSendMapNotify( + DeviceIntPtr /* kbd */, + xkbMapNotify * /* ev */ +); + +extern _X_EXPORT int XkbComputeControlsNotify( + DeviceIntPtr /* kbd */, + XkbControlsPtr /* old */, + XkbControlsPtr /* new */, + xkbControlsNotify * /* pCN */, + Bool /* forceCtrlProc */ +); + +extern _X_EXPORT void XkbSendControlsNotify( + DeviceIntPtr /* kbd */, + xkbControlsNotify * /* ev */ +); + +extern _X_EXPORT void XkbSendCompatMapNotify( + DeviceIntPtr /* kbd */, + xkbCompatMapNotify * /* ev */ +); + +extern _X_EXPORT void XkbHandleBell( + BOOL /* force */, + BOOL /* eventOnly */, + DeviceIntPtr /* kbd */, + CARD8 /* percent */, + pointer /* ctrl */, + CARD8 /* class */, + Atom /* name */, + WindowPtr /* pWin */, + ClientPtr /* pClient */ +); + +extern _X_EXPORT void XkbSendAccessXNotify( + DeviceIntPtr /* kbd */, + xkbAccessXNotify * /* pEv */ +); + +extern _X_EXPORT void XkbSendNamesNotify( + DeviceIntPtr /* kbd */, + xkbNamesNotify * /* ev */ +); + +extern _X_EXPORT void XkbSendActionMessage( + DeviceIntPtr /* kbd */, + xkbActionMessage * /* ev */ +); + +extern _X_EXPORT void XkbSendExtensionDeviceNotify( + DeviceIntPtr /* kbd */, + ClientPtr /* client */, + xkbExtensionDeviceNotify * /* ev */ +); + +extern _X_EXPORT void XkbSendNotification( + DeviceIntPtr /* kbd */, + XkbChangesPtr /* pChanges */, + XkbEventCausePtr /* cause */ +); + +extern _X_EXPORT void XkbProcessKeyboardEvent( + DeviceEvent* /* event */, + DeviceIntPtr /* keybd */ +); + +extern _X_EXPORT void XkbHandleActions( + DeviceIntPtr /* dev */, + DeviceIntPtr /* kbd */, + DeviceEvent* /* event */ +); + +extern _X_EXPORT Bool XkbEnableDisableControls( + XkbSrvInfoPtr /* xkbi */, + unsigned long /* change */, + unsigned long /* newValues */, + XkbChangesPtr /* changes */, + XkbEventCausePtr /* cause */ +); + +extern _X_EXPORT void AccessXInit( + DeviceIntPtr /* dev */ +); + +extern _X_EXPORT Bool AccessXFilterPressEvent( + DeviceEvent* /* event */, + DeviceIntPtr /* keybd */ +); + +extern _X_EXPORT Bool AccessXFilterReleaseEvent( + DeviceEvent* /* event */, + DeviceIntPtr /* keybd */ +); + +extern _X_EXPORT void AccessXCancelRepeatKey( + XkbSrvInfoPtr /* xkbi */, + KeyCode /* key */ +); + +extern _X_EXPORT void AccessXComputeCurveFactor( + XkbSrvInfoPtr /* xkbi */, + XkbControlsPtr /* ctrls */ +); + +extern _X_EXPORT XkbInterestPtr XkbFindClientResource( + DevicePtr /* inDev */, + ClientPtr /* client */ +); + +extern _X_EXPORT XkbInterestPtr XkbAddClientResource( + DevicePtr /* inDev */, + ClientPtr /* client */, + XID /* id */ +); + +extern _X_EXPORT int XkbRemoveResourceClient( + DevicePtr /* inDev */, + XID /* id */ +); + +extern _X_EXPORT int XkbDDXAccessXBeep( + DeviceIntPtr /* dev */, + unsigned int /* what */, + unsigned int /* which */ +); + +extern _X_EXPORT int XkbDDXUsesSoftRepeat( + DeviceIntPtr /* dev */ +); + +extern _X_EXPORT void XkbDDXKeybdCtrlProc( + DeviceIntPtr /* dev */, + KeybdCtrl * /* ctrl */ +); + +extern _X_EXPORT void XkbDDXChangeControls( + DeviceIntPtr /* dev */, + XkbControlsPtr /* old */, + XkbControlsPtr /* new */ +); + +extern _X_EXPORT void XkbDDXUpdateDeviceIndicators( + DeviceIntPtr /* dev */, + XkbSrvLedInfoPtr /* sli */, + CARD32 /* newState */ +); + +extern _X_EXPORT int XkbDDXTerminateServer( + DeviceIntPtr /* dev */, + KeyCode /* key */, + XkbAction * /* act */ +); + +extern _X_EXPORT int XkbDDXSwitchScreen( + DeviceIntPtr /* dev */, + KeyCode /* key */, + XkbAction * /* act */ +); + +extern _X_EXPORT int XkbDDXPrivate( + DeviceIntPtr /* dev */, + KeyCode /* key */, + XkbAction * /* act */ +); + +extern _X_EXPORT void XkbDisableComputedAutoRepeats( + DeviceIntPtr /* pXDev */, + unsigned int /* key */ +); + +extern _X_EXPORT void XkbSetRepeatKeys( + DeviceIntPtr /* pXDev */, + int /* key */, + int /* onoff */ +); + +extern _X_EXPORT int XkbLatchModifiers( + DeviceIntPtr /* pXDev */, + CARD8 /* mask */, + CARD8 /* latches */ +); + +extern _X_EXPORT int XkbLatchGroup( + DeviceIntPtr /* pXDev */, + int /* group */ +); + +extern _X_EXPORT void XkbClearAllLatchesAndLocks( + DeviceIntPtr /* dev */, + XkbSrvInfoPtr /* xkbi */, + Bool /* genEv */, + XkbEventCausePtr /* cause */ +); + +extern _X_EXPORT void XkbGetRulesDflts( + XkbRMLVOSet * /* rmlvo */ +); + +extern _X_EXPORT void XkbFreeRMLVOSet( + XkbRMLVOSet * /* rmlvo */, + Bool /* freeRMLVO */ +); + +extern _X_EXPORT void XkbSetRulesDflts( + XkbRMLVOSet * /* rmlvo */ +); + +extern _X_EXPORT void XkbDeleteRulesDflts( + void +); + +extern _X_EXPORT int SProcXkbDispatch( + ClientPtr /* client */ +); + +extern _X_EXPORT XkbGeometryPtr XkbLookupNamedGeometry( + DeviceIntPtr /* dev */, + Atom /* name */, + Bool * /* shouldFree */ +); + +extern _X_EXPORT void XkbConvertCase( + KeySym /* sym */, + KeySym * /* lower */, + KeySym * /* upper */ +); + +extern _X_EXPORT Status XkbChangeKeycodeRange( + XkbDescPtr /* xkb */, + int /* minKC */, + int /* maxKC */, + XkbChangesPtr /* changes */ +); + +extern _X_EXPORT void XkbFreeSrvLedInfo( + XkbSrvLedInfoPtr /* sli */ +); + +extern _X_EXPORT void XkbFreeInfo( + XkbSrvInfoPtr /* xkbi */ +); + +extern _X_EXPORT Status XkbChangeTypesOfKey( + XkbDescPtr /* xkb */, + int /* key */, + int /* nGroups */, + unsigned int /* groups */, + int * /* newTypesIn */, + XkbMapChangesPtr /* changes */ +); + +extern _X_EXPORT int XkbKeyTypesForCoreSymbols( + XkbDescPtr /* xkb */, + int /* map_width */, + KeySym * /* core_syms */, + unsigned int /* protected */, + int * /* types_inout */, + KeySym * /* xkb_syms_rtrn */ +); + +extern _X_EXPORT Bool XkbApplyCompatMapToKey( + XkbDescPtr /* xkb */, + KeyCode /* key */, + XkbChangesPtr /* changes */ +); + +extern _X_EXPORT Bool XkbApplyVirtualModChanges( + XkbDescPtr /* xkb */, + unsigned int /* changed */, + XkbChangesPtr /* changes */ +); + +extern _X_EXPORT void XkbSendNewKeyboardNotify( + DeviceIntPtr /* kbd */, + xkbNewKeyboardNotify * /* pNKN */ +); + +extern Bool XkbCopyKeymap( + XkbDescPtr /* dst */, + XkbDescPtr /* src */); + +extern _X_EXPORT Bool XkbCopyDeviceKeymap( + DeviceIntPtr /* dst */, + DeviceIntPtr /* src */); + +extern void XkbFilterEvents( + ClientPtr /* pClient */, + int /* nEvents */, + xEvent* /* xE */); + +extern int XkbGetEffectiveGroup( + XkbSrvInfoPtr /* xkbi */, + XkbStatePtr /* xkbstate */, + CARD8 /* keycode */); + +extern void XkbMergeLockedPtrBtns( + DeviceIntPtr /* master */); + +extern void XkbFakeDeviceButton( + DeviceIntPtr /* dev */, + int /* press */, + int /* button */); + + +#include "xkbfile.h" +#include "xkbrules.h" + +#define _XkbListKeycodes 0 +#define _XkbListTypes 1 +#define _XkbListCompat 2 +#define _XkbListSymbols 3 +#define _XkbListGeometry 4 +#define _XkbListNumComponents 5 + +typedef struct _XkbSrvListInfo { + int szPool; + int nPool; + char * pool; + + int maxRtrn; + int nTotal; + + char * pattern[_XkbListNumComponents]; + int nFound[_XkbListNumComponents]; +} XkbSrvListInfoRec,*XkbSrvListInfoPtr; + +extern _X_EXPORT Status XkbDDXList( + DeviceIntPtr /* dev */, + XkbSrvListInfoPtr /* listing */, + ClientPtr /* client */ +); + +extern _X_EXPORT unsigned int XkbDDXLoadKeymapByNames( + DeviceIntPtr /* keybd */, + XkbComponentNamesPtr /* names */, + unsigned int /* want */, + unsigned int /* need */, + XkbDescPtr * /* finfoRtrn */, + char * /* keymapNameRtrn */, + int /* keymapNameRtrnLen */ +); + +extern _X_EXPORT Bool XkbDDXNamesFromRules( + DeviceIntPtr /* keybd */, + char * /* rules */, + XkbRF_VarDefsPtr /* defs */, + XkbComponentNamesPtr /* names */ +); + +extern _X_EXPORT XkbDescPtr XkbCompileKeymap( + DeviceIntPtr /* dev */, + XkbRMLVOSet * /* rmlvo */ +); + +#endif /* _XKBSRV_H_ */ diff --git a/xorg-server/mi/midispcur.c b/xorg-server/mi/midispcur.c index ef5c4e29e..9b3e87a57 100644 --- a/xorg-server/mi/midispcur.c +++ b/xorg-server/mi/midispcur.c @@ -1,592 +1,592 @@ -/*
- * midispcur.c
- *
- * machine independent cursor display routines
- */
-
-
-/*
-
-Copyright 1989, 1998 The Open Group
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation.
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
-AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of The Open Group shall not be
-used in advertising or otherwise to promote the sale, use or other dealings
-in this Software without prior written authorization from The Open Group.
-*/
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-# include <X11/X.h>
-# include "misc.h"
-# include "input.h"
-# include "cursorstr.h"
-# include "windowstr.h"
-# include "regionstr.h"
-# include "dixstruct.h"
-# include "scrnintstr.h"
-# include "servermd.h"
-# include "mipointer.h"
-# include "misprite.h"
-# include "gcstruct.h"
-
-#ifdef ARGB_CURSOR
-# include "picturestr.h"
-#endif
-
-# include "inputstr.h"
-
-/* per-screen private data */
-static DevPrivateKeyRec miDCScreenKeyRec;
-#define miDCScreenKey (&miDCScreenKeyRec)
-static DevScreenPrivateKeyRec miDCCursorBitsKeyRec;
-#define miDCCursorBitsKey (&miDCCursorBitsKeyRec)
-static DevScreenPrivateKeyRec miDCDeviceKeyRec;
-#define miDCDeviceKey (&miDCDeviceKeyRec)
-
-static Bool miDCCloseScreen(int index, ScreenPtr pScreen);
-
-/* per device private data */
-typedef struct {
- GCPtr pSourceGC, pMaskGC;
- GCPtr pSaveGC, pRestoreGC;
- PixmapPtr pSave;
-#ifdef ARGB_CURSOR
- PicturePtr pRootPicture;
-#endif
-} miDCBufferRec, *miDCBufferPtr;
-
-#define miGetDCDevice(dev, screen) \
- ((DevHasCursor(dev)) ? \
- (miDCBufferPtr)dixLookupScreenPrivate(&dev->devPrivates, miDCDeviceKey, screen) : \
- (miDCBufferPtr)dixLookupScreenPrivate(&dev->u.master->devPrivates, miDCDeviceKey, screen))
-
-/*
- * The core pointer buffer will point to the index of the virtual core pointer
- * in the pCursorBuffers array.
- */
-typedef struct {
- CloseScreenProcPtr CloseScreen;
-} miDCScreenRec, *miDCScreenPtr;
-
-#define miGetDCScreen(s) ((miDCScreenPtr)(dixLookupPrivate(&(s)->devPrivates, miDCScreenKey)))
-
-/* per-cursor per-screen private data */
-typedef struct {
- PixmapPtr sourceBits; /* source bits */
- PixmapPtr maskBits; /* mask bits */
-#ifdef ARGB_CURSOR
- PicturePtr pPicture;
-#endif
-} miDCCursorRec, *miDCCursorPtr;
-
-Bool
-miDCInitialize (ScreenPtr pScreen, miPointerScreenFuncPtr screenFuncs)
-{
- miDCScreenPtr pScreenPriv;
-
- if (!dixRegisterPrivateKey(&miDCScreenKeyRec, PRIVATE_SCREEN, 0) ||
- !dixRegisterScreenPrivateKey(&miDCCursorBitsKeyRec, pScreen, PRIVATE_CURSOR_BITS, 0) ||
- !dixRegisterScreenPrivateKey(&miDCDeviceKeyRec, pScreen, PRIVATE_DEVICE, 0))
- return FALSE;
-
- pScreenPriv = malloc(sizeof (miDCScreenRec));
- if (!pScreenPriv)
- return FALSE;
-
- pScreenPriv->CloseScreen = pScreen->CloseScreen;
- pScreen->CloseScreen = miDCCloseScreen;
-
- dixSetPrivate(&pScreen->devPrivates, miDCScreenKey, pScreenPriv);
-
- if (!miSpriteInitialize (pScreen, screenFuncs))
- {
- free((pointer) pScreenPriv);
- return FALSE;
- }
- return TRUE;
-}
-
-static Bool
-miDCCloseScreen (int index, ScreenPtr pScreen)
-{
- miDCScreenPtr pScreenPriv;
-
- pScreenPriv = (miDCScreenPtr)dixLookupPrivate(&pScreen->devPrivates,
- miDCScreenKey);
- pScreen->CloseScreen = pScreenPriv->CloseScreen;
- free((pointer) pScreenPriv);
- return (*pScreen->CloseScreen) (index, pScreen);
-}
-
-Bool
-miDCRealizeCursor (ScreenPtr pScreen, CursorPtr pCursor)
-{
- if (pCursor->bits->refcnt <= 1)
- dixSetScreenPrivate(&pCursor->bits->devPrivates, miDCCursorBitsKey, pScreen, NULL);
- return TRUE;
-}
-
-#ifdef ARGB_CURSOR
-#define EnsurePicture(picture,draw,win) (picture || miDCMakePicture(&picture,draw,win))
-
-static VisualPtr
-miDCGetWindowVisual (WindowPtr pWin)
-{
- ScreenPtr pScreen = pWin->drawable.pScreen;
- VisualID vid = wVisual (pWin);
- int i;
-
- for (i = 0; i < pScreen->numVisuals; i++)
- if (pScreen->visuals[i].vid == vid)
- return &pScreen->visuals[i];
- return 0;
-}
-
-static PicturePtr
-miDCMakePicture (PicturePtr *ppPicture, DrawablePtr pDraw, WindowPtr pWin)
-{
- ScreenPtr pScreen = pDraw->pScreen;
- VisualPtr pVisual;
- PictFormatPtr pFormat;
- XID subwindow_mode = IncludeInferiors;
- PicturePtr pPicture;
- int error;
-
- pVisual = miDCGetWindowVisual (pWin);
- if (!pVisual)
- return 0;
- pFormat = PictureMatchVisual (pScreen, pDraw->depth, pVisual);
- if (!pFormat)
- return 0;
- pPicture = CreatePicture (0, pDraw, pFormat,
- CPSubwindowMode, &subwindow_mode,
- serverClient, &error);
- *ppPicture = pPicture;
- return pPicture;
-}
-#endif
-
-static miDCCursorPtr
-miDCRealize (ScreenPtr pScreen, CursorPtr pCursor)
-{
- miDCCursorPtr pPriv;
- GCPtr pGC;
- ChangeGCVal gcvals;
-
- pPriv = malloc(sizeof (miDCCursorRec));
- if (!pPriv)
- return NULL;
-#ifdef ARGB_CURSOR
- if (pCursor->bits->argb)
- {
- PixmapPtr pPixmap;
- PictFormatPtr pFormat;
- int error;
-
- pFormat = PictureMatchFormat (pScreen, 32, PICT_a8r8g8b8);
- if (!pFormat)
- {
- free((pointer) pPriv);
- return NULL;
- }
-
- pPriv->sourceBits = 0;
- pPriv->maskBits = 0;
- pPixmap = (*pScreen->CreatePixmap) (pScreen, pCursor->bits->width,
- pCursor->bits->height, 32,
- CREATE_PIXMAP_USAGE_SCRATCH);
- if (!pPixmap)
- {
- free((pointer) pPriv);
- return NULL;
- }
- pGC = GetScratchGC (32, pScreen);
- if (!pGC)
- {
- (*pScreen->DestroyPixmap) (pPixmap);
- free((pointer) pPriv);
- return NULL;
- }
- ValidateGC (&pPixmap->drawable, pGC);
- (*pGC->ops->PutImage) (&pPixmap->drawable, pGC, 32,
- 0, 0, pCursor->bits->width,
- pCursor->bits->height,
- 0, ZPixmap, (char *) pCursor->bits->argb);
- FreeScratchGC (pGC);
- pPriv->pPicture = CreatePicture (0, &pPixmap->drawable,
- pFormat, 0, 0, serverClient, &error);
- (*pScreen->DestroyPixmap) (pPixmap);
- if (!pPriv->pPicture)
- {
- free((pointer) pPriv);
- return NULL;
- }
- dixSetScreenPrivate(&pCursor->bits->devPrivates, miDCCursorBitsKey, pScreen, pPriv);
- return pPriv;
- }
- pPriv->pPicture = 0;
-#endif
- pPriv->sourceBits = (*pScreen->CreatePixmap) (pScreen, pCursor->bits->width, pCursor->bits->height, 1, 0);
- if (!pPriv->sourceBits)
- {
- free((pointer) pPriv);
- return NULL;
- }
- pPriv->maskBits = (*pScreen->CreatePixmap) (pScreen, pCursor->bits->width, pCursor->bits->height, 1, 0);
- if (!pPriv->maskBits)
- {
- (*pScreen->DestroyPixmap) (pPriv->sourceBits);
- free((pointer) pPriv);
- return NULL;
- }
- dixSetScreenPrivate(&pCursor->bits->devPrivates, miDCCursorBitsKey, pScreen, pPriv);
-
- /* create the two sets of bits, clipping as appropriate */
-
- pGC = GetScratchGC (1, pScreen);
- if (!pGC)
- {
- (void) miDCUnrealizeCursor (pScreen, pCursor);
- return NULL;
- }
-
- ValidateGC ((DrawablePtr)pPriv->sourceBits, pGC);
- (*pGC->ops->PutImage) ((DrawablePtr)pPriv->sourceBits, pGC, 1,
- 0, 0, pCursor->bits->width, pCursor->bits->height,
- 0, XYPixmap, (char *)pCursor->bits->source);
- gcvals.val = GXand;
- ChangeGC (NullClient, pGC, GCFunction, &gcvals);
- ValidateGC ((DrawablePtr)pPriv->sourceBits, pGC);
- (*pGC->ops->PutImage) ((DrawablePtr)pPriv->sourceBits, pGC, 1,
- 0, 0, pCursor->bits->width, pCursor->bits->height,
- 0, XYPixmap, (char *)pCursor->bits->mask);
-
- /* mask bits -- pCursor->mask & ~pCursor->source */
- gcvals.val = GXcopy;
- ChangeGC (NullClient, pGC, GCFunction, &gcvals);
- ValidateGC ((DrawablePtr)pPriv->maskBits, pGC);
- (*pGC->ops->PutImage) ((DrawablePtr)pPriv->maskBits, pGC, 1,
- 0, 0, pCursor->bits->width, pCursor->bits->height,
- 0, XYPixmap, (char *)pCursor->bits->mask);
- gcvals.val = GXandInverted;
- ChangeGC (NullClient, pGC, GCFunction, &gcvals);
- ValidateGC ((DrawablePtr)pPriv->maskBits, pGC);
- (*pGC->ops->PutImage) ((DrawablePtr)pPriv->maskBits, pGC, 1,
- 0, 0, pCursor->bits->width, pCursor->bits->height,
- 0, XYPixmap, (char *)pCursor->bits->source);
- FreeScratchGC (pGC);
- return pPriv;
-}
-
-Bool
-miDCUnrealizeCursor (ScreenPtr pScreen, CursorPtr pCursor)
-{
- miDCCursorPtr pPriv;
-
- pPriv = (miDCCursorPtr)dixLookupScreenPrivate(&pCursor->bits->devPrivates,
- miDCCursorBitsKey, pScreen);
- if (pPriv && (pCursor->bits->refcnt <= 1))
- {
- if (pPriv->sourceBits)
- (*pScreen->DestroyPixmap) (pPriv->sourceBits);
- if (pPriv->maskBits)
- (*pScreen->DestroyPixmap) (pPriv->maskBits);
-#ifdef ARGB_CURSOR
- if (pPriv->pPicture)
- FreePicture (pPriv->pPicture, 0);
-#endif
- free((pointer) pPriv);
- dixSetScreenPrivate(&pCursor->bits->devPrivates, miDCCursorBitsKey, pScreen, NULL);
- }
- return TRUE;
-}
-
-static void
-miDCPutBits (
- DrawablePtr pDrawable,
- miDCCursorPtr pPriv,
- GCPtr sourceGC,
- GCPtr maskGC,
- int x_org,
- int y_org,
- unsigned w,
- unsigned h,
- unsigned long source,
- unsigned long mask)
-{
- ChangeGCVal gcval;
- int x, y;
-
- if (sourceGC->fgPixel != source)
- {
- gcval.val = source;
- ChangeGC (NullClient, sourceGC, GCForeground, &gcval);
- }
- if (sourceGC->serialNumber != pDrawable->serialNumber)
- ValidateGC (pDrawable, sourceGC);
-
- if(sourceGC->miTranslate)
- {
- x = pDrawable->x + x_org;
- y = pDrawable->y + y_org;
- }
- else
- {
- x = x_org;
- y = y_org;
- }
-
- (*sourceGC->ops->PushPixels) (sourceGC, pPriv->sourceBits, pDrawable, w, h, x, y);
- if (maskGC->fgPixel != mask)
- {
- gcval.val = mask;
- ChangeGC (NullClient, maskGC, GCForeground, &gcval);
- }
- if (maskGC->serialNumber != pDrawable->serialNumber)
- ValidateGC (pDrawable, maskGC);
-
- if(maskGC->miTranslate)
- {
- x = pDrawable->x + x_org;
- y = pDrawable->y + y_org;
- }
- else
- {
- x = x_org;
- y = y_org;
- }
-
- (*maskGC->ops->PushPixels) (maskGC, pPriv->maskBits, pDrawable, w, h, x, y);
-}
-
-static GCPtr
-miDCMakeGC(WindowPtr pWin)
-{
- GCPtr pGC;
- int status;
- XID gcvals[2];
-
- gcvals[0] = IncludeInferiors;
- gcvals[1] = FALSE;
- pGC = CreateGC((DrawablePtr)pWin,
- GCSubwindowMode|GCGraphicsExposures, gcvals, &status,
- (XID)0, serverClient);
- return pGC;
-}
-
-
-Bool
-miDCPutUpCursor (DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor,
- int x, int y, unsigned long source, unsigned long mask)
-{
- miDCScreenPtr pScreenPriv;
- miDCCursorPtr pPriv;
- miDCBufferPtr pBuffer;
- WindowPtr pWin;
-
- pPriv = (miDCCursorPtr)dixLookupScreenPrivate(&pCursor->bits->devPrivates,
- miDCCursorBitsKey, pScreen);
- if (!pPriv)
- {
- pPriv = miDCRealize(pScreen, pCursor);
- if (!pPriv)
- return FALSE;
- }
- pScreenPriv = (miDCScreenPtr)dixLookupPrivate(&pScreen->devPrivates,
- miDCScreenKey);
- pWin = pScreen->root;
- pBuffer = miGetDCDevice(pDev, pScreen);
-
-#ifdef ARGB_CURSOR
- if (pPriv->pPicture)
- {
- if (!EnsurePicture(pBuffer->pRootPicture, &pWin->drawable, pWin))
- return FALSE;
- CompositePicture (PictOpOver,
- pPriv->pPicture,
- NULL,
- pBuffer->pRootPicture,
- 0, 0, 0, 0,
- x, y,
- pCursor->bits->width,
- pCursor->bits->height);
- }
- else
-#endif
- {
- miDCPutBits ((DrawablePtr)pWin, pPriv,
- pBuffer->pSourceGC, pBuffer->pMaskGC,
- x, y, pCursor->bits->width, pCursor->bits->height,
- source, mask);
- }
- return TRUE;
-}
-
-Bool
-miDCSaveUnderCursor (DeviceIntPtr pDev, ScreenPtr pScreen,
- int x, int y, int w, int h)
-{
- miDCScreenPtr pScreenPriv;
- miDCBufferPtr pBuffer;
- PixmapPtr pSave;
- WindowPtr pWin;
- GCPtr pGC;
-
- pScreenPriv = (miDCScreenPtr)dixLookupPrivate(&pScreen->devPrivates,
- miDCScreenKey);
- pBuffer = miGetDCDevice(pDev, pScreen);
-
- pSave = pBuffer->pSave;
- pWin = pScreen->root;
- if (!pSave || pSave->drawable.width < w || pSave->drawable.height < h)
- {
- if (pSave)
- (*pScreen->DestroyPixmap) (pSave);
- pBuffer->pSave = pSave =
- (*pScreen->CreatePixmap) (pScreen, w, h, pScreen->rootDepth, 0);
- if (!pSave)
- return FALSE;
- }
-
- pGC = pBuffer->pSaveGC;
- if (pSave->drawable.serialNumber != pGC->serialNumber)
- ValidateGC ((DrawablePtr) pSave, pGC);
- (*pGC->ops->CopyArea) ((DrawablePtr) pWin, (DrawablePtr) pSave, pGC,
- x, y, w, h, 0, 0);
- return TRUE;
-}
-
-Bool
-miDCRestoreUnderCursor (DeviceIntPtr pDev, ScreenPtr pScreen,
- int x, int y, int w, int h)
-{
- miDCScreenPtr pScreenPriv;
- miDCBufferPtr pBuffer;
- PixmapPtr pSave;
- WindowPtr pWin;
- GCPtr pGC;
-
- pScreenPriv = (miDCScreenPtr)dixLookupPrivate(&pScreen->devPrivates,
- miDCScreenKey);
- pBuffer = miGetDCDevice(pDev, pScreen);
- pSave = pBuffer->pSave;
-
- pWin = pScreen->root;
- if (!pSave)
- return FALSE;
-
- pGC = pBuffer->pRestoreGC;
- if (pWin->drawable.serialNumber != pGC->serialNumber)
- ValidateGC ((DrawablePtr) pWin, pGC);
- (*pGC->ops->CopyArea) ((DrawablePtr) pSave, (DrawablePtr) pWin, pGC,
- 0, 0, w, h, x, y);
- return TRUE;
-}
-
-Bool
-miDCDeviceInitialize(DeviceIntPtr pDev, ScreenPtr pScreen)
-{
- miDCBufferPtr pBuffer;
- WindowPtr pWin;
- int i;
-
- if (!DevHasCursor(pDev))
- return TRUE;
-
- for (i = 0; i < screenInfo.numScreens; i++)
- {
- pScreen = screenInfo.screens[i];
-
- pBuffer = calloc(1, sizeof(miDCBufferRec));
- if (!pBuffer)
- goto failure;
-
- dixSetScreenPrivate(&pDev->devPrivates, miDCDeviceKey, pScreen, pBuffer);
- pWin = pScreen->root;
-
- pBuffer->pSourceGC = miDCMakeGC(pWin);
- if (!pBuffer->pSourceGC)
- goto failure;
-
- pBuffer->pMaskGC = miDCMakeGC(pWin);
- if (!pBuffer->pMaskGC)
- goto failure;
-
- pBuffer->pSaveGC = miDCMakeGC(pWin);
- if (!pBuffer->pSaveGC)
- goto failure;
-
- pBuffer->pRestoreGC = miDCMakeGC(pWin);
- if (!pBuffer->pRestoreGC)
- goto failure;
-
-#ifdef ARGB_CURSOR
- pBuffer->pRootPicture = NULL;
-#endif
-
- /* (re)allocated lazily depending on the cursor size */
- pBuffer->pSave = NULL;
- }
-
- return TRUE;
-
-failure:
-
- miDCDeviceCleanup(pDev, pScreen);
-
- return FALSE;
-}
-
-void
-miDCDeviceCleanup(DeviceIntPtr pDev, ScreenPtr pScreen)
-{
- miDCBufferPtr pBuffer;
- int i;
-
- if (DevHasCursor(pDev))
- {
- for (i = 0; i < screenInfo.numScreens; i++)
- {
- pScreen = screenInfo.screens[i];
-
- pBuffer = miGetDCDevice(pDev, pScreen);
-
- if (pBuffer)
- {
- if (pBuffer->pSourceGC) FreeGC(pBuffer->pSourceGC, (GContext) 0);
- if (pBuffer->pMaskGC) FreeGC(pBuffer->pMaskGC, (GContext) 0);
- if (pBuffer->pSaveGC) FreeGC(pBuffer->pSaveGC, (GContext) 0);
- if (pBuffer->pRestoreGC) FreeGC(pBuffer->pRestoreGC, (GContext) 0);
-
-#ifdef ARGB_CURSOR
- /* If a pRootPicture was allocated for a root window, it
- * is freed when that root window is destroyed, so don't
- * free it again here. */
-#endif
-
- if (pBuffer->pSave) (*pScreen->DestroyPixmap)(pBuffer->pSave);
-
- free(pBuffer);
- dixSetScreenPrivate(&pDev->devPrivates, miDCDeviceKey, pScreen, NULL);
- }
- }
- }
-}
+/* + * midispcur.c + * + * machine independent cursor display routines + */ + + +/* + +Copyright 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. +*/ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +# include <X11/X.h> +# include "misc.h" +# include "input.h" +# include "cursorstr.h" +# include "windowstr.h" +# include "regionstr.h" +# include "dixstruct.h" +# include "scrnintstr.h" +# include "servermd.h" +# include "mipointer.h" +# include "misprite.h" +# include "gcstruct.h" + +#ifdef ARGB_CURSOR +# include "picturestr.h" +#endif + +# include "inputstr.h" + +/* per-screen private data */ +static DevPrivateKeyRec miDCScreenKeyRec; +#define miDCScreenKey (&miDCScreenKeyRec) +static DevScreenPrivateKeyRec miDCCursorBitsKeyRec; +#define miDCCursorBitsKey (&miDCCursorBitsKeyRec) +static DevScreenPrivateKeyRec miDCDeviceKeyRec; +#define miDCDeviceKey (&miDCDeviceKeyRec) + +static Bool miDCCloseScreen(int index, ScreenPtr pScreen); + +/* per device private data */ +typedef struct { + GCPtr pSourceGC, pMaskGC; + GCPtr pSaveGC, pRestoreGC; + PixmapPtr pSave; +#ifdef ARGB_CURSOR + PicturePtr pRootPicture; +#endif +} miDCBufferRec, *miDCBufferPtr; + +#define miGetDCDevice(dev, screen) \ + ((DevHasCursor(dev)) ? \ + (miDCBufferPtr)dixLookupScreenPrivate(&dev->devPrivates, miDCDeviceKey, screen) : \ + (miDCBufferPtr)dixLookupScreenPrivate(&GetMaster(dev, MASTER_POINTER)->devPrivates, miDCDeviceKey, screen)) + +/* + * The core pointer buffer will point to the index of the virtual core pointer + * in the pCursorBuffers array. + */ +typedef struct { + CloseScreenProcPtr CloseScreen; +} miDCScreenRec, *miDCScreenPtr; + +#define miGetDCScreen(s) ((miDCScreenPtr)(dixLookupPrivate(&(s)->devPrivates, miDCScreenKey))) + +/* per-cursor per-screen private data */ +typedef struct { + PixmapPtr sourceBits; /* source bits */ + PixmapPtr maskBits; /* mask bits */ +#ifdef ARGB_CURSOR + PicturePtr pPicture; +#endif +} miDCCursorRec, *miDCCursorPtr; + +Bool +miDCInitialize (ScreenPtr pScreen, miPointerScreenFuncPtr screenFuncs) +{ + miDCScreenPtr pScreenPriv; + + if (!dixRegisterPrivateKey(&miDCScreenKeyRec, PRIVATE_SCREEN, 0) || + !dixRegisterScreenPrivateKey(&miDCCursorBitsKeyRec, pScreen, PRIVATE_CURSOR_BITS, 0) || + !dixRegisterScreenPrivateKey(&miDCDeviceKeyRec, pScreen, PRIVATE_DEVICE, 0)) + return FALSE; + + pScreenPriv = malloc(sizeof (miDCScreenRec)); + if (!pScreenPriv) + return FALSE; + + pScreenPriv->CloseScreen = pScreen->CloseScreen; + pScreen->CloseScreen = miDCCloseScreen; + + dixSetPrivate(&pScreen->devPrivates, miDCScreenKey, pScreenPriv); + + if (!miSpriteInitialize (pScreen, screenFuncs)) + { + free((pointer) pScreenPriv); + return FALSE; + } + return TRUE; +} + +static Bool +miDCCloseScreen (int index, ScreenPtr pScreen) +{ + miDCScreenPtr pScreenPriv; + + pScreenPriv = (miDCScreenPtr)dixLookupPrivate(&pScreen->devPrivates, + miDCScreenKey); + pScreen->CloseScreen = pScreenPriv->CloseScreen; + free((pointer) pScreenPriv); + return (*pScreen->CloseScreen) (index, pScreen); +} + +Bool +miDCRealizeCursor (ScreenPtr pScreen, CursorPtr pCursor) +{ + if (pCursor->bits->refcnt <= 1) + dixSetScreenPrivate(&pCursor->bits->devPrivates, miDCCursorBitsKey, pScreen, NULL); + return TRUE; +} + +#ifdef ARGB_CURSOR +#define EnsurePicture(picture,draw,win) (picture || miDCMakePicture(&picture,draw,win)) + +static VisualPtr +miDCGetWindowVisual (WindowPtr pWin) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + VisualID vid = wVisual (pWin); + int i; + + for (i = 0; i < pScreen->numVisuals; i++) + if (pScreen->visuals[i].vid == vid) + return &pScreen->visuals[i]; + return 0; +} + +static PicturePtr +miDCMakePicture (PicturePtr *ppPicture, DrawablePtr pDraw, WindowPtr pWin) +{ + ScreenPtr pScreen = pDraw->pScreen; + VisualPtr pVisual; + PictFormatPtr pFormat; + XID subwindow_mode = IncludeInferiors; + PicturePtr pPicture; + int error; + + pVisual = miDCGetWindowVisual (pWin); + if (!pVisual) + return 0; + pFormat = PictureMatchVisual (pScreen, pDraw->depth, pVisual); + if (!pFormat) + return 0; + pPicture = CreatePicture (0, pDraw, pFormat, + CPSubwindowMode, &subwindow_mode, + serverClient, &error); + *ppPicture = pPicture; + return pPicture; +} +#endif + +static miDCCursorPtr +miDCRealize (ScreenPtr pScreen, CursorPtr pCursor) +{ + miDCCursorPtr pPriv; + GCPtr pGC; + ChangeGCVal gcvals; + + pPriv = malloc(sizeof (miDCCursorRec)); + if (!pPriv) + return NULL; +#ifdef ARGB_CURSOR + if (pCursor->bits->argb) + { + PixmapPtr pPixmap; + PictFormatPtr pFormat; + int error; + + pFormat = PictureMatchFormat (pScreen, 32, PICT_a8r8g8b8); + if (!pFormat) + { + free((pointer) pPriv); + return NULL; + } + + pPriv->sourceBits = 0; + pPriv->maskBits = 0; + pPixmap = (*pScreen->CreatePixmap) (pScreen, pCursor->bits->width, + pCursor->bits->height, 32, + CREATE_PIXMAP_USAGE_SCRATCH); + if (!pPixmap) + { + free((pointer) pPriv); + return NULL; + } + pGC = GetScratchGC (32, pScreen); + if (!pGC) + { + (*pScreen->DestroyPixmap) (pPixmap); + free((pointer) pPriv); + return NULL; + } + ValidateGC (&pPixmap->drawable, pGC); + (*pGC->ops->PutImage) (&pPixmap->drawable, pGC, 32, + 0, 0, pCursor->bits->width, + pCursor->bits->height, + 0, ZPixmap, (char *) pCursor->bits->argb); + FreeScratchGC (pGC); + pPriv->pPicture = CreatePicture (0, &pPixmap->drawable, + pFormat, 0, 0, serverClient, &error); + (*pScreen->DestroyPixmap) (pPixmap); + if (!pPriv->pPicture) + { + free((pointer) pPriv); + return NULL; + } + dixSetScreenPrivate(&pCursor->bits->devPrivates, miDCCursorBitsKey, pScreen, pPriv); + return pPriv; + } + pPriv->pPicture = 0; +#endif + pPriv->sourceBits = (*pScreen->CreatePixmap) (pScreen, pCursor->bits->width, pCursor->bits->height, 1, 0); + if (!pPriv->sourceBits) + { + free((pointer) pPriv); + return NULL; + } + pPriv->maskBits = (*pScreen->CreatePixmap) (pScreen, pCursor->bits->width, pCursor->bits->height, 1, 0); + if (!pPriv->maskBits) + { + (*pScreen->DestroyPixmap) (pPriv->sourceBits); + free((pointer) pPriv); + return NULL; + } + dixSetScreenPrivate(&pCursor->bits->devPrivates, miDCCursorBitsKey, pScreen, pPriv); + + /* create the two sets of bits, clipping as appropriate */ + + pGC = GetScratchGC (1, pScreen); + if (!pGC) + { + (void) miDCUnrealizeCursor (pScreen, pCursor); + return NULL; + } + + ValidateGC ((DrawablePtr)pPriv->sourceBits, pGC); + (*pGC->ops->PutImage) ((DrawablePtr)pPriv->sourceBits, pGC, 1, + 0, 0, pCursor->bits->width, pCursor->bits->height, + 0, XYPixmap, (char *)pCursor->bits->source); + gcvals.val = GXand; + ChangeGC (NullClient, pGC, GCFunction, &gcvals); + ValidateGC ((DrawablePtr)pPriv->sourceBits, pGC); + (*pGC->ops->PutImage) ((DrawablePtr)pPriv->sourceBits, pGC, 1, + 0, 0, pCursor->bits->width, pCursor->bits->height, + 0, XYPixmap, (char *)pCursor->bits->mask); + + /* mask bits -- pCursor->mask & ~pCursor->source */ + gcvals.val = GXcopy; + ChangeGC (NullClient, pGC, GCFunction, &gcvals); + ValidateGC ((DrawablePtr)pPriv->maskBits, pGC); + (*pGC->ops->PutImage) ((DrawablePtr)pPriv->maskBits, pGC, 1, + 0, 0, pCursor->bits->width, pCursor->bits->height, + 0, XYPixmap, (char *)pCursor->bits->mask); + gcvals.val = GXandInverted; + ChangeGC (NullClient, pGC, GCFunction, &gcvals); + ValidateGC ((DrawablePtr)pPriv->maskBits, pGC); + (*pGC->ops->PutImage) ((DrawablePtr)pPriv->maskBits, pGC, 1, + 0, 0, pCursor->bits->width, pCursor->bits->height, + 0, XYPixmap, (char *)pCursor->bits->source); + FreeScratchGC (pGC); + return pPriv; +} + +Bool +miDCUnrealizeCursor (ScreenPtr pScreen, CursorPtr pCursor) +{ + miDCCursorPtr pPriv; + + pPriv = (miDCCursorPtr)dixLookupScreenPrivate(&pCursor->bits->devPrivates, + miDCCursorBitsKey, pScreen); + if (pPriv && (pCursor->bits->refcnt <= 1)) + { + if (pPriv->sourceBits) + (*pScreen->DestroyPixmap) (pPriv->sourceBits); + if (pPriv->maskBits) + (*pScreen->DestroyPixmap) (pPriv->maskBits); +#ifdef ARGB_CURSOR + if (pPriv->pPicture) + FreePicture (pPriv->pPicture, 0); +#endif + free((pointer) pPriv); + dixSetScreenPrivate(&pCursor->bits->devPrivates, miDCCursorBitsKey, pScreen, NULL); + } + return TRUE; +} + +static void +miDCPutBits ( + DrawablePtr pDrawable, + miDCCursorPtr pPriv, + GCPtr sourceGC, + GCPtr maskGC, + int x_org, + int y_org, + unsigned w, + unsigned h, + unsigned long source, + unsigned long mask) +{ + ChangeGCVal gcval; + int x, y; + + if (sourceGC->fgPixel != source) + { + gcval.val = source; + ChangeGC (NullClient, sourceGC, GCForeground, &gcval); + } + if (sourceGC->serialNumber != pDrawable->serialNumber) + ValidateGC (pDrawable, sourceGC); + + if(sourceGC->miTranslate) + { + x = pDrawable->x + x_org; + y = pDrawable->y + y_org; + } + else + { + x = x_org; + y = y_org; + } + + (*sourceGC->ops->PushPixels) (sourceGC, pPriv->sourceBits, pDrawable, w, h, x, y); + if (maskGC->fgPixel != mask) + { + gcval.val = mask; + ChangeGC (NullClient, maskGC, GCForeground, &gcval); + } + if (maskGC->serialNumber != pDrawable->serialNumber) + ValidateGC (pDrawable, maskGC); + + if(maskGC->miTranslate) + { + x = pDrawable->x + x_org; + y = pDrawable->y + y_org; + } + else + { + x = x_org; + y = y_org; + } + + (*maskGC->ops->PushPixels) (maskGC, pPriv->maskBits, pDrawable, w, h, x, y); +} + +static GCPtr +miDCMakeGC(WindowPtr pWin) +{ + GCPtr pGC; + int status; + XID gcvals[2]; + + gcvals[0] = IncludeInferiors; + gcvals[1] = FALSE; + pGC = CreateGC((DrawablePtr)pWin, + GCSubwindowMode|GCGraphicsExposures, gcvals, &status, + (XID)0, serverClient); + return pGC; +} + + +Bool +miDCPutUpCursor (DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor, + int x, int y, unsigned long source, unsigned long mask) +{ + miDCScreenPtr pScreenPriv; + miDCCursorPtr pPriv; + miDCBufferPtr pBuffer; + WindowPtr pWin; + + pPriv = (miDCCursorPtr)dixLookupScreenPrivate(&pCursor->bits->devPrivates, + miDCCursorBitsKey, pScreen); + if (!pPriv) + { + pPriv = miDCRealize(pScreen, pCursor); + if (!pPriv) + return FALSE; + } + pScreenPriv = (miDCScreenPtr)dixLookupPrivate(&pScreen->devPrivates, + miDCScreenKey); + pWin = pScreen->root; + pBuffer = miGetDCDevice(pDev, pScreen); + +#ifdef ARGB_CURSOR + if (pPriv->pPicture) + { + if (!EnsurePicture(pBuffer->pRootPicture, &pWin->drawable, pWin)) + return FALSE; + CompositePicture (PictOpOver, + pPriv->pPicture, + NULL, + pBuffer->pRootPicture, + 0, 0, 0, 0, + x, y, + pCursor->bits->width, + pCursor->bits->height); + } + else +#endif + { + miDCPutBits ((DrawablePtr)pWin, pPriv, + pBuffer->pSourceGC, pBuffer->pMaskGC, + x, y, pCursor->bits->width, pCursor->bits->height, + source, mask); + } + return TRUE; +} + +Bool +miDCSaveUnderCursor (DeviceIntPtr pDev, ScreenPtr pScreen, + int x, int y, int w, int h) +{ + miDCScreenPtr pScreenPriv; + miDCBufferPtr pBuffer; + PixmapPtr pSave; + WindowPtr pWin; + GCPtr pGC; + + pScreenPriv = (miDCScreenPtr)dixLookupPrivate(&pScreen->devPrivates, + miDCScreenKey); + pBuffer = miGetDCDevice(pDev, pScreen); + + pSave = pBuffer->pSave; + pWin = pScreen->root; + if (!pSave || pSave->drawable.width < w || pSave->drawable.height < h) + { + if (pSave) + (*pScreen->DestroyPixmap) (pSave); + pBuffer->pSave = pSave = + (*pScreen->CreatePixmap) (pScreen, w, h, pScreen->rootDepth, 0); + if (!pSave) + return FALSE; + } + + pGC = pBuffer->pSaveGC; + if (pSave->drawable.serialNumber != pGC->serialNumber) + ValidateGC ((DrawablePtr) pSave, pGC); + (*pGC->ops->CopyArea) ((DrawablePtr) pWin, (DrawablePtr) pSave, pGC, + x, y, w, h, 0, 0); + return TRUE; +} + +Bool +miDCRestoreUnderCursor (DeviceIntPtr pDev, ScreenPtr pScreen, + int x, int y, int w, int h) +{ + miDCScreenPtr pScreenPriv; + miDCBufferPtr pBuffer; + PixmapPtr pSave; + WindowPtr pWin; + GCPtr pGC; + + pScreenPriv = (miDCScreenPtr)dixLookupPrivate(&pScreen->devPrivates, + miDCScreenKey); + pBuffer = miGetDCDevice(pDev, pScreen); + pSave = pBuffer->pSave; + + pWin = pScreen->root; + if (!pSave) + return FALSE; + + pGC = pBuffer->pRestoreGC; + if (pWin->drawable.serialNumber != pGC->serialNumber) + ValidateGC ((DrawablePtr) pWin, pGC); + (*pGC->ops->CopyArea) ((DrawablePtr) pSave, (DrawablePtr) pWin, pGC, + 0, 0, w, h, x, y); + return TRUE; +} + +Bool +miDCDeviceInitialize(DeviceIntPtr pDev, ScreenPtr pScreen) +{ + miDCBufferPtr pBuffer; + WindowPtr pWin; + int i; + + if (!DevHasCursor(pDev)) + return TRUE; + + for (i = 0; i < screenInfo.numScreens; i++) + { + pScreen = screenInfo.screens[i]; + + pBuffer = calloc(1, sizeof(miDCBufferRec)); + if (!pBuffer) + goto failure; + + dixSetScreenPrivate(&pDev->devPrivates, miDCDeviceKey, pScreen, pBuffer); + pWin = pScreen->root; + + pBuffer->pSourceGC = miDCMakeGC(pWin); + if (!pBuffer->pSourceGC) + goto failure; + + pBuffer->pMaskGC = miDCMakeGC(pWin); + if (!pBuffer->pMaskGC) + goto failure; + + pBuffer->pSaveGC = miDCMakeGC(pWin); + if (!pBuffer->pSaveGC) + goto failure; + + pBuffer->pRestoreGC = miDCMakeGC(pWin); + if (!pBuffer->pRestoreGC) + goto failure; + +#ifdef ARGB_CURSOR + pBuffer->pRootPicture = NULL; +#endif + + /* (re)allocated lazily depending on the cursor size */ + pBuffer->pSave = NULL; + } + + return TRUE; + +failure: + + miDCDeviceCleanup(pDev, pScreen); + + return FALSE; +} + +void +miDCDeviceCleanup(DeviceIntPtr pDev, ScreenPtr pScreen) +{ + miDCBufferPtr pBuffer; + int i; + + if (DevHasCursor(pDev)) + { + for (i = 0; i < screenInfo.numScreens; i++) + { + pScreen = screenInfo.screens[i]; + + pBuffer = miGetDCDevice(pDev, pScreen); + + if (pBuffer) + { + if (pBuffer->pSourceGC) FreeGC(pBuffer->pSourceGC, (GContext) 0); + if (pBuffer->pMaskGC) FreeGC(pBuffer->pMaskGC, (GContext) 0); + if (pBuffer->pSaveGC) FreeGC(pBuffer->pSaveGC, (GContext) 0); + if (pBuffer->pRestoreGC) FreeGC(pBuffer->pRestoreGC, (GContext) 0); + +#ifdef ARGB_CURSOR + /* If a pRootPicture was allocated for a root window, it + * is freed when that root window is destroyed, so don't + * free it again here. */ +#endif + + if (pBuffer->pSave) (*pScreen->DestroyPixmap)(pBuffer->pSave); + + free(pBuffer); + dixSetScreenPrivate(&pDev->devPrivates, miDCDeviceKey, pScreen, NULL); + } + } + } +} diff --git a/xorg-server/mi/mieq.c b/xorg-server/mi/mieq.c index 974bec77d..08a0c8758 100644 --- a/xorg-server/mi/mieq.c +++ b/xorg-server/mi/mieq.c @@ -1,495 +1,497 @@ -/*
- *
-Copyright 1990, 1998 The Open Group
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation.
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
-AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of The Open Group shall not be
-used in advertising or otherwise to promote the sale, use or other dealings
-in this Software without prior written authorization from The Open Group.
- *
- * Author: Keith Packard, MIT X Consortium
- */
-
-/*
- * mieq.c
- *
- * Machine independent event queue
- *
- */
-
-#if HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-# include <X11/X.h>
-# include <X11/Xmd.h>
-# include <X11/Xproto.h>
-# include "misc.h"
-# include "windowstr.h"
-# include "pixmapstr.h"
-# include "inputstr.h"
-# include "mi.h"
-# include "mipointer.h"
-# include "scrnintstr.h"
-# include <X11/extensions/XI.h>
-# include <X11/extensions/XIproto.h>
-# include <X11/extensions/geproto.h>
-# include "extinit.h"
-# include "exglobals.h"
-# include "eventstr.h"
-
-#ifdef DPMSExtension
-# include "dpmsproc.h"
-# include <X11/extensions/dpmsconst.h>
-#endif
-
-#define QUEUE_SIZE 512
-
-#define EnqueueScreen(dev) dev->spriteInfo->sprite->pEnqueueScreen
-#define DequeueScreen(dev) dev->spriteInfo->sprite->pDequeueScreen
-
-typedef struct _Event {
- EventListPtr events;
- ScreenPtr pScreen;
- DeviceIntPtr pDev; /* device this event _originated_ from */
-} EventRec, *EventPtr;
-
-typedef struct _EventQueue {
- HWEventQueueType head, tail; /* long for SetInputCheck */
- CARD32 lastEventTime; /* to avoid time running backwards */
- int lastMotion; /* device ID if last event motion? */
- EventRec events[QUEUE_SIZE]; /* static allocation for signals */
- mieqHandler handlers[128]; /* custom event handler */
-} EventQueueRec, *EventQueuePtr;
-
-static EventQueueRec miEventQueue;
-
-#ifdef XQUARTZ
-#include <pthread.h>
-static pthread_mutex_t miEventQueueMutex = PTHREAD_MUTEX_INITIALIZER;
-
-extern BOOL serverInitComplete;
-extern pthread_mutex_t serverInitCompleteMutex;
-extern pthread_cond_t serverInitCompleteCond;
-
-static inline void wait_for_server_init(void) {
- /* If the server hasn't finished initializing, wait for it... */
- if(!serverInitComplete) {
- pthread_mutex_lock(&serverInitCompleteMutex);
- while(!serverInitComplete)
- pthread_cond_wait(&serverInitCompleteCond, &serverInitCompleteMutex);
- pthread_mutex_unlock(&serverInitCompleteMutex);
- }
-}
-#endif
-
-Bool
-mieqInit(void)
-{
- int i;
-
- miEventQueue.head = miEventQueue.tail = 0;
- miEventQueue.lastEventTime = GetTimeInMillis ();
- miEventQueue.lastMotion = FALSE;
- for (i = 0; i < 128; i++)
- miEventQueue.handlers[i] = NULL;
- for (i = 0; i < QUEUE_SIZE; i++)
- {
- if (miEventQueue.events[i].events == NULL) {
- EventListPtr evlist = InitEventList(1);
- if (!evlist)
- FatalError("Could not allocate event queue.\n");
- miEventQueue.events[i].events = evlist;
- }
- }
-
- SetInputCheck(&miEventQueue.head, &miEventQueue.tail);
- return TRUE;
-}
-
-void
-mieqFini(void)
-{
- int i;
- for (i = 0; i < QUEUE_SIZE; i++)
- {
- if (miEventQueue.events[i].events != NULL) {
- FreeEventList(miEventQueue.events[i].events, 1);
- miEventQueue.events[i].events = NULL;
- }
- }
-}
-
-/*
- * Must be reentrant with ProcessInputEvents. Assumption: mieqEnqueue
- * will never be interrupted. If this is called from both signal
- * handlers and regular code, make sure the signal is suspended when
- * called from regular code.
- */
-
-void
-mieqEnqueue(DeviceIntPtr pDev, InternalEvent *e)
-{
- unsigned int oldtail = miEventQueue.tail;
- EventListPtr evt;
- int isMotion = 0;
- int evlen;
- Time time;
-
-#ifdef XQUARTZ
- wait_for_server_init();
- pthread_mutex_lock(&miEventQueueMutex);
-#endif
-
- CHECKEVENT(e);
-
- /* avoid merging events from different devices */
- if (e->any.type == ET_Motion)
- isMotion = pDev->id;
-
- if (isMotion && isMotion == miEventQueue.lastMotion &&
- oldtail != miEventQueue.head) {
- oldtail = (oldtail - 1) % QUEUE_SIZE;
- }
- else {
- static int stuck = 0;
- /* Toss events which come in late. Usually this means your server's
- * stuck in an infinite loop somewhere, but SIGIO is still getting
- * handled. */
- if (((oldtail + 1) % QUEUE_SIZE) == miEventQueue.head) {
- if (!stuck) {
- ErrorF("[mi] EQ overflowing. The server is probably stuck "
- "in an infinite loop.\n");
- xorg_backtrace();
- stuck = 1;
- }
-#ifdef XQUARTZ
- pthread_mutex_unlock(&miEventQueueMutex);
-#endif
- return;
- }
- stuck = 0;
- }
-
- evlen = e->any.length;
- evt = miEventQueue.events[oldtail].events;
- if (evt->evlen < evlen)
- {
- evt->evlen = evlen;
- evt->event = realloc(evt->event, evt->evlen);
- if (!evt->event)
- {
- ErrorF("[mi] Running out of memory. Tossing event.\n");
-#ifdef XQUARTZ
- pthread_mutex_unlock(&miEventQueueMutex);
-#endif
- return;
- }
- }
-
- memcpy(evt->event, e, evlen);
-
- time = e->any.time;
- /* Make sure that event times don't go backwards - this
- * is "unnecessary", but very useful. */
- if (time < miEventQueue.lastEventTime &&
- miEventQueue.lastEventTime - time < 10000)
- e->any.time = miEventQueue.lastEventTime;
-
- miEventQueue.lastEventTime = ((InternalEvent*)evt->event)->any.time;
- miEventQueue.events[oldtail].pScreen = pDev ? EnqueueScreen(pDev) : NULL;
- miEventQueue.events[oldtail].pDev = pDev;
-
- miEventQueue.lastMotion = isMotion;
- miEventQueue.tail = (oldtail + 1) % QUEUE_SIZE;
-#ifdef XQUARTZ
- pthread_mutex_unlock(&miEventQueueMutex);
-#endif
-}
-
-void
-mieqSwitchScreen(DeviceIntPtr pDev, ScreenPtr pScreen, Bool fromDIX)
-{
-#ifdef XQUARTZ
- pthread_mutex_lock(&miEventQueueMutex);
-#endif
- EnqueueScreen(pDev) = pScreen;
- if (fromDIX)
- DequeueScreen(pDev) = pScreen;
-#ifdef XQUARTZ
- pthread_mutex_unlock(&miEventQueueMutex);
-#endif
-}
-
-void
-mieqSetHandler(int event, mieqHandler handler)
-{
-#ifdef XQUARTZ
- pthread_mutex_lock(&miEventQueueMutex);
-#endif
- if (handler && miEventQueue.handlers[event])
- ErrorF("[mi] mieq: warning: overriding existing handler %p with %p for "
- "event %d\n", miEventQueue.handlers[event], handler, event);
-
- miEventQueue.handlers[event] = handler;
-#ifdef XQUARTZ
- pthread_mutex_unlock(&miEventQueueMutex);
-#endif
-}
-
-/**
- * Change the device id of the given event to the given device's id.
- */
-static void
-ChangeDeviceID(DeviceIntPtr dev, InternalEvent* event)
-{
- switch(event->any.type)
- {
- case ET_Motion:
- case ET_KeyPress:
- case ET_KeyRelease:
- case ET_ButtonPress:
- case ET_ButtonRelease:
- case ET_ProximityIn:
- case ET_ProximityOut:
- case ET_Hierarchy:
- case ET_DeviceChanged:
- event->device_event.deviceid = dev->id;
- break;
-#if XFreeXDGA
- case ET_DGAEvent:
- break;
-#endif
- case ET_RawKeyPress:
- case ET_RawKeyRelease:
- case ET_RawButtonPress:
- case ET_RawButtonRelease:
- case ET_RawMotion:
- event->raw_event.deviceid = dev->id;
- break;
- default:
- ErrorF("[mi] Unknown event type (%d), cannot change id.\n",
- event->any.type);
- }
-}
-
-static void
-FixUpEventForMaster(DeviceIntPtr mdev, DeviceIntPtr sdev,
- InternalEvent* original, InternalEvent *master)
-{
- CHECKEVENT(original);
- CHECKEVENT(master);
- /* Ensure chained button mappings, i.e. that the detail field is the
- * value of the mapped button on the SD, not the physical button */
- if (original->any.type == ET_ButtonPress ||
- original->any.type == ET_ButtonRelease)
- {
- int btn = original->device_event.detail.button;
- if (!sdev->button)
- return; /* Should never happen */
-
- master->device_event.detail.button = sdev->button->map[btn];
- }
-}
-
-/**
- * Copy the given event into master.
- * @param sdev The slave device the original event comes from
- * @param original The event as it came from the EQ
- * @param copy The event after being copied
- * @return The master device or NULL if the device is a floating slave.
- */
-DeviceIntPtr
-CopyGetMasterEvent(DeviceIntPtr sdev,
- InternalEvent* original, InternalEvent *copy)
-{
- DeviceIntPtr mdev;
- int len = original->any.length;
- int type = original->any.type;
-
- CHECKEVENT(original);
-
- /* ET_XQuartz has sdev == NULL */
- if (!sdev || !sdev->u.master)
- return NULL;
-
-#if XFreeXDGA
- if (type == ET_DGAEvent)
- type = original->dga_event.subtype;
-#endif
-
- switch(type)
- {
- case ET_KeyPress:
- case ET_KeyRelease:
- mdev = GetMaster(sdev, MASTER_KEYBOARD);
- break;
- case ET_ButtonPress:
- case ET_ButtonRelease:
- case ET_Motion:
- case ET_ProximityIn:
- case ET_ProximityOut:
- mdev = GetMaster(sdev, MASTER_POINTER);
- break;
- default:
- mdev = sdev->u.master;
- break;
- }
-
- memcpy(copy, original, len);
- ChangeDeviceID(mdev, copy);
- FixUpEventForMaster(mdev, sdev, original, copy);
-
- return mdev;
-}
-
-
-/**
- * Post the given @event through the device hierarchy, as appropriate.
- * Use this function if an event must be posted for a given device during the
- * usual event processing cycle.
- */
-void
-mieqProcessDeviceEvent(DeviceIntPtr dev,
- InternalEvent *event,
- ScreenPtr screen)
-{
- mieqHandler handler;
- int x = 0, y = 0;
- DeviceIntPtr master;
- InternalEvent mevent; /* master event */
-
- CHECKEVENT(event);
-
- /* Custom event handler */
- handler = miEventQueue.handlers[event->any.type];
-
- switch (event->any.type) {
- /* Catch events that include valuator information and check if they
- * are changing the screen */
- case ET_Motion:
- case ET_KeyPress:
- case ET_KeyRelease:
- case ET_ButtonPress:
- case ET_ButtonRelease:
- if (dev && screen && screen != DequeueScreen(dev) && !handler) {
- DequeueScreen(dev) = screen;
- x = event->device_event.root_x;
- y = event->device_event.root_y;
- NewCurrentScreen (dev, DequeueScreen(dev), x, y);
- }
- break;
- default:
- break;
- }
- master = CopyGetMasterEvent(dev, event, &mevent);
-
- if (master)
- master->u.lastSlave = dev;
-
- /* If someone's registered a custom event handler, let them
- * steal it. */
- if (handler)
- {
- int screenNum = dev && DequeueScreen(dev) ? DequeueScreen(dev)->myNum : (screen ? screen->myNum : 0);
- handler(screenNum, event, dev);
- /* Check for the SD's master in case the device got detached
- * during event processing */
- if (master && dev->u.master)
- handler(screenNum, &mevent, master);
- } else
- {
- /* process slave first, then master */
- dev->public.processInputProc(event, dev);
-
- /* Check for the SD's master in case the device got detached
- * during event processing */
- if (master && dev->u.master)
- master->public.processInputProc(&mevent, master);
- }
-}
-
-/* Call this from ProcessInputEvents(). */
-void
-mieqProcessInputEvents(void)
-{
- EventRec *e = NULL;
- int evlen;
- ScreenPtr screen;
- static InternalEvent *event = NULL;
- static size_t event_size = 0;
- DeviceIntPtr dev = NULL,
- master = NULL;
-
-#ifdef XQUARTZ
- pthread_mutex_lock(&miEventQueueMutex);
-#endif
-
- while (miEventQueue.head != miEventQueue.tail) {
- e = &miEventQueue.events[miEventQueue.head];
-
- evlen = e->events->evlen;
- if(evlen > event_size)
- {
- event = realloc(event, evlen);
- event_size = evlen;
- }
-
-
- if (!event)
- FatalError("[mi] No memory left for event processing.\n");
-
- memcpy(event, e->events->event, evlen);
-
-
- dev = e->pDev;
- screen = e->pScreen;
-
- miEventQueue.head = (miEventQueue.head + 1) % QUEUE_SIZE;
-
-#ifdef XQUARTZ
- pthread_mutex_unlock(&miEventQueueMutex);
-#endif
-
- master = (dev && !IsMaster(dev) && dev->u.master) ? dev->u.master : NULL;
-
- if (screenIsSaved == SCREEN_SAVER_ON)
- dixSaveScreens (serverClient, SCREEN_SAVER_OFF, ScreenSaverReset);
-#ifdef DPMSExtension
- else if (DPMSPowerLevel != DPMSModeOn)
- SetScreenSaverTimer();
-
- if (DPMSPowerLevel != DPMSModeOn)
- DPMSSet(serverClient, DPMSModeOn);
-#endif
-
- mieqProcessDeviceEvent(dev, event, screen);
-
- /* Update the sprite now. Next event may be from different device. */
- if (event->any.type == ET_Motion && master)
- miPointerUpdateSprite(dev);
-
-#ifdef XQUARTZ
- pthread_mutex_lock(&miEventQueueMutex);
-#endif
- }
-#ifdef XQUARTZ
- pthread_mutex_unlock(&miEventQueueMutex);
-#endif
-}
-
+/* + * +Copyright 1990, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + * + * Author: Keith Packard, MIT X Consortium + */ + +/* + * mieq.c + * + * Machine independent event queue + * + */ + +#if HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +# include <X11/X.h> +# include <X11/Xmd.h> +# include <X11/Xproto.h> +# include "misc.h" +# include "windowstr.h" +# include "pixmapstr.h" +# include "inputstr.h" +# include "mi.h" +# include "mipointer.h" +# include "scrnintstr.h" +# include <X11/extensions/XI.h> +# include <X11/extensions/XIproto.h> +# include <X11/extensions/geproto.h> +# include "extinit.h" +# include "exglobals.h" +# include "eventstr.h" + +#ifdef DPMSExtension +# include "dpmsproc.h" +# include <X11/extensions/dpmsconst.h> +#endif + +#define QUEUE_SIZE 512 + +#define EnqueueScreen(dev) dev->spriteInfo->sprite->pEnqueueScreen +#define DequeueScreen(dev) dev->spriteInfo->sprite->pDequeueScreen + +typedef struct _Event { + EventListPtr events; + ScreenPtr pScreen; + DeviceIntPtr pDev; /* device this event _originated_ from */ +} EventRec, *EventPtr; + +typedef struct _EventQueue { + HWEventQueueType head, tail; /* long for SetInputCheck */ + CARD32 lastEventTime; /* to avoid time running backwards */ + int lastMotion; /* device ID if last event motion? */ + EventRec events[QUEUE_SIZE]; /* static allocation for signals */ + mieqHandler handlers[128]; /* custom event handler */ +} EventQueueRec, *EventQueuePtr; + +static EventQueueRec miEventQueue; + +#ifdef XQUARTZ +#include <pthread.h> +static pthread_mutex_t miEventQueueMutex = PTHREAD_MUTEX_INITIALIZER; + +extern BOOL serverInitComplete; +extern pthread_mutex_t serverInitCompleteMutex; +extern pthread_cond_t serverInitCompleteCond; + +static inline void wait_for_server_init(void) { + /* If the server hasn't finished initializing, wait for it... */ + if(!serverInitComplete) { + pthread_mutex_lock(&serverInitCompleteMutex); + while(!serverInitComplete) + pthread_cond_wait(&serverInitCompleteCond, &serverInitCompleteMutex); + pthread_mutex_unlock(&serverInitCompleteMutex); + } +} +#endif + +Bool +mieqInit(void) +{ + int i; + + miEventQueue.head = miEventQueue.tail = 0; + miEventQueue.lastEventTime = GetTimeInMillis (); + miEventQueue.lastMotion = FALSE; + for (i = 0; i < 128; i++) + miEventQueue.handlers[i] = NULL; + for (i = 0; i < QUEUE_SIZE; i++) + { + if (miEventQueue.events[i].events == NULL) { + EventListPtr evlist = InitEventList(1); + if (!evlist) + FatalError("Could not allocate event queue.\n"); + miEventQueue.events[i].events = evlist; + } + } + + SetInputCheck(&miEventQueue.head, &miEventQueue.tail); + return TRUE; +} + +void +mieqFini(void) +{ + int i; + for (i = 0; i < QUEUE_SIZE; i++) + { + if (miEventQueue.events[i].events != NULL) { + FreeEventList(miEventQueue.events[i].events, 1); + miEventQueue.events[i].events = NULL; + } + } +} + +/* + * Must be reentrant with ProcessInputEvents. Assumption: mieqEnqueue + * will never be interrupted. If this is called from both signal + * handlers and regular code, make sure the signal is suspended when + * called from regular code. + */ + +void +mieqEnqueue(DeviceIntPtr pDev, InternalEvent *e) +{ + unsigned int oldtail = miEventQueue.tail; + EventListPtr evt; + int isMotion = 0; + int evlen; + Time time; + +#ifdef XQUARTZ + wait_for_server_init(); + pthread_mutex_lock(&miEventQueueMutex); +#endif + + CHECKEVENT(e); + + /* avoid merging events from different devices */ + if (e->any.type == ET_Motion) + isMotion = pDev->id; + + if (isMotion && isMotion == miEventQueue.lastMotion && + oldtail != miEventQueue.head) { + oldtail = (oldtail - 1) % QUEUE_SIZE; + } + else { + static int stuck = 0; + /* Toss events which come in late. Usually this means your server's + * stuck in an infinite loop somewhere, but SIGIO is still getting + * handled. */ + if (((oldtail + 1) % QUEUE_SIZE) == miEventQueue.head) { + if (!stuck) { + ErrorF("[mi] EQ overflowing. The server is probably stuck " + "in an infinite loop.\n"); + xorg_backtrace(); + stuck = 1; + } +#ifdef XQUARTZ + pthread_mutex_unlock(&miEventQueueMutex); +#endif + return; + } + stuck = 0; + } + + evlen = e->any.length; + evt = miEventQueue.events[oldtail].events; + if (evt->evlen < evlen) + { + evt->evlen = evlen; + evt->event = realloc(evt->event, evt->evlen); + if (!evt->event) + { + ErrorF("[mi] Running out of memory. Tossing event.\n"); +#ifdef XQUARTZ + pthread_mutex_unlock(&miEventQueueMutex); +#endif + return; + } + } + + memcpy(evt->event, e, evlen); + + time = e->any.time; + /* Make sure that event times don't go backwards - this + * is "unnecessary", but very useful. */ + if (time < miEventQueue.lastEventTime && + miEventQueue.lastEventTime - time < 10000) + e->any.time = miEventQueue.lastEventTime; + + miEventQueue.lastEventTime = ((InternalEvent*)evt->event)->any.time; + miEventQueue.events[oldtail].pScreen = pDev ? EnqueueScreen(pDev) : NULL; + miEventQueue.events[oldtail].pDev = pDev; + + miEventQueue.lastMotion = isMotion; + miEventQueue.tail = (oldtail + 1) % QUEUE_SIZE; +#ifdef XQUARTZ + pthread_mutex_unlock(&miEventQueueMutex); +#endif +} + +void +mieqSwitchScreen(DeviceIntPtr pDev, ScreenPtr pScreen, Bool fromDIX) +{ +#ifdef XQUARTZ + pthread_mutex_lock(&miEventQueueMutex); +#endif + EnqueueScreen(pDev) = pScreen; + if (fromDIX) + DequeueScreen(pDev) = pScreen; +#ifdef XQUARTZ + pthread_mutex_unlock(&miEventQueueMutex); +#endif +} + +void +mieqSetHandler(int event, mieqHandler handler) +{ +#ifdef XQUARTZ + pthread_mutex_lock(&miEventQueueMutex); +#endif + if (handler && miEventQueue.handlers[event]) + ErrorF("[mi] mieq: warning: overriding existing handler %p with %p for " + "event %d\n", miEventQueue.handlers[event], handler, event); + + miEventQueue.handlers[event] = handler; +#ifdef XQUARTZ + pthread_mutex_unlock(&miEventQueueMutex); +#endif +} + +/** + * Change the device id of the given event to the given device's id. + */ +static void +ChangeDeviceID(DeviceIntPtr dev, InternalEvent* event) +{ + switch(event->any.type) + { + case ET_Motion: + case ET_KeyPress: + case ET_KeyRelease: + case ET_ButtonPress: + case ET_ButtonRelease: + case ET_ProximityIn: + case ET_ProximityOut: + case ET_Hierarchy: + case ET_DeviceChanged: + event->device_event.deviceid = dev->id; + break; +#if XFreeXDGA + case ET_DGAEvent: + break; +#endif + case ET_RawKeyPress: + case ET_RawKeyRelease: + case ET_RawButtonPress: + case ET_RawButtonRelease: + case ET_RawMotion: + event->raw_event.deviceid = dev->id; + break; + default: + ErrorF("[mi] Unknown event type (%d), cannot change id.\n", + event->any.type); + } +} + +static void +FixUpEventForMaster(DeviceIntPtr mdev, DeviceIntPtr sdev, + InternalEvent* original, InternalEvent *master) +{ + CHECKEVENT(original); + CHECKEVENT(master); + /* Ensure chained button mappings, i.e. that the detail field is the + * value of the mapped button on the SD, not the physical button */ + if (original->any.type == ET_ButtonPress || + original->any.type == ET_ButtonRelease) + { + int btn = original->device_event.detail.button; + if (!sdev->button) + return; /* Should never happen */ + + master->device_event.detail.button = sdev->button->map[btn]; + } +} + +/** + * Copy the given event into master. + * @param sdev The slave device the original event comes from + * @param original The event as it came from the EQ + * @param copy The event after being copied + * @return The master device or NULL if the device is a floating slave. + */ +DeviceIntPtr +CopyGetMasterEvent(DeviceIntPtr sdev, + InternalEvent* original, InternalEvent *copy) +{ + DeviceIntPtr mdev; + int len = original->any.length; + int type = original->any.type; + int mtype; /* which master type? */ + + CHECKEVENT(original); + + /* ET_XQuartz has sdev == NULL */ + if (!sdev || IsMaster(sdev) || IsFloating(sdev)) + return NULL; + +#if XFreeXDGA + if (type == ET_DGAEvent) + type = original->dga_event.subtype; +#endif + + switch(type) + { + case ET_KeyPress: + case ET_KeyRelease: + mtype = MASTER_KEYBOARD; + break; + case ET_ButtonPress: + case ET_ButtonRelease: + case ET_Motion: + case ET_ProximityIn: + case ET_ProximityOut: + mtype = MASTER_POINTER; + break; + default: + mtype = MASTER_ATTACHED; + break; + } + + mdev = GetMaster(sdev, mtype); + memcpy(copy, original, len); + ChangeDeviceID(mdev, copy); + FixUpEventForMaster(mdev, sdev, original, copy); + + return mdev; +} + + +/** + * Post the given @event through the device hierarchy, as appropriate. + * Use this function if an event must be posted for a given device during the + * usual event processing cycle. + */ +void +mieqProcessDeviceEvent(DeviceIntPtr dev, + InternalEvent *event, + ScreenPtr screen) +{ + mieqHandler handler; + int x = 0, y = 0; + DeviceIntPtr master; + InternalEvent mevent; /* master event */ + + CHECKEVENT(event); + + /* Custom event handler */ + handler = miEventQueue.handlers[event->any.type]; + + switch (event->any.type) { + /* Catch events that include valuator information and check if they + * are changing the screen */ + case ET_Motion: + case ET_KeyPress: + case ET_KeyRelease: + case ET_ButtonPress: + case ET_ButtonRelease: + if (dev && screen && screen != DequeueScreen(dev) && !handler) { + DequeueScreen(dev) = screen; + x = event->device_event.root_x; + y = event->device_event.root_y; + NewCurrentScreen (dev, DequeueScreen(dev), x, y); + } + break; + default: + break; + } + master = CopyGetMasterEvent(dev, event, &mevent); + + if (master) + master->lastSlave = dev; + + /* If someone's registered a custom event handler, let them + * steal it. */ + if (handler) + { + int screenNum = dev && DequeueScreen(dev) ? DequeueScreen(dev)->myNum : (screen ? screen->myNum : 0); + handler(screenNum, event, dev); + /* Check for the SD's master in case the device got detached + * during event processing */ + if (master && !IsFloating(dev)) + handler(screenNum, &mevent, master); + } else + { + /* process slave first, then master */ + dev->public.processInputProc(event, dev); + + /* Check for the SD's master in case the device got detached + * during event processing */ + if (master && !IsFloating(dev)) + master->public.processInputProc(&mevent, master); + } +} + +/* Call this from ProcessInputEvents(). */ +void +mieqProcessInputEvents(void) +{ + EventRec *e = NULL; + int evlen; + ScreenPtr screen; + static InternalEvent *event = NULL; + static size_t event_size = 0; + DeviceIntPtr dev = NULL, + master = NULL; + +#ifdef XQUARTZ + pthread_mutex_lock(&miEventQueueMutex); +#endif + + while (miEventQueue.head != miEventQueue.tail) { + e = &miEventQueue.events[miEventQueue.head]; + + evlen = e->events->evlen; + if(evlen > event_size) + { + event = realloc(event, evlen); + event_size = evlen; + } + + + if (!event) + FatalError("[mi] No memory left for event processing.\n"); + + memcpy(event, e->events->event, evlen); + + + dev = e->pDev; + screen = e->pScreen; + + miEventQueue.head = (miEventQueue.head + 1) % QUEUE_SIZE; + +#ifdef XQUARTZ + pthread_mutex_unlock(&miEventQueueMutex); +#endif + + master = (dev) ? GetMaster(dev, MASTER_ATTACHED) : NULL; + + if (screenIsSaved == SCREEN_SAVER_ON) + dixSaveScreens (serverClient, SCREEN_SAVER_OFF, ScreenSaverReset); +#ifdef DPMSExtension + else if (DPMSPowerLevel != DPMSModeOn) + SetScreenSaverTimer(); + + if (DPMSPowerLevel != DPMSModeOn) + DPMSSet(serverClient, DPMSModeOn); +#endif + + mieqProcessDeviceEvent(dev, event, screen); + + /* Update the sprite now. Next event may be from different device. */ + if (event->any.type == ET_Motion && master) + miPointerUpdateSprite(dev); + +#ifdef XQUARTZ + pthread_mutex_lock(&miEventQueueMutex); +#endif + } +#ifdef XQUARTZ + pthread_mutex_unlock(&miEventQueueMutex); +#endif +} + diff --git a/xorg-server/mi/mipointer.c b/xorg-server/mi/mipointer.c index f9ca9a70b..209ea06be 100644 --- a/xorg-server/mi/mipointer.c +++ b/xorg-server/mi/mipointer.c @@ -1,590 +1,688 @@ -/*
-
-Copyright 1989, 1998 The Open Group
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation.
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
-AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of The Open Group shall not be
-used in advertising or otherwise to promote the sale, use or other dealings
-in this Software without prior written authorization from The Open Group.
-*/
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-# include <X11/X.h>
-# include <X11/Xmd.h>
-# include <X11/Xproto.h>
-# include "misc.h"
-# include "windowstr.h"
-# include "pixmapstr.h"
-# include "mi.h"
-# include "scrnintstr.h"
-# include "mipointrst.h"
-# include "cursorstr.h"
-# include "dixstruct.h"
-# include "inputstr.h"
-# include "inpututils.h"
-
-DevPrivateKeyRec miPointerScreenKeyRec;
-
-#define GetScreenPrivate(s) ((miPointerScreenPtr) \
- dixLookupPrivate(&(s)->devPrivates, miPointerScreenKey))
-#define SetupScreen(s) miPointerScreenPtr pScreenPriv = GetScreenPrivate(s)
-
-DevPrivateKeyRec miPointerPrivKeyRec;
-
-#define MIPOINTER(dev) \
- ((!IsMaster(dev) && !dev->u.master) ? \
- (miPointerPtr)dixLookupPrivate(&(dev)->devPrivates, miPointerPrivKey): \
- (miPointerPtr)dixLookupPrivate(&(GetMaster(dev, MASTER_POINTER))->devPrivates, miPointerPrivKey))
-
-static Bool miPointerRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
- CursorPtr pCursor);
-static Bool miPointerUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
- CursorPtr pCursor);
-static Bool miPointerDisplayCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
- CursorPtr pCursor);
-static void miPointerConstrainCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
- BoxPtr pBox);
-static void miPointerCursorLimits(DeviceIntPtr pDev, ScreenPtr pScreen,
- CursorPtr pCursor, BoxPtr pHotBox,
- BoxPtr pTopLeftBox);
-static Bool miPointerSetCursorPosition(DeviceIntPtr pDev, ScreenPtr pScreen,
- int x, int y,
- Bool generateEvent);
-static Bool miPointerCloseScreen(int index, ScreenPtr pScreen);
-static void miPointerMove(DeviceIntPtr pDev, ScreenPtr pScreen,
- int x, int y);
-static Bool miPointerDeviceInitialize(DeviceIntPtr pDev, ScreenPtr pScreen);
-static void miPointerDeviceCleanup(DeviceIntPtr pDev,
- ScreenPtr pScreen);
-static void miPointerMoveNoEvent (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y);
-
-static EventList* events; /* for WarpPointer MotionNotifies */
-
-Bool
-miPointerInitialize (ScreenPtr pScreen,
- miPointerSpriteFuncPtr spriteFuncs,
- miPointerScreenFuncPtr screenFuncs,
- Bool waitForUpdate)
-{
- miPointerScreenPtr pScreenPriv;
-
- if (!dixRegisterPrivateKey(&miPointerScreenKeyRec, PRIVATE_SCREEN, 0))
- return FALSE;
-
- if (!dixRegisterPrivateKey(&miPointerPrivKeyRec, PRIVATE_DEVICE, 0))
- return FALSE;
-
- pScreenPriv = malloc(sizeof (miPointerScreenRec));
- if (!pScreenPriv)
- return FALSE;
- pScreenPriv->spriteFuncs = spriteFuncs;
- pScreenPriv->screenFuncs = screenFuncs;
- /*
- * check for uninitialized methods
- */
- if (!screenFuncs->EnqueueEvent)
- screenFuncs->EnqueueEvent = mieqEnqueue;
- if (!screenFuncs->NewEventScreen)
- screenFuncs->NewEventScreen = mieqSwitchScreen;
- pScreenPriv->waitForUpdate = waitForUpdate;
- pScreenPriv->showTransparent = FALSE;
- pScreenPriv->CloseScreen = pScreen->CloseScreen;
- pScreen->CloseScreen = miPointerCloseScreen;
- dixSetPrivate(&pScreen->devPrivates, miPointerScreenKey, pScreenPriv);
- /*
- * set up screen cursor method table
- */
- pScreen->ConstrainCursor = miPointerConstrainCursor;
- pScreen->CursorLimits = miPointerCursorLimits;
- pScreen->DisplayCursor = miPointerDisplayCursor;
- pScreen->RealizeCursor = miPointerRealizeCursor;
- pScreen->UnrealizeCursor = miPointerUnrealizeCursor;
- pScreen->SetCursorPosition = miPointerSetCursorPosition;
- pScreen->RecolorCursor = miRecolorCursor;
- pScreen->DeviceCursorInitialize = miPointerDeviceInitialize;
- pScreen->DeviceCursorCleanup = miPointerDeviceCleanup;
-
- events = NULL;
- return TRUE;
-}
-
-static Bool
-miPointerCloseScreen (int index, ScreenPtr pScreen)
-{
-#if 0
- miPointerPtr pPointer;
- DeviceIntPtr pDev;
-#endif
-
- SetupScreen(pScreen);
-
-#if 0
- for (pDev = inputInfo.devices; pDev; pDev = pDev->next)
- {
- if (DevHasCursor(pDev))
- {
- pPointer = MIPOINTER(pDev);
-
- if (pScreen == pPointer->pScreen)
- pPointer->pScreen = 0;
- if (pScreen == pPointer->pSpriteScreen)
- pPointer->pSpriteScreen = 0;
- }
- }
-
- if (MIPOINTER(inputInfo.pointer)->pScreen == pScreen)
- MIPOINTER(inputInfo.pointer)->pScreen = 0;
- if (MIPOINTER(inputInfo.pointer)->pSpriteScreen == pScreen)
- MIPOINTER(inputInfo.pointer)->pSpriteScreen = 0;
-#endif
-
- pScreen->CloseScreen = pScreenPriv->CloseScreen;
- free((pointer) pScreenPriv);
- FreeEventList(events, GetMaximumEventsNum());
- events = NULL;
- return (*pScreen->CloseScreen) (index, pScreen);
-}
-
-/*
- * DIX/DDX interface routines
- */
-
-static Bool
-miPointerRealizeCursor (DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor)
-{
- SetupScreen(pScreen);
- return (*pScreenPriv->spriteFuncs->RealizeCursor) (pDev, pScreen, pCursor);
-}
-
-static Bool
-miPointerUnrealizeCursor (DeviceIntPtr pDev,
- ScreenPtr pScreen,
- CursorPtr pCursor)
-{
- SetupScreen(pScreen);
- return (*pScreenPriv->spriteFuncs->UnrealizeCursor) (pDev, pScreen, pCursor);
-}
-
-static Bool
-miPointerDisplayCursor (DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor)
-{
- miPointerPtr pPointer;
-
- /* return for keyboards */
- if ((IsMaster(pDev) && !DevHasCursor(pDev)) ||
- (!IsMaster(pDev) && pDev->u.master && !DevHasCursor(pDev->u.master)))
- return FALSE;
-
- pPointer = MIPOINTER(pDev);
-
- pPointer->pCursor = pCursor;
- pPointer->pScreen = pScreen;
- miPointerUpdateSprite(pDev);
- return TRUE;
-}
-
-static void
-miPointerConstrainCursor (DeviceIntPtr pDev, ScreenPtr pScreen, BoxPtr pBox)
-{
- miPointerPtr pPointer;
-
- pPointer = MIPOINTER(pDev);
-
- pPointer->limits = *pBox;
- pPointer->confined = PointerConfinedToScreen(pDev);
-}
-
-/*ARGSUSED*/
-static void
-miPointerCursorLimits(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor,
- BoxPtr pHotBox, BoxPtr pTopLeftBox)
-{
- *pTopLeftBox = *pHotBox;
-}
-
-static Bool GenerateEvent;
-
-static Bool
-miPointerSetCursorPosition(DeviceIntPtr pDev, ScreenPtr pScreen,
- int x, int y, Bool generateEvent)
-{
- SetupScreen (pScreen);
-
- GenerateEvent = generateEvent;
- /* device dependent - must pend signal and call miPointerWarpCursor */
- (*pScreenPriv->screenFuncs->WarpCursor) (pDev, pScreen, x, y);
- if (!generateEvent)
- miPointerUpdateSprite(pDev);
- return TRUE;
-}
-
-/* Set up sprite information for the device.
- This function will be called once for each device after it is initialized
- in the DIX.
- */
-static Bool
-miPointerDeviceInitialize(DeviceIntPtr pDev, ScreenPtr pScreen)
-{
- miPointerPtr pPointer;
- SetupScreen (pScreen);
-
- pPointer = malloc(sizeof(miPointerRec));
- if (!pPointer)
- return FALSE;
-
- pPointer->pScreen = NULL;
- pPointer->pSpriteScreen = NULL;
- pPointer->pCursor = NULL;
- pPointer->pSpriteCursor = NULL;
- pPointer->limits.x1 = 0;
- pPointer->limits.x2 = 32767;
- pPointer->limits.y1 = 0;
- pPointer->limits.y2 = 32767;
- pPointer->confined = FALSE;
- pPointer->x = 0;
- pPointer->y = 0;
-
- if (!((*pScreenPriv->spriteFuncs->DeviceCursorInitialize)(pDev, pScreen)))
- {
- free(pPointer);
- return FALSE;
- }
-
- dixSetPrivate(&pDev->devPrivates, miPointerPrivKey, pPointer);
- return TRUE;
-}
-
-/* Clean up after device.
- This function will be called once before the device is freed in the DIX
- */
-static void
-miPointerDeviceCleanup(DeviceIntPtr pDev, ScreenPtr pScreen)
-{
- SetupScreen(pScreen);
-
- if (!IsMaster(pDev) && pDev->u.master)
- return;
-
- (*pScreenPriv->spriteFuncs->DeviceCursorCleanup)(pDev, pScreen);
- free(dixLookupPrivate(&pDev->devPrivates, miPointerPrivKey));
- dixSetPrivate(&pDev->devPrivates, miPointerPrivKey, NULL);
-}
-
-
-/* Once signals are ignored, the WarpCursor function can call this */
-
-void
-miPointerWarpCursor (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)
-{
- miPointerPtr pPointer;
- BOOL changedScreen = FALSE;
-
- SetupScreen (pScreen);
- pPointer = MIPOINTER(pDev);
-
- if (pPointer->pScreen != pScreen)
- {
- (*pScreenPriv->screenFuncs->NewEventScreen) (pDev, pScreen, TRUE);
- changedScreen = TRUE;
- }
-
- if (GenerateEvent)
- miPointerMove (pDev, pScreen, x, y);
- else
- miPointerMoveNoEvent(pDev, pScreen, x, y);
-
- /* Don't call USFS if we use Xinerama, otherwise the root window is
- * updated to the second screen, and we never receive any events.
- * (FDO bug #18668) */
- if (changedScreen
-#ifdef PANORAMIX
- && noPanoramiXExtension
-#endif
- )
- UpdateSpriteForScreen (pDev, pScreen) ;
-}
-
-/*
- * Pointer/CursorDisplay interface routines
- */
-
-/*
- * miPointerUpdateSprite
- *
- * Syncronize the sprite with the cursor - called from ProcessInputEvents
- */
-
-void
-miPointerUpdateSprite (DeviceIntPtr pDev)
-{
- ScreenPtr pScreen;
- miPointerScreenPtr pScreenPriv;
- CursorPtr pCursor;
- int x, y, devx, devy;
- miPointerPtr pPointer;
-
- if (!pDev || !pDev->coreEvents)
- return;
-
- pPointer = MIPOINTER(pDev);
-
- if (!pPointer)
- return;
-
- pScreen = pPointer->pScreen;
- if (!pScreen)
- return;
-
- x = pPointer->x;
- y = pPointer->y;
- devx = pPointer->devx;
- devy = pPointer->devy;
-
- pScreenPriv = GetScreenPrivate (pScreen);
- /*
- * if the cursor has switched screens, disable the sprite
- * on the old screen
- */
- if (pScreen != pPointer->pSpriteScreen)
- {
- if (pPointer->pSpriteScreen)
- {
- miPointerScreenPtr pOldPriv;
-
- pOldPriv = GetScreenPrivate (pPointer->pSpriteScreen);
- if (pPointer->pCursor)
- {
- (*pOldPriv->spriteFuncs->SetCursor)
- (pDev, pPointer->pSpriteScreen, NullCursor, 0, 0);
- }
- (*pOldPriv->screenFuncs->CrossScreen) (pPointer->pSpriteScreen, FALSE);
- }
- (*pScreenPriv->screenFuncs->CrossScreen) (pScreen, TRUE);
- (*pScreenPriv->spriteFuncs->SetCursor)
- (pDev, pScreen, pPointer->pCursor, x, y);
- pPointer->devx = x;
- pPointer->devy = y;
- pPointer->pSpriteCursor = pPointer->pCursor;
- pPointer->pSpriteScreen = pScreen;
- }
- /*
- * if the cursor has changed, display the new one
- */
- else if (pPointer->pCursor != pPointer->pSpriteCursor)
- {
- pCursor = pPointer->pCursor;
- if (!pCursor || (pCursor->bits->emptyMask && !pScreenPriv->showTransparent))
- pCursor = NullCursor;
- (*pScreenPriv->spriteFuncs->SetCursor) (pDev, pScreen, pCursor, x, y);
-
- pPointer->devx = x;
- pPointer->devy = y;
- pPointer->pSpriteCursor = pPointer->pCursor;
- }
- else if (x != devx || y != devy)
- {
- pPointer->devx = x;
- pPointer->devy = y;
- if(pPointer->pCursor && !pPointer->pCursor->bits->emptyMask)
- (*pScreenPriv->spriteFuncs->MoveCursor) (pDev, pScreen, x, y);
- }
-}
-
-void
-miPointerSetScreen(DeviceIntPtr pDev, int screen_no, int x, int y)
-{
- miPointerScreenPtr pScreenPriv;
- ScreenPtr pScreen;
- miPointerPtr pPointer;
-
- pPointer = MIPOINTER(pDev);
-
- pScreen = screenInfo.screens[screen_no];
- pScreenPriv = GetScreenPrivate (pScreen);
- (*pScreenPriv->screenFuncs->NewEventScreen) (pDev, pScreen, FALSE);
- NewCurrentScreen (pDev, pScreen, x, y);
-
- pPointer->limits.x2 = pScreen->width;
- pPointer->limits.y2 = pScreen->height;
-}
-
-ScreenPtr
-miPointerCurrentScreen (void)
-{
- return miPointerGetScreen(inputInfo.pointer);
-}
-
-ScreenPtr
-miPointerGetScreen(DeviceIntPtr pDev)
-{
- miPointerPtr pPointer = MIPOINTER(pDev);
- return (pPointer) ? pPointer->pScreen : NULL;
-}
-
-/* Controls whether the cursor image should be updated immediately when
- moved (FALSE) or if something else will be responsible for updating
- it later (TRUE). Returns current setting.
- Caller is responsible for calling OsBlockSignal first.
-*/
-Bool
-miPointerSetWaitForUpdate(ScreenPtr pScreen, Bool wait)
-{
- SetupScreen(pScreen);
- Bool prevWait = pScreenPriv->waitForUpdate;
-
- pScreenPriv->waitForUpdate = wait;
- return prevWait;
-}
-
-
-/* Move the pointer on the current screen, and update the sprite. */
-static void
-miPointerMoveNoEvent (DeviceIntPtr pDev, ScreenPtr pScreen,
- int x, int y)
-{
- miPointerPtr pPointer;
- SetupScreen(pScreen);
-
- pPointer = MIPOINTER(pDev);
-
- /* Hack: We mustn't call into ->MoveCursor for anything but the
- * VCP, as this may cause a non-HW rendered cursor to be rendered during
- * SIGIO. This again leads to allocs during SIGIO which leads to SIGABRT.
- */
- if ((pDev == inputInfo.pointer || (!IsMaster(pDev) && pDev->u.master == inputInfo.pointer))
- && !pScreenPriv->waitForUpdate && pScreen == pPointer->pSpriteScreen)
- {
- pPointer->devx = x;
- pPointer->devy = y;
- if(pPointer->pCursor && !pPointer->pCursor->bits->emptyMask)
- (*pScreenPriv->spriteFuncs->MoveCursor) (pDev, pScreen, x, y);
- }
-
- pPointer->x = x;
- pPointer->y = y;
- pPointer->pScreen = pScreen;
-}
-
-void
-miPointerSetPosition(DeviceIntPtr pDev, int *x, int *y)
-{
- miPointerScreenPtr pScreenPriv;
- ScreenPtr pScreen;
- ScreenPtr newScreen;
-
- miPointerPtr pPointer;
-
- if (!pDev || !pDev->coreEvents)
- return;
-
- pPointer = MIPOINTER(pDev);
- pScreen = pPointer->pScreen;
- if (!pScreen)
- return; /* called before ready */
-
- if (*x < 0 || *x >= pScreen->width || *y < 0 || *y >= pScreen->height)
- {
- pScreenPriv = GetScreenPrivate (pScreen);
- if (!pPointer->confined)
- {
- newScreen = pScreen;
- (*pScreenPriv->screenFuncs->CursorOffScreen) (&newScreen, x, y);
- if (newScreen != pScreen)
- {
- pScreen = newScreen;
- (*pScreenPriv->screenFuncs->NewEventScreen) (pDev, pScreen,
- FALSE);
- pScreenPriv = GetScreenPrivate (pScreen);
- /* Smash the confine to the new screen */
- pPointer->limits.x2 = pScreen->width;
- pPointer->limits.y2 = pScreen->height;
- }
- }
- }
- /* Constrain the sprite to the current limits. */
- if (*x < pPointer->limits.x1)
- *x = pPointer->limits.x1;
- if (*x >= pPointer->limits.x2)
- *x = pPointer->limits.x2 - 1;
- if (*y < pPointer->limits.y1)
- *y = pPointer->limits.y1;
- if (*y >= pPointer->limits.y2)
- *y = pPointer->limits.y2 - 1;
-
- if (pPointer->x == *x && pPointer->y == *y &&
- pPointer->pScreen == pScreen)
- return;
-
- miPointerMoveNoEvent(pDev, pScreen, *x, *y);
-}
-
-void
-miPointerGetPosition(DeviceIntPtr pDev, int *x, int *y)
-{
- *x = MIPOINTER(pDev)->x;
- *y = MIPOINTER(pDev)->y;
-}
-
-#ifdef XQUARTZ
-#include <pthread.h>
-void darwinEvents_lock(void);
-void darwinEvents_unlock(void);
-#endif
-
-void
-miPointerMove (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)
-{
- int i, nevents;
- int valuators[2];
- ValuatorMask mask;
-
- miPointerMoveNoEvent(pDev, pScreen, x, y);
-
- /* generate motion notify */
- valuators[0] = x;
- valuators[1] = y;
-
- if (!events)
- {
- events = InitEventList(GetMaximumEventsNum());
-
- if (!events)
- {
- FatalError("Could not allocate event store.\n");
- return;
- }
- }
-
- valuator_mask_set_range(&mask, 0, 2, valuators);
- nevents = GetPointerEvents(events, pDev, MotionNotify, 0,
- POINTER_SCREEN | POINTER_ABSOLUTE, &mask);
-
- OsBlockSignals();
-#ifdef XQUARTZ
- darwinEvents_lock();
-#endif
- for (i = 0; i < nevents; i++)
- mieqEnqueue(pDev, (InternalEvent*)events[i].event);
-#ifdef XQUARTZ
- darwinEvents_unlock();
-#endif
- OsReleaseSignals();
-}
+/* + +Copyright 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. +*/ + +/** + * @file + * This file contains functions to move the pointer on the screen and/or + * restrict its movement. These functions are divided into two sets: + * Screen-specific functions that are used as function pointers from other + * parts of the server (and end up heavily wrapped by e.g. animcur and + * xfixes): + * miPointerConstrainCursor + * miPointerCursorLimits + * miPointerDisplayCursor + * miPointerRealizeCursor + * miPointerUnrealizeCursor + * miPointerSetCursorPosition + * miRecolorCursor + * miPointerDeviceInitialize + * miPointerDeviceCleanup + * If wrapped, these are the last element in the wrapping chain. They may + * call into sprite-specific code through further function pointers though. + * + * The second type of functions are those that are directly called by the + * DIX, DDX and some drivers. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +# include <X11/X.h> +# include <X11/Xmd.h> +# include <X11/Xproto.h> +# include "misc.h" +# include "windowstr.h" +# include "pixmapstr.h" +# include "mi.h" +# include "scrnintstr.h" +# include "mipointrst.h" +# include "cursorstr.h" +# include "dixstruct.h" +# include "inputstr.h" +# include "inpututils.h" + +DevPrivateKeyRec miPointerScreenKeyRec; + +#define GetScreenPrivate(s) ((miPointerScreenPtr) \ + dixLookupPrivate(&(s)->devPrivates, miPointerScreenKey)) +#define SetupScreen(s) miPointerScreenPtr pScreenPriv = GetScreenPrivate(s) + +DevPrivateKeyRec miPointerPrivKeyRec; + +#define MIPOINTER(dev) \ + (IsFloating(dev) ? \ + (miPointerPtr)dixLookupPrivate(&(dev)->devPrivates, miPointerPrivKey): \ + (miPointerPtr)dixLookupPrivate(&(GetMaster(dev, MASTER_POINTER))->devPrivates, miPointerPrivKey)) + +static Bool miPointerRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, + CursorPtr pCursor); +static Bool miPointerUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, + CursorPtr pCursor); +static Bool miPointerDisplayCursor(DeviceIntPtr pDev, ScreenPtr pScreen, + CursorPtr pCursor); +static void miPointerConstrainCursor(DeviceIntPtr pDev, ScreenPtr pScreen, + BoxPtr pBox); +static void miPointerCursorLimits(DeviceIntPtr pDev, ScreenPtr pScreen, + CursorPtr pCursor, BoxPtr pHotBox, + BoxPtr pTopLeftBox); +static Bool miPointerSetCursorPosition(DeviceIntPtr pDev, ScreenPtr pScreen, + int x, int y, + Bool generateEvent); +static Bool miPointerCloseScreen(int index, ScreenPtr pScreen); +static void miPointerMove(DeviceIntPtr pDev, ScreenPtr pScreen, + int x, int y); +static Bool miPointerDeviceInitialize(DeviceIntPtr pDev, ScreenPtr pScreen); +static void miPointerDeviceCleanup(DeviceIntPtr pDev, + ScreenPtr pScreen); +static void miPointerMoveNoEvent (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y); + +static EventList* events; /* for WarpPointer MotionNotifies */ + +Bool +miPointerInitialize (ScreenPtr pScreen, + miPointerSpriteFuncPtr spriteFuncs, + miPointerScreenFuncPtr screenFuncs, + Bool waitForUpdate) +{ + miPointerScreenPtr pScreenPriv; + + if (!dixRegisterPrivateKey(&miPointerScreenKeyRec, PRIVATE_SCREEN, 0)) + return FALSE; + + if (!dixRegisterPrivateKey(&miPointerPrivKeyRec, PRIVATE_DEVICE, 0)) + return FALSE; + + pScreenPriv = malloc(sizeof (miPointerScreenRec)); + if (!pScreenPriv) + return FALSE; + pScreenPriv->spriteFuncs = spriteFuncs; + pScreenPriv->screenFuncs = screenFuncs; + /* + * check for uninitialized methods + */ + if (!screenFuncs->EnqueueEvent) + screenFuncs->EnqueueEvent = mieqEnqueue; + if (!screenFuncs->NewEventScreen) + screenFuncs->NewEventScreen = mieqSwitchScreen; + pScreenPriv->waitForUpdate = waitForUpdate; + pScreenPriv->showTransparent = FALSE; + pScreenPriv->CloseScreen = pScreen->CloseScreen; + pScreen->CloseScreen = miPointerCloseScreen; + dixSetPrivate(&pScreen->devPrivates, miPointerScreenKey, pScreenPriv); + /* + * set up screen cursor method table + */ + pScreen->ConstrainCursor = miPointerConstrainCursor; + pScreen->CursorLimits = miPointerCursorLimits; + pScreen->DisplayCursor = miPointerDisplayCursor; + pScreen->RealizeCursor = miPointerRealizeCursor; + pScreen->UnrealizeCursor = miPointerUnrealizeCursor; + pScreen->SetCursorPosition = miPointerSetCursorPosition; + pScreen->RecolorCursor = miRecolorCursor; + pScreen->DeviceCursorInitialize = miPointerDeviceInitialize; + pScreen->DeviceCursorCleanup = miPointerDeviceCleanup; + + events = NULL; + return TRUE; +} + +/** + * Destroy screen-specific information. + * + * @param index Screen index of the screen in screenInfo.screens[] + * @param pScreen The actual screen pointer + */ +static Bool +miPointerCloseScreen (int index, ScreenPtr pScreen) +{ + SetupScreen(pScreen); + + pScreen->CloseScreen = pScreenPriv->CloseScreen; + free((pointer) pScreenPriv); + FreeEventList(events, GetMaximumEventsNum()); + events = NULL; + return (*pScreen->CloseScreen) (index, pScreen); +} + +/* + * DIX/DDX interface routines + */ + +static Bool +miPointerRealizeCursor (DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor) +{ + SetupScreen(pScreen); + return (*pScreenPriv->spriteFuncs->RealizeCursor) (pDev, pScreen, pCursor); +} + +static Bool +miPointerUnrealizeCursor (DeviceIntPtr pDev, + ScreenPtr pScreen, + CursorPtr pCursor) +{ + SetupScreen(pScreen); + return (*pScreenPriv->spriteFuncs->UnrealizeCursor) (pDev, pScreen, pCursor); +} + +static Bool +miPointerDisplayCursor (DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor) +{ + miPointerPtr pPointer; + + /* return for keyboards */ + if (!IsPointerDevice(pDev)) + return FALSE; + + pPointer = MIPOINTER(pDev); + + pPointer->pCursor = pCursor; + pPointer->pScreen = pScreen; + miPointerUpdateSprite(pDev); + return TRUE; +} + +/** + * Set up the constraints for the given device. This function does not + * actually constrain the cursor but merely copies the given box to the + * internal constraint storage. + * + * @param pDev The device to constrain to the box + * @param pBox The rectangle to constrain the cursor to + * @param pScreen Used for copying screen confinement + */ +static void +miPointerConstrainCursor (DeviceIntPtr pDev, ScreenPtr pScreen, BoxPtr pBox) +{ + miPointerPtr pPointer; + + pPointer = MIPOINTER(pDev); + + pPointer->limits = *pBox; + pPointer->confined = PointerConfinedToScreen(pDev); +} + +/** + * Should calculate the box for the given cursor, based on screen and the + * confinement given. But we assume that whatever box is passed in is valid + * anyway. + * + * @param pDev The device to calculate the cursor limits for + * @param pScreen The screen the confinement happens on + * @param pCursor The screen the confinement happens on + * @param pHotBox The confinement box for the cursor + * @param[out] pTopLeftBox The new confinement box, always *pHotBox. + */ +static void +miPointerCursorLimits(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor, + BoxPtr pHotBox, BoxPtr pTopLeftBox) +{ + *pTopLeftBox = *pHotBox; +} + +/** + * Set the device's cursor position to the x/y position on the given screen. + * Generates and event if required. + * + * This function is called from: + * - sprite init code to place onto initial position + * - the various WarpPointer implementations (core, XI, Xinerama, dmx,…) + * - during the cursor update path in CheckMotion + * - in the Xinerama part of NewCurrentScreen + * - when a RandR/RandR1.2 mode was applied (it may have moved the pointer, so + * it's set back to the original pos) + * + * @param pDev The device to move + * @param pScreen The screen the device is on + * @param x The x coordinate in per-screen coordinates + * @param y The y coordinate in per-screen coordinates + * @param generateEvent True if the pointer movement should generate an + * event. + * + * @return TRUE in all cases + */ +static Bool +miPointerSetCursorPosition(DeviceIntPtr pDev, ScreenPtr pScreen, + int x, int y, Bool generateEvent) +{ + SetupScreen (pScreen); + miPointerPtr pPointer = MIPOINTER(pDev); + + pPointer->generateEvent = generateEvent; + + /* device dependent - must pend signal and call miPointerWarpCursor */ + (*pScreenPriv->screenFuncs->WarpCursor) (pDev, pScreen, x, y); + if (!generateEvent) + miPointerUpdateSprite(pDev); + return TRUE; +} + +/** + * Set up sprite information for the device. + * This function will be called once for each device after it is initialized + * in the DIX. + * + * @param pDev The newly created device + * @param pScreen The initial sprite scree. + */ +static Bool +miPointerDeviceInitialize(DeviceIntPtr pDev, ScreenPtr pScreen) +{ + miPointerPtr pPointer; + SetupScreen (pScreen); + + pPointer = malloc(sizeof(miPointerRec)); + if (!pPointer) + return FALSE; + + pPointer->pScreen = NULL; + pPointer->pSpriteScreen = NULL; + pPointer->pCursor = NULL; + pPointer->pSpriteCursor = NULL; + pPointer->limits.x1 = 0; + pPointer->limits.x2 = 32767; + pPointer->limits.y1 = 0; + pPointer->limits.y2 = 32767; + pPointer->confined = FALSE; + pPointer->x = 0; + pPointer->y = 0; + pPointer->generateEvent = FALSE; + + if (!((*pScreenPriv->spriteFuncs->DeviceCursorInitialize)(pDev, pScreen))) + { + free(pPointer); + return FALSE; + } + + dixSetPrivate(&pDev->devPrivates, miPointerPrivKey, pPointer); + return TRUE; +} + +/** + * Clean up after device. + * This function will be called once before the device is freed in the DIX + * + * @param pDev The device to be removed from the server + * @param pScreen Current screen of the device + */ +static void +miPointerDeviceCleanup(DeviceIntPtr pDev, ScreenPtr pScreen) +{ + SetupScreen(pScreen); + + if (!IsMaster(pDev) && !IsFloating(pDev)) + return; + + (*pScreenPriv->spriteFuncs->DeviceCursorCleanup)(pDev, pScreen); + free(dixLookupPrivate(&pDev->devPrivates, miPointerPrivKey)); + dixSetPrivate(&pDev->devPrivates, miPointerPrivKey, NULL); +} + + +/** + * Warp the pointer to the given position on the given screen. May generate + * an event, depending on whether we're coming from miPointerSetPosition. + * + * Once signals are ignored, the WarpCursor function can call this + * + * @param pDev The device to warp + * @param pScreen Screen to warp on + * @param x The x coordinate in per-screen coordinates + * @param y The y coordinate in per-screen coordinates + */ + +void +miPointerWarpCursor (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y) +{ + miPointerPtr pPointer; + BOOL changedScreen = FALSE; + + SetupScreen (pScreen); + pPointer = MIPOINTER(pDev); + + if (pPointer->pScreen != pScreen) + { + (*pScreenPriv->screenFuncs->NewEventScreen) (pDev, pScreen, TRUE); + changedScreen = TRUE; + } + + if (pPointer->generateEvent) + miPointerMove (pDev, pScreen, x, y); + else + miPointerMoveNoEvent(pDev, pScreen, x, y); + + /* Don't call USFS if we use Xinerama, otherwise the root window is + * updated to the second screen, and we never receive any events. + * (FDO bug #18668) */ + if (changedScreen +#ifdef PANORAMIX + && noPanoramiXExtension +#endif + ) + UpdateSpriteForScreen (pDev, pScreen) ; +} + +/** + * Syncronize the sprite with the cursor. + * + * @param pDev The device to sync + */ +void +miPointerUpdateSprite (DeviceIntPtr pDev) +{ + ScreenPtr pScreen; + miPointerScreenPtr pScreenPriv; + CursorPtr pCursor; + int x, y, devx, devy; + miPointerPtr pPointer; + + if (!pDev || !pDev->coreEvents) + return; + + pPointer = MIPOINTER(pDev); + + if (!pPointer) + return; + + pScreen = pPointer->pScreen; + if (!pScreen) + return; + + x = pPointer->x; + y = pPointer->y; + devx = pPointer->devx; + devy = pPointer->devy; + + pScreenPriv = GetScreenPrivate (pScreen); + /* + * if the cursor has switched screens, disable the sprite + * on the old screen + */ + if (pScreen != pPointer->pSpriteScreen) + { + if (pPointer->pSpriteScreen) + { + miPointerScreenPtr pOldPriv; + + pOldPriv = GetScreenPrivate (pPointer->pSpriteScreen); + if (pPointer->pCursor) + { + (*pOldPriv->spriteFuncs->SetCursor) + (pDev, pPointer->pSpriteScreen, NullCursor, 0, 0); + } + (*pOldPriv->screenFuncs->CrossScreen) (pPointer->pSpriteScreen, FALSE); + } + (*pScreenPriv->screenFuncs->CrossScreen) (pScreen, TRUE); + (*pScreenPriv->spriteFuncs->SetCursor) + (pDev, pScreen, pPointer->pCursor, x, y); + pPointer->devx = x; + pPointer->devy = y; + pPointer->pSpriteCursor = pPointer->pCursor; + pPointer->pSpriteScreen = pScreen; + } + /* + * if the cursor has changed, display the new one + */ + else if (pPointer->pCursor != pPointer->pSpriteCursor) + { + pCursor = pPointer->pCursor; + if (!pCursor || (pCursor->bits->emptyMask && !pScreenPriv->showTransparent)) + pCursor = NullCursor; + (*pScreenPriv->spriteFuncs->SetCursor) (pDev, pScreen, pCursor, x, y); + + pPointer->devx = x; + pPointer->devy = y; + pPointer->pSpriteCursor = pPointer->pCursor; + } + else if (x != devx || y != devy) + { + pPointer->devx = x; + pPointer->devy = y; + if(pPointer->pCursor && !pPointer->pCursor->bits->emptyMask) + (*pScreenPriv->spriteFuncs->MoveCursor) (pDev, pScreen, x, y); + } +} + +/** + * Set the device to the coordinates on the given screen. + * + * @param pDev The device to move + * @param screen_no Index of the screen to move to + * @param x The x coordinate in per-screen coordinates + * @param y The y coordinate in per-screen coordinates + */ +void +miPointerSetScreen(DeviceIntPtr pDev, int screen_no, int x, int y) +{ + miPointerScreenPtr pScreenPriv; + ScreenPtr pScreen; + miPointerPtr pPointer; + + pPointer = MIPOINTER(pDev); + + pScreen = screenInfo.screens[screen_no]; + pScreenPriv = GetScreenPrivate (pScreen); + (*pScreenPriv->screenFuncs->NewEventScreen) (pDev, pScreen, FALSE); + NewCurrentScreen (pDev, pScreen, x, y); + + pPointer->limits.x2 = pScreen->width; + pPointer->limits.y2 = pScreen->height; +} + +/** + * @return The current screen of the VCP + */ +ScreenPtr +miPointerCurrentScreen (void) +{ + return miPointerGetScreen(inputInfo.pointer); +} + +/** + * @return The current screen of the given device or NULL. + */ +ScreenPtr +miPointerGetScreen(DeviceIntPtr pDev) +{ + miPointerPtr pPointer = MIPOINTER(pDev); + return (pPointer) ? pPointer->pScreen : NULL; +} + +/* Controls whether the cursor image should be updated immediately when + moved (FALSE) or if something else will be responsible for updating + it later (TRUE). Returns current setting. + Caller is responsible for calling OsBlockSignal first. +*/ +Bool +miPointerSetWaitForUpdate(ScreenPtr pScreen, Bool wait) +{ + SetupScreen(pScreen); + Bool prevWait = pScreenPriv->waitForUpdate; + + pScreenPriv->waitForUpdate = wait; + return prevWait; +} + + +/* Move the pointer on the current screen, and update the sprite. */ +static void +miPointerMoveNoEvent (DeviceIntPtr pDev, ScreenPtr pScreen, + int x, int y) +{ + miPointerPtr pPointer; + SetupScreen(pScreen); + + pPointer = MIPOINTER(pDev); + + /* Hack: We mustn't call into ->MoveCursor for anything but the + * VCP, as this may cause a non-HW rendered cursor to be rendered during + * SIGIO. This again leads to allocs during SIGIO which leads to SIGABRT. + */ + if (GetMaster(pDev, MASTER_POINTER) == inputInfo.pointer + && !pScreenPriv->waitForUpdate && pScreen == pPointer->pSpriteScreen) + { + pPointer->devx = x; + pPointer->devy = y; + if(pPointer->pCursor && !pPointer->pCursor->bits->emptyMask) + (*pScreenPriv->spriteFuncs->MoveCursor) (pDev, pScreen, x, y); + } + + pPointer->x = x; + pPointer->y = y; + pPointer->pScreen = pScreen; +} + +/** + * Set the devices' cursor position to the given x/y position. + * + * This function is called during the pointer update path in + * GetPointerEvents and friends (and the same in the xwin DDX). + * + * @param pDev The device to move + * @param[in,out] x The x coordiante in screen coordinates (in regards to total + * desktop size) + * @param[in,out] y The y coordiante in screen coordinates (in regards to total + * desktop size) + */ +void +miPointerSetPosition(DeviceIntPtr pDev, int *x, int *y) +{ + miPointerScreenPtr pScreenPriv; + ScreenPtr pScreen; + ScreenPtr newScreen; + + miPointerPtr pPointer; + + if (!pDev || !pDev->coreEvents) + return; + + pPointer = MIPOINTER(pDev); + pScreen = pPointer->pScreen; + if (!pScreen) + return; /* called before ready */ + + if (*x < 0 || *x >= pScreen->width || *y < 0 || *y >= pScreen->height) + { + pScreenPriv = GetScreenPrivate (pScreen); + if (!pPointer->confined) + { + newScreen = pScreen; + (*pScreenPriv->screenFuncs->CursorOffScreen) (&newScreen, x, y); + if (newScreen != pScreen) + { + pScreen = newScreen; + (*pScreenPriv->screenFuncs->NewEventScreen) (pDev, pScreen, + FALSE); + pScreenPriv = GetScreenPrivate (pScreen); + /* Smash the confine to the new screen */ + pPointer->limits.x2 = pScreen->width; + pPointer->limits.y2 = pScreen->height; + } + } + } + /* Constrain the sprite to the current limits. */ + if (*x < pPointer->limits.x1) + *x = pPointer->limits.x1; + if (*x >= pPointer->limits.x2) + *x = pPointer->limits.x2 - 1; + if (*y < pPointer->limits.y1) + *y = pPointer->limits.y1; + if (*y >= pPointer->limits.y2) + *y = pPointer->limits.y2 - 1; + + if (pPointer->x == *x && pPointer->y == *y && + pPointer->pScreen == pScreen) + return; + + miPointerMoveNoEvent(pDev, pScreen, *x, *y); +} + +/** + * Get the current position of the device in desktop coordinates. + * + * @param x Return value for the current x coordinate in desktop coordiates. + * @param y Return value for the current y coordinate in desktop coordiates. + */ +void +miPointerGetPosition(DeviceIntPtr pDev, int *x, int *y) +{ + *x = MIPOINTER(pDev)->x; + *y = MIPOINTER(pDev)->y; +} + +#ifdef XQUARTZ +#include <pthread.h> +void darwinEvents_lock(void); +void darwinEvents_unlock(void); +#endif + +/** + * Move the device's pointer to the x/y coordinates on the given screen. + * This function generates and enqueues pointer events. + * + * @param pDev The device to move + * @param pScreen The screen the device is on + * @param x The x coordinate in per-screen coordinates + * @param y The y coordinate in per-screen coordinates + */ +void +miPointerMove (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y) +{ + int i, nevents; + int valuators[2]; + ValuatorMask mask; + + miPointerMoveNoEvent(pDev, pScreen, x, y); + + /* generate motion notify */ + valuators[0] = x; + valuators[1] = y; + + if (!events) + { + events = InitEventList(GetMaximumEventsNum()); + + if (!events) + { + FatalError("Could not allocate event store.\n"); + return; + } + } + + valuator_mask_set_range(&mask, 0, 2, valuators); + nevents = GetPointerEvents(events, pDev, MotionNotify, 0, + POINTER_SCREEN | POINTER_ABSOLUTE, &mask); + + OsBlockSignals(); +#ifdef XQUARTZ + darwinEvents_lock(); +#endif + for (i = 0; i < nevents; i++) + mieqEnqueue(pDev, (InternalEvent*)events[i].event); +#ifdef XQUARTZ + darwinEvents_unlock(); +#endif + OsReleaseSignals(); +} diff --git a/xorg-server/mi/mipointrst.h b/xorg-server/mi/mipointrst.h index bd9c24a00..c912a17da 100644 --- a/xorg-server/mi/mipointrst.h +++ b/xorg-server/mi/mipointrst.h @@ -44,6 +44,7 @@ typedef struct { Bool confined; /* pointer can't change screens */ int x, y; /* hot spot location */ int devx, devy; /* sprite position */ + Bool generateEvent; /* generate an event during warping? */ } miPointerRec, *miPointerPtr; typedef struct { diff --git a/xorg-server/mi/misprite.c b/xorg-server/mi/misprite.c index 0dce0a266..b0290af29 100644 --- a/xorg-server/mi/misprite.c +++ b/xorg-server/mi/misprite.c @@ -1,1045 +1,1045 @@ -/*
- * misprite.c
- *
- * machine independent software sprite routines
- */
-
-/*
-
-Copyright 1989, 1998 The Open Group
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation.
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
-AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of The Open Group shall not be
-used in advertising or otherwise to promote the sale, use or other dealings
-in this Software without prior written authorization from The Open Group.
-*/
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#include <X11/X.h>
-#include <X11/Xproto.h>
-#include "misc.h"
-#include "pixmapstr.h"
-#include "input.h"
-#include "mi.h"
-#include "cursorstr.h"
-#include <X11/fonts/font.h>
-#include "scrnintstr.h"
-#include "colormapst.h"
-#include "windowstr.h"
-#include "gcstruct.h"
-#include "mipointer.h"
-#include "misprite.h"
-#include "dixfontstr.h"
-#include <X11/fonts/fontstruct.h>
-#include "inputstr.h"
-#include "damage.h"
-
-typedef struct {
- CursorPtr pCursor;
- int x; /* cursor hotspot */
- int y;
- BoxRec saved; /* saved area from the screen */
- Bool isUp; /* cursor in frame buffer */
- Bool shouldBeUp; /* cursor should be displayed */
- WindowPtr pCacheWin; /* window the cursor last seen in */
- Bool isInCacheWin;
- Bool checkPixels; /* check colormap collision */
- ScreenPtr pScreen;
-} miCursorInfoRec, *miCursorInfoPtr;
-
-/*
- * per screen information
- */
-
-typedef struct {
- /* screen procedures */
- CloseScreenProcPtr CloseScreen;
- GetImageProcPtr GetImage;
- GetSpansProcPtr GetSpans;
- SourceValidateProcPtr SourceValidate;
-
- /* window procedures */
- CopyWindowProcPtr CopyWindow;
-
- /* colormap procedures */
- InstallColormapProcPtr InstallColormap;
- StoreColorsProcPtr StoreColors;
-
- /* os layer procedures */
- ScreenBlockHandlerProcPtr BlockHandler;
-
- /* device cursor procedures */
- DeviceCursorInitializeProcPtr DeviceCursorInitialize;
- DeviceCursorCleanupProcPtr DeviceCursorCleanup;
-
- xColorItem colors[2];
- ColormapPtr pInstalledMap;
- ColormapPtr pColormap;
- VisualPtr pVisual;
- DamagePtr pDamage; /* damage tracking structure */
- Bool damageRegistered;
- int numberOfCursors;
-} miSpriteScreenRec, *miSpriteScreenPtr;
-
-#define SOURCE_COLOR 0
-#define MASK_COLOR 1
-
-/*
- * Overlap BoxPtr and Box elements
- */
-#define BOX_OVERLAP(pCbox,X1,Y1,X2,Y2) \
- (((pCbox)->x1 <= (X2)) && ((X1) <= (pCbox)->x2) && \
- ((pCbox)->y1 <= (Y2)) && ((Y1) <= (pCbox)->y2))
-
-/*
- * Overlap BoxPtr, origins, and rectangle
- */
-#define ORG_OVERLAP(pCbox,xorg,yorg,x,y,w,h) \
- BOX_OVERLAP((pCbox),(x)+(xorg),(y)+(yorg),(x)+(xorg)+(w),(y)+(yorg)+(h))
-
-/*
- * Overlap BoxPtr, origins and RectPtr
- */
-#define ORGRECT_OVERLAP(pCbox,xorg,yorg,pRect) \
- ORG_OVERLAP((pCbox),(xorg),(yorg),(pRect)->x,(pRect)->y, \
- (int)((pRect)->width), (int)((pRect)->height))
-/*
- * Overlap BoxPtr and horizontal span
- */
-#define SPN_OVERLAP(pCbox,y,x,w) BOX_OVERLAP((pCbox),(x),(y),(x)+(w),(y))
-
-#define LINE_SORT(x1,y1,x2,y2) \
-{ int _t; \
- if (x1 > x2) { _t = x1; x1 = x2; x2 = _t; } \
- if (y1 > y2) { _t = y1; y1 = y2; y2 = _t; } }
-
-#define LINE_OVERLAP(pCbox,x1,y1,x2,y2,lw2) \
- BOX_OVERLAP((pCbox), (x1)-(lw2), (y1)-(lw2), (x2)+(lw2), (y2)+(lw2))
-
-
-#define SPRITE_DEBUG_ENABLE 0
-#if SPRITE_DEBUG_ENABLE
-#define SPRITE_DEBUG(x) ErrorF x
-#else
-#define SPRITE_DEBUG(x)
-#endif
-
-#define MISPRITE(dev) \
- ((!IsMaster(dev) && !dev->u.master) ? \
- (miCursorInfoPtr)dixLookupPrivate(&dev->devPrivates, miSpriteDevPrivatesKey) : \
- (miCursorInfoPtr)dixLookupPrivate(&(GetMaster(dev, MASTER_POINTER))->devPrivates, miSpriteDevPrivatesKey))
-
-static void
-miSpriteDisableDamage(ScreenPtr pScreen, miSpriteScreenPtr pScreenPriv)
-{
- if (pScreenPriv->damageRegistered) {
- DamageUnregister (&(pScreen->GetScreenPixmap(pScreen)->drawable),
- pScreenPriv->pDamage);
- pScreenPriv->damageRegistered = 0;
- }
-}
-
-static void
-miSpriteEnableDamage(ScreenPtr pScreen, miSpriteScreenPtr pScreenPriv)
-{
- if (!pScreenPriv->damageRegistered) {
- pScreenPriv->damageRegistered = 1;
- DamageRegister (&(pScreen->GetScreenPixmap(pScreen)->drawable),
- pScreenPriv->pDamage);
- }
-}
-
-static void
-miSpriteIsUp(miCursorInfoPtr pDevCursor)
-{
- pDevCursor->isUp = TRUE;
-}
-
-static void
-miSpriteIsDown(miCursorInfoPtr pDevCursor)
-{
- pDevCursor->isUp = FALSE;
-}
-
-/*
- * screen wrappers
- */
-
-static DevPrivateKeyRec miSpriteScreenKeyRec;
-#define miSpriteScreenKey (&miSpriteScreenKeyRec)
-#define GetSpriteScreen(pScreen) \
- (dixLookupPrivate(&(pScreen)->devPrivates, miSpriteScreenKey))
-static DevPrivateKeyRec miSpriteDevPrivatesKeyRec;
-#define miSpriteDevPrivatesKey (&miSpriteDevPrivatesKeyRec)
-
-static Bool miSpriteCloseScreen(int i, ScreenPtr pScreen);
-static void miSpriteGetImage(DrawablePtr pDrawable, int sx, int sy,
- int w, int h, unsigned int format,
- unsigned long planemask, char *pdstLine);
-static void miSpriteGetSpans(DrawablePtr pDrawable, int wMax,
- DDXPointPtr ppt, int *pwidth, int nspans,
- char *pdstStart);
-static void miSpriteSourceValidate(DrawablePtr pDrawable, int x, int y,
- int width, int height,
- unsigned int subWindowMode);
-static void miSpriteCopyWindow (WindowPtr pWindow,
- DDXPointRec ptOldOrg,
- RegionPtr prgnSrc);
-static void miSpriteBlockHandler(int i, pointer blockData,
- pointer pTimeout,
- pointer pReadMask);
-static void miSpriteInstallColormap(ColormapPtr pMap);
-static void miSpriteStoreColors(ColormapPtr pMap, int ndef,
- xColorItem *pdef);
-
-static void miSpriteComputeSaved(DeviceIntPtr pDev,
- ScreenPtr pScreen);
-
-static Bool miSpriteDeviceCursorInitialize(DeviceIntPtr pDev,
- ScreenPtr pScreen);
-static void miSpriteDeviceCursorCleanup(DeviceIntPtr pDev,
- ScreenPtr pScreen);
-
-#define SCREEN_PROLOGUE(pPriv, pScreen, field) ((pScreen)->field = \
- (pPriv)->field)
-#define SCREEN_EPILOGUE(pPriv, pScreen, field)\
- ((pPriv)->field = (pScreen)->field, (pScreen)->field = miSprite##field)
-
-/*
- * pointer-sprite method table
- */
-
-static Bool miSpriteRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
- CursorPtr pCursor);
-static Bool miSpriteUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
- CursorPtr pCursor);
-static void miSpriteSetCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
- CursorPtr pCursor, int x, int y);
-static void miSpriteMoveCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
- int x, int y);
-
-miPointerSpriteFuncRec miSpritePointerFuncs = {
- miSpriteRealizeCursor,
- miSpriteUnrealizeCursor,
- miSpriteSetCursor,
- miSpriteMoveCursor,
- miSpriteDeviceCursorInitialize,
- miSpriteDeviceCursorCleanup,
-};
-
-/*
- * other misc functions
- */
-
-static void miSpriteRemoveCursor(DeviceIntPtr pDev,
- ScreenPtr pScreen);
-static void miSpriteSaveUnderCursor(DeviceIntPtr pDev,
- ScreenPtr pScreen);
-static void miSpriteRestoreCursor(DeviceIntPtr pDev,
- ScreenPtr pScreen);
-
-static void
-miSpriteRegisterBlockHandler(ScreenPtr pScreen, miSpriteScreenPtr pScreenPriv)
-{
- if (!pScreenPriv->BlockHandler) {
- pScreenPriv->BlockHandler = pScreen->BlockHandler;
- pScreen->BlockHandler = miSpriteBlockHandler;
- }
-}
-
-static void
-miSpriteReportDamage (DamagePtr pDamage, RegionPtr pRegion, void *closure)
-{
- ScreenPtr pScreen = closure;
- miCursorInfoPtr pCursorInfo;
- DeviceIntPtr pDev;
-
- for (pDev = inputInfo.devices; pDev; pDev = pDev->next)
- {
- if (DevHasCursor(pDev))
- {
- pCursorInfo = MISPRITE(pDev);
-
- if (pCursorInfo->isUp &&
- pCursorInfo->pScreen == pScreen &&
- RegionContainsRect(pRegion, &pCursorInfo->saved) != rgnOUT)
- {
- SPRITE_DEBUG(("Damage remove\n"));
- miSpriteRemoveCursor (pDev, pScreen);
- }
- }
- }
-}
-
-/*
- * miSpriteInitialize -- called from device-dependent screen
- * initialization proc after all of the function pointers have
- * been stored in the screen structure.
- */
-
-Bool
-miSpriteInitialize (ScreenPtr pScreen,
- miPointerScreenFuncPtr screenFuncs)
-{
- miSpriteScreenPtr pScreenPriv;
- VisualPtr pVisual;
-
- if (!DamageSetup (pScreen))
- return FALSE;
-
- if (!dixRegisterPrivateKey(&miSpriteScreenKeyRec, PRIVATE_SCREEN, 0))
- return FALSE;
-
- if (!dixRegisterPrivateKey(&miSpriteDevPrivatesKeyRec, PRIVATE_DEVICE, 0))
- return FALSE;
-
- pScreenPriv = malloc(sizeof (miSpriteScreenRec));
- if (!pScreenPriv)
- return FALSE;
-
- pScreenPriv->pDamage = DamageCreate (miSpriteReportDamage,
- NULL,
- DamageReportRawRegion,
- TRUE,
- pScreen,
- pScreen);
-
- if (!miPointerInitialize (pScreen, &miSpritePointerFuncs, screenFuncs,TRUE))
- {
- free(pScreenPriv);
- return FALSE;
- }
- for (pVisual = pScreen->visuals;
- pVisual->vid != pScreen->rootVisual;
- pVisual++)
- ;
- pScreenPriv->pVisual = pVisual;
- pScreenPriv->CloseScreen = pScreen->CloseScreen;
- pScreenPriv->GetImage = pScreen->GetImage;
- pScreenPriv->GetSpans = pScreen->GetSpans;
- pScreenPriv->SourceValidate = pScreen->SourceValidate;
-
- pScreenPriv->CopyWindow = pScreen->CopyWindow;
-
- pScreenPriv->InstallColormap = pScreen->InstallColormap;
- pScreenPriv->StoreColors = pScreen->StoreColors;
-
- pScreenPriv->BlockHandler = NULL;
-
- pScreenPriv->DeviceCursorInitialize = pScreen->DeviceCursorInitialize;
- pScreenPriv->DeviceCursorCleanup = pScreen->DeviceCursorCleanup;
-
- pScreenPriv->pInstalledMap = NULL;
- pScreenPriv->pColormap = NULL;
- pScreenPriv->colors[SOURCE_COLOR].red = 0;
- pScreenPriv->colors[SOURCE_COLOR].green = 0;
- pScreenPriv->colors[SOURCE_COLOR].blue = 0;
- pScreenPriv->colors[MASK_COLOR].red = 0;
- pScreenPriv->colors[MASK_COLOR].green = 0;
- pScreenPriv->colors[MASK_COLOR].blue = 0;
- pScreenPriv->damageRegistered = 0;
- pScreenPriv->numberOfCursors = 0;
-
- dixSetPrivate(&pScreen->devPrivates, miSpriteScreenKey, pScreenPriv);
-
- pScreen->CloseScreen = miSpriteCloseScreen;
- pScreen->GetImage = miSpriteGetImage;
- pScreen->GetSpans = miSpriteGetSpans;
- pScreen->SourceValidate = miSpriteSourceValidate;
-
- pScreen->CopyWindow = miSpriteCopyWindow;
- pScreen->InstallColormap = miSpriteInstallColormap;
- pScreen->StoreColors = miSpriteStoreColors;
-
- return TRUE;
-}
-
-/*
- * Screen wrappers
- */
-
-/*
- * CloseScreen wrapper -- unwrap everything, free the private data
- * and call the wrapped function
- */
-
-static Bool
-miSpriteCloseScreen (int i, ScreenPtr pScreen)
-{
- miSpriteScreenPtr pScreenPriv = GetSpriteScreen(pScreen);
-
- pScreen->CloseScreen = pScreenPriv->CloseScreen;
- pScreen->GetImage = pScreenPriv->GetImage;
- pScreen->GetSpans = pScreenPriv->GetSpans;
- pScreen->SourceValidate = pScreenPriv->SourceValidate;
- pScreen->InstallColormap = pScreenPriv->InstallColormap;
- pScreen->StoreColors = pScreenPriv->StoreColors;
-
- DamageDestroy (pScreenPriv->pDamage);
-
- free(pScreenPriv);
-
- return (*pScreen->CloseScreen) (i, pScreen);
-}
-
-static void
-miSpriteGetImage (DrawablePtr pDrawable, int sx, int sy, int w, int h,
- unsigned int format, unsigned long planemask,
- char *pdstLine)
-{
- ScreenPtr pScreen = pDrawable->pScreen;
- DeviceIntPtr pDev;
- miCursorInfoPtr pCursorInfo;
- miSpriteScreenPtr pPriv = GetSpriteScreen(pScreen);
-
- SCREEN_PROLOGUE (pPriv, pScreen, GetImage);
-
- if (pDrawable->type == DRAWABLE_WINDOW)
- {
- for(pDev = inputInfo.devices; pDev; pDev = pDev->next)
- {
- if (DevHasCursor(pDev))
- {
- pCursorInfo = MISPRITE(pDev);
- if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen &&
- ORG_OVERLAP(&pCursorInfo->saved,pDrawable->x,pDrawable->y,
- sx, sy, w, h))
- {
- SPRITE_DEBUG (("GetImage remove\n"));
- miSpriteRemoveCursor (pDev, pScreen);
- }
- }
- }
- }
-
- (*pScreen->GetImage) (pDrawable, sx, sy, w, h,
- format, planemask, pdstLine);
-
- SCREEN_EPILOGUE (pPriv, pScreen, GetImage);
-}
-
-static void
-miSpriteGetSpans (DrawablePtr pDrawable, int wMax, DDXPointPtr ppt,
- int *pwidth, int nspans, char *pdstStart)
-{
- ScreenPtr pScreen = pDrawable->pScreen;
- DeviceIntPtr pDev;
- miCursorInfoPtr pCursorInfo;
- miSpriteScreenPtr pPriv = GetSpriteScreen(pScreen);
-
- SCREEN_PROLOGUE (pPriv, pScreen, GetSpans);
-
- if (pDrawable->type == DRAWABLE_WINDOW)
- {
- for(pDev = inputInfo.devices; pDev; pDev = pDev->next)
- {
- if (DevHasCursor(pDev))
- {
- pCursorInfo = MISPRITE(pDev);
-
- if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen)
- {
- DDXPointPtr pts;
- int *widths;
- int nPts;
- int xorg,
- yorg;
-
- xorg = pDrawable->x;
- yorg = pDrawable->y;
-
- for (pts = ppt, widths = pwidth, nPts = nspans;
- nPts--;
- pts++, widths++)
- {
- if (SPN_OVERLAP(&pCursorInfo->saved,pts->y+yorg,
- pts->x+xorg,*widths))
- {
- SPRITE_DEBUG (("GetSpans remove\n"));
- miSpriteRemoveCursor (pDev, pScreen);
- break;
- }
- }
- }
- }
- }
- }
-
- (*pScreen->GetSpans) (pDrawable, wMax, ppt, pwidth, nspans, pdstStart);
-
- SCREEN_EPILOGUE (pPriv, pScreen, GetSpans);
-}
-
-static void
-miSpriteSourceValidate (DrawablePtr pDrawable, int x, int y, int width,
- int height, unsigned int subWindowMode)
-{
- ScreenPtr pScreen = pDrawable->pScreen;
- DeviceIntPtr pDev;
- miCursorInfoPtr pCursorInfo;
- miSpriteScreenPtr pPriv = GetSpriteScreen(pScreen);
-
- SCREEN_PROLOGUE (pPriv, pScreen, SourceValidate);
-
- if (pDrawable->type == DRAWABLE_WINDOW)
- {
- for(pDev = inputInfo.devices; pDev; pDev = pDev->next)
- {
- if (DevHasCursor(pDev))
- {
- pCursorInfo = MISPRITE(pDev);
- if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen &&
- ORG_OVERLAP(&pCursorInfo->saved, pDrawable->x, pDrawable->y,
- x, y, width, height))
- {
- SPRITE_DEBUG (("SourceValidate remove\n"));
- miSpriteRemoveCursor (pDev, pScreen);
- }
- }
- }
- }
-
- if (pScreen->SourceValidate)
- (*pScreen->SourceValidate) (pDrawable, x, y, width, height, subWindowMode);
-
- SCREEN_EPILOGUE (pPriv, pScreen, SourceValidate);
-}
-
-static void
-miSpriteCopyWindow (WindowPtr pWindow, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
-{
- ScreenPtr pScreen = pWindow->drawable.pScreen;
- DeviceIntPtr pDev;
- miCursorInfoPtr pCursorInfo;
- miSpriteScreenPtr pPriv = GetSpriteScreen(pScreen);
-
- SCREEN_PROLOGUE (pPriv, pScreen, CopyWindow);
-
- for(pDev = inputInfo.devices; pDev; pDev = pDev->next)
- {
- if (DevHasCursor(pDev))
- {
- pCursorInfo = MISPRITE(pDev);
- /*
- * Damage will take care of destination check
- */
- if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen &&
- RegionContainsRect(prgnSrc, &pCursorInfo->saved) != rgnOUT)
- {
- SPRITE_DEBUG (("CopyWindow remove\n"));
- miSpriteRemoveCursor (pDev, pScreen);
- }
- }
- }
-
- (*pScreen->CopyWindow) (pWindow, ptOldOrg, prgnSrc);
- SCREEN_EPILOGUE (pPriv, pScreen, CopyWindow);
-}
-
-static void
-miSpriteBlockHandler (int i, pointer blockData, pointer pTimeout,
- pointer pReadmask)
-{
- ScreenPtr pScreen = screenInfo.screens[i];
- miSpriteScreenPtr pPriv = GetSpriteScreen(pScreen);
- DeviceIntPtr pDev;
- miCursorInfoPtr pCursorInfo;
- Bool WorkToDo = FALSE;
-
- for(pDev = inputInfo.devices; pDev; pDev = pDev->next)
- {
- if (DevHasCursor(pDev))
- {
- pCursorInfo = MISPRITE(pDev);
- if (pCursorInfo && !pCursorInfo->isUp
- && pCursorInfo->pScreen == pScreen
- && pCursorInfo->shouldBeUp)
- {
- SPRITE_DEBUG (("BlockHandler save"));
- miSpriteSaveUnderCursor (pDev, pScreen);
- }
- }
- }
- for(pDev = inputInfo.devices; pDev; pDev = pDev->next)
- {
- if (DevHasCursor(pDev))
- {
- pCursorInfo = MISPRITE(pDev);
- if (pCursorInfo && !pCursorInfo->isUp &&
- pCursorInfo->pScreen == pScreen &&
- pCursorInfo->shouldBeUp)
- {
- SPRITE_DEBUG (("BlockHandler restore\n"));
- miSpriteRestoreCursor (pDev, pScreen);
- if (!pCursorInfo->isUp)
- WorkToDo = TRUE;
- }
- }
- }
-
- SCREEN_PROLOGUE(pPriv, pScreen, BlockHandler);
-
- (*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask);
-
- if (WorkToDo)
- SCREEN_EPILOGUE(pPriv, pScreen, BlockHandler);
- else
- pPriv->BlockHandler = NULL;
-}
-
-static void
-miSpriteInstallColormap (ColormapPtr pMap)
-{
- ScreenPtr pScreen = pMap->pScreen;
- miSpriteScreenPtr pPriv = GetSpriteScreen(pScreen);
-
- SCREEN_PROLOGUE(pPriv, pScreen, InstallColormap);
-
- (*pScreen->InstallColormap) (pMap);
-
- SCREEN_EPILOGUE(pPriv, pScreen, InstallColormap);
-
- /* InstallColormap can be called before devices are initialized. */
- pPriv->pInstalledMap = pMap;
- if (pPriv->pColormap != pMap)
- {
- DeviceIntPtr pDev;
- miCursorInfoPtr pCursorInfo;
- for (pDev = inputInfo.devices; pDev; pDev = pDev->next)
- {
- if (DevHasCursor(pDev))
- {
- pCursorInfo = MISPRITE(pDev);
- pCursorInfo->checkPixels = TRUE;
- if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen)
- miSpriteRemoveCursor(pDev, pScreen);
- }
- }
-
- }
-}
-
-static void
-miSpriteStoreColors (ColormapPtr pMap, int ndef, xColorItem *pdef)
-{
- ScreenPtr pScreen = pMap->pScreen;
- miSpriteScreenPtr pPriv = GetSpriteScreen(pScreen);
- int i;
- int updated;
- VisualPtr pVisual;
- DeviceIntPtr pDev;
- miCursorInfoPtr pCursorInfo;
-
- SCREEN_PROLOGUE(pPriv, pScreen, StoreColors);
-
- (*pScreen->StoreColors) (pMap, ndef, pdef);
-
- SCREEN_EPILOGUE(pPriv, pScreen, StoreColors);
-
- if (pPriv->pColormap == pMap)
- {
- updated = 0;
- pVisual = pMap->pVisual;
- if (pVisual->class == DirectColor)
- {
- /* Direct color - match on any of the subfields */
-
-#define MaskMatch(a,b,mask) (((a) & (pVisual->mask)) == ((b) & (pVisual->mask)))
-
-#define UpdateDAC(dev, plane,dac,mask) {\
- if (MaskMatch (dev->colors[plane].pixel,pdef[i].pixel,mask)) {\
- dev->colors[plane].dac = pdef[i].dac; \
- updated = 1; \
- } \
-}
-
-#define CheckDirect(dev, plane) \
- UpdateDAC(dev, plane,red,redMask) \
- UpdateDAC(dev, plane,green,greenMask) \
- UpdateDAC(dev, plane,blue,blueMask)
-
- for (i = 0; i < ndef; i++)
- {
- CheckDirect (pPriv, SOURCE_COLOR)
- CheckDirect (pPriv, MASK_COLOR)
- }
- }
- else
- {
- /* PseudoColor/GrayScale - match on exact pixel */
- for (i = 0; i < ndef; i++)
- {
- if (pdef[i].pixel ==
- pPriv->colors[SOURCE_COLOR].pixel)
- {
- pPriv->colors[SOURCE_COLOR] = pdef[i];
- if (++updated == 2)
- break;
- }
- if (pdef[i].pixel ==
- pPriv->colors[MASK_COLOR].pixel)
- {
- pPriv->colors[MASK_COLOR] = pdef[i];
- if (++updated == 2)
- break;
- }
- }
- }
- if (updated)
- {
- for(pDev = inputInfo.devices; pDev; pDev = pDev->next)
- {
- if (DevHasCursor(pDev))
- {
- pCursorInfo = MISPRITE(pDev);
- pCursorInfo->checkPixels = TRUE;
- if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen)
- miSpriteRemoveCursor (pDev, pScreen);
- }
- }
- }
- }
-}
-
-static void
-miSpriteFindColors (miCursorInfoPtr pDevCursor, ScreenPtr pScreen)
-{
- miSpriteScreenPtr pScreenPriv = GetSpriteScreen(pScreen);
- CursorPtr pCursor;
- xColorItem *sourceColor, *maskColor;
-
- pCursor = pDevCursor->pCursor;
- sourceColor = &pScreenPriv->colors[SOURCE_COLOR];
- maskColor = &pScreenPriv->colors[MASK_COLOR];
- if (pScreenPriv->pColormap != pScreenPriv->pInstalledMap ||
- !(pCursor->foreRed == sourceColor->red &&
- pCursor->foreGreen == sourceColor->green &&
- pCursor->foreBlue == sourceColor->blue &&
- pCursor->backRed == maskColor->red &&
- pCursor->backGreen == maskColor->green &&
- pCursor->backBlue == maskColor->blue))
- {
- pScreenPriv->pColormap = pScreenPriv->pInstalledMap;
- sourceColor->red = pCursor->foreRed;
- sourceColor->green = pCursor->foreGreen;
- sourceColor->blue = pCursor->foreBlue;
- FakeAllocColor (pScreenPriv->pColormap, sourceColor);
- maskColor->red = pCursor->backRed;
- maskColor->green = pCursor->backGreen;
- maskColor->blue = pCursor->backBlue;
- FakeAllocColor (pScreenPriv->pColormap, maskColor);
- /* "free" the pixels right away, don't let this confuse you */
- FakeFreeColor(pScreenPriv->pColormap, sourceColor->pixel);
- FakeFreeColor(pScreenPriv->pColormap, maskColor->pixel);
- }
-
- pDevCursor->checkPixels = FALSE;
-
-}
-
-/*
- * miPointer interface routines
- */
-
-#define SPRITE_PAD 8
-
-static Bool
-miSpriteRealizeCursor (DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor)
-{
- miCursorInfoPtr pCursorInfo;
-
- if (!IsMaster(pDev) && !pDev->u.master)
- return FALSE;
-
- pCursorInfo = MISPRITE(pDev);
-
- if (pCursor == pCursorInfo->pCursor)
- pCursorInfo->checkPixels = TRUE;
-
- return miDCRealizeCursor(pScreen, pCursor);
-}
-
-static Bool
-miSpriteUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor)
-{
- return miDCUnrealizeCursor(pScreen, pCursor);
-}
-
-static void
-miSpriteSetCursor (DeviceIntPtr pDev, ScreenPtr pScreen,
- CursorPtr pCursor, int x, int y)
-{
- miCursorInfoPtr pPointer;
- miSpriteScreenPtr pScreenPriv;
-
- if (!IsMaster(pDev) && !pDev->u.master)
- return;
-
- pPointer = MISPRITE(pDev);
- pScreenPriv = GetSpriteScreen(pScreen);
-
- if (!pCursor)
- {
- if (pPointer->shouldBeUp)
- --pScreenPriv->numberOfCursors;
- pPointer->shouldBeUp = FALSE;
- if (pPointer->isUp)
- miSpriteRemoveCursor (pDev, pScreen);
- if (pScreenPriv->numberOfCursors == 0)
- miSpriteDisableDamage(pScreen, pScreenPriv);
- pPointer->pCursor = 0;
- return;
- }
- if (!pPointer->shouldBeUp)
- pScreenPriv->numberOfCursors++;
- pPointer->shouldBeUp = TRUE;
- if (!pPointer->isUp)
- miSpriteRegisterBlockHandler(pScreen, pScreenPriv);
- if (pPointer->x == x &&
- pPointer->y == y &&
- pPointer->pCursor == pCursor &&
- !pPointer->checkPixels)
- {
- return;
- }
- pPointer->x = x;
- pPointer->y = y;
- pPointer->pCacheWin = NullWindow;
- if (pPointer->checkPixels || pPointer->pCursor != pCursor)
- {
- pPointer->pCursor = pCursor;
- miSpriteFindColors (pPointer, pScreen);
- }
- if (pPointer->isUp) {
- /* TODO: reimplement flicker-free MoveCursor */
- SPRITE_DEBUG (("SetCursor remove %d\n", pDev->id));
- miSpriteRemoveCursor (pDev, pScreen);
- }
-
- if (!pPointer->isUp && pPointer->pCursor)
- {
- SPRITE_DEBUG (("SetCursor restore %d\n", pDev->id));
- miSpriteSaveUnderCursor(pDev, pScreen);
- miSpriteRestoreCursor (pDev, pScreen);
- }
-
-}
-
-static void
-miSpriteMoveCursor (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)
-{
- CursorPtr pCursor;
-
- if (!IsMaster(pDev) && !pDev->u.master)
- return;
-
- pCursor = MISPRITE(pDev)->pCursor;
-
- miSpriteSetCursor (pDev, pScreen, pCursor, x, y);
-}
-
-
-static Bool
-miSpriteDeviceCursorInitialize(DeviceIntPtr pDev, ScreenPtr pScreen)
-{
- miCursorInfoPtr pCursorInfo;
- int ret = FALSE;
-
- pCursorInfo = malloc(sizeof(miCursorInfoRec));
- if (!pCursorInfo)
- return FALSE;
-
- pCursorInfo->pCursor = NULL;
- pCursorInfo->x = 0;
- pCursorInfo->y = 0;
- pCursorInfo->isUp = FALSE;
- pCursorInfo->shouldBeUp = FALSE;
- pCursorInfo->pCacheWin = NullWindow;
- pCursorInfo->isInCacheWin = FALSE;
- pCursorInfo->checkPixels = TRUE;
- pCursorInfo->pScreen = FALSE;
-
- ret = miDCDeviceInitialize(pDev, pScreen);
- if (!ret)
- {
- free(pCursorInfo);
- pCursorInfo = NULL;
- }
- dixSetPrivate(&pDev->devPrivates, miSpriteDevPrivatesKey, pCursorInfo);
- return ret;
-}
-
-static void
-miSpriteDeviceCursorCleanup(DeviceIntPtr pDev, ScreenPtr pScreen)
-{
- if (DevHasCursor(pDev))
- miDCDeviceCleanup(pDev, pScreen);
-}
-
-/*
- * undraw/draw cursor
- */
-
-static void
-miSpriteRemoveCursor (DeviceIntPtr pDev, ScreenPtr pScreen)
-{
- miSpriteScreenPtr pScreenPriv;
- miCursorInfoPtr pCursorInfo;
-
-
- if (!IsMaster(pDev) && !pDev->u.master)
- return;
-
- DamageDrawInternal (pScreen, TRUE);
- pScreenPriv = GetSpriteScreen(pScreen);
- pCursorInfo = MISPRITE(pDev);
-
- miSpriteIsDown(pCursorInfo);
- miSpriteRegisterBlockHandler(pScreen, pScreenPriv);
- pCursorInfo->pCacheWin = NullWindow;
- miSpriteDisableDamage(pScreen, pScreenPriv);
- if (!miDCRestoreUnderCursor(pDev,
- pScreen,
- pCursorInfo->saved.x1,
- pCursorInfo->saved.y1,
- pCursorInfo->saved.x2 -
- pCursorInfo->saved.x1,
- pCursorInfo->saved.y2 -
- pCursorInfo->saved.y1))
- {
- miSpriteIsUp(pCursorInfo);
- }
- miSpriteEnableDamage(pScreen, pScreenPriv);
- DamageDrawInternal (pScreen, FALSE);
-}
-
-/*
- * Called from the block handler, saves area under cursor
- * before waiting for something to do.
- */
-
-static void
-miSpriteSaveUnderCursor(DeviceIntPtr pDev, ScreenPtr pScreen)
-{
- miSpriteScreenPtr pScreenPriv;
- int x, y;
- CursorPtr pCursor;
- miCursorInfoPtr pCursorInfo;
-
- if (!IsMaster(pDev) && !pDev->u.master)
- return;
-
- DamageDrawInternal (pScreen, TRUE);
- pScreenPriv = GetSpriteScreen(pScreen);
- pCursorInfo = MISPRITE(pDev);
-
- miSpriteComputeSaved (pDev, pScreen);
- pCursor = pCursorInfo->pCursor;
-
- x = pCursorInfo->x - (int)pCursor->bits->xhot;
- y = pCursorInfo->y - (int)pCursor->bits->yhot;
- miSpriteDisableDamage(pScreen, pScreenPriv);
-
- miDCSaveUnderCursor(pDev,
- pScreen,
- pCursorInfo->saved.x1,
- pCursorInfo->saved.y1,
- pCursorInfo->saved.x2 -
- pCursorInfo->saved.x1,
- pCursorInfo->saved.y2 -
- pCursorInfo->saved.y1);
- SPRITE_DEBUG(("SaveUnderCursor %d\n", pDev->id));
- miSpriteEnableDamage(pScreen, pScreenPriv);
- DamageDrawInternal (pScreen, FALSE);
-}
-
-
-/*
- * Called from the block handler, restores the cursor
- * before waiting for something to do.
- */
-
-static void
-miSpriteRestoreCursor (DeviceIntPtr pDev, ScreenPtr pScreen)
-{
- miSpriteScreenPtr pScreenPriv;
- int x, y;
- CursorPtr pCursor;
- miCursorInfoPtr pCursorInfo;
-
- if (!IsMaster(pDev) && !pDev->u.master)
- return;
-
- DamageDrawInternal (pScreen, TRUE);
- pScreenPriv = GetSpriteScreen(pScreen);
- pCursorInfo = MISPRITE(pDev);
-
- miSpriteComputeSaved (pDev, pScreen);
- pCursor = pCursorInfo->pCursor;
-
- x = pCursorInfo->x - (int)pCursor->bits->xhot;
- y = pCursorInfo->y - (int)pCursor->bits->yhot;
- miSpriteDisableDamage(pScreen, pScreenPriv);
- SPRITE_DEBUG(("RestoreCursor %d\n", pDev->id));
- if (pCursorInfo->checkPixels)
- miSpriteFindColors (pCursorInfo, pScreen);
- if (miDCPutUpCursor(pDev, pScreen,
- pCursor, x, y,
- pScreenPriv->colors[SOURCE_COLOR].pixel,
- pScreenPriv->colors[MASK_COLOR].pixel))
- {
- miSpriteIsUp(pCursorInfo);
- pCursorInfo->pScreen = pScreen;
- }
- miSpriteEnableDamage(pScreen, pScreenPriv);
- DamageDrawInternal (pScreen, FALSE);
-}
-
-/*
- * compute the desired area of the screen to save
- */
-
-static void
-miSpriteComputeSaved (DeviceIntPtr pDev, ScreenPtr pScreen)
-{
- int x, y, w, h;
- int wpad, hpad;
- CursorPtr pCursor;
- miCursorInfoPtr pCursorInfo;
-
- if (!IsMaster(pDev) && !pDev->u.master)
- return;
-
- pCursorInfo = MISPRITE(pDev);
-
- pCursor = pCursorInfo->pCursor;
- x = pCursorInfo->x - (int)pCursor->bits->xhot;
- y = pCursorInfo->y - (int)pCursor->bits->yhot;
- w = pCursor->bits->width;
- h = pCursor->bits->height;
- wpad = SPRITE_PAD;
- hpad = SPRITE_PAD;
- pCursorInfo->saved.x1 = x - wpad;
- pCursorInfo->saved.y1 = y - hpad;
- pCursorInfo->saved.x2 = pCursorInfo->saved.x1 + w + wpad * 2;
- pCursorInfo->saved.y2 = pCursorInfo->saved.y1 + h + hpad * 2;
-}
-
+/* + * misprite.c + * + * machine independent software sprite routines + */ + +/* + +Copyright 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. +*/ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include <X11/X.h> +#include <X11/Xproto.h> +#include "misc.h" +#include "pixmapstr.h" +#include "input.h" +#include "mi.h" +#include "cursorstr.h" +#include <X11/fonts/font.h> +#include "scrnintstr.h" +#include "colormapst.h" +#include "windowstr.h" +#include "gcstruct.h" +#include "mipointer.h" +#include "misprite.h" +#include "dixfontstr.h" +#include <X11/fonts/fontstruct.h> +#include "inputstr.h" +#include "damage.h" + +typedef struct { + CursorPtr pCursor; + int x; /* cursor hotspot */ + int y; + BoxRec saved; /* saved area from the screen */ + Bool isUp; /* cursor in frame buffer */ + Bool shouldBeUp; /* cursor should be displayed */ + WindowPtr pCacheWin; /* window the cursor last seen in */ + Bool isInCacheWin; + Bool checkPixels; /* check colormap collision */ + ScreenPtr pScreen; +} miCursorInfoRec, *miCursorInfoPtr; + +/* + * per screen information + */ + +typedef struct { + /* screen procedures */ + CloseScreenProcPtr CloseScreen; + GetImageProcPtr GetImage; + GetSpansProcPtr GetSpans; + SourceValidateProcPtr SourceValidate; + + /* window procedures */ + CopyWindowProcPtr CopyWindow; + + /* colormap procedures */ + InstallColormapProcPtr InstallColormap; + StoreColorsProcPtr StoreColors; + + /* os layer procedures */ + ScreenBlockHandlerProcPtr BlockHandler; + + /* device cursor procedures */ + DeviceCursorInitializeProcPtr DeviceCursorInitialize; + DeviceCursorCleanupProcPtr DeviceCursorCleanup; + + xColorItem colors[2]; + ColormapPtr pInstalledMap; + ColormapPtr pColormap; + VisualPtr pVisual; + DamagePtr pDamage; /* damage tracking structure */ + Bool damageRegistered; + int numberOfCursors; +} miSpriteScreenRec, *miSpriteScreenPtr; + +#define SOURCE_COLOR 0 +#define MASK_COLOR 1 + +/* + * Overlap BoxPtr and Box elements + */ +#define BOX_OVERLAP(pCbox,X1,Y1,X2,Y2) \ + (((pCbox)->x1 <= (X2)) && ((X1) <= (pCbox)->x2) && \ + ((pCbox)->y1 <= (Y2)) && ((Y1) <= (pCbox)->y2)) + +/* + * Overlap BoxPtr, origins, and rectangle + */ +#define ORG_OVERLAP(pCbox,xorg,yorg,x,y,w,h) \ + BOX_OVERLAP((pCbox),(x)+(xorg),(y)+(yorg),(x)+(xorg)+(w),(y)+(yorg)+(h)) + +/* + * Overlap BoxPtr, origins and RectPtr + */ +#define ORGRECT_OVERLAP(pCbox,xorg,yorg,pRect) \ + ORG_OVERLAP((pCbox),(xorg),(yorg),(pRect)->x,(pRect)->y, \ + (int)((pRect)->width), (int)((pRect)->height)) +/* + * Overlap BoxPtr and horizontal span + */ +#define SPN_OVERLAP(pCbox,y,x,w) BOX_OVERLAP((pCbox),(x),(y),(x)+(w),(y)) + +#define LINE_SORT(x1,y1,x2,y2) \ +{ int _t; \ + if (x1 > x2) { _t = x1; x1 = x2; x2 = _t; } \ + if (y1 > y2) { _t = y1; y1 = y2; y2 = _t; } } + +#define LINE_OVERLAP(pCbox,x1,y1,x2,y2,lw2) \ + BOX_OVERLAP((pCbox), (x1)-(lw2), (y1)-(lw2), (x2)+(lw2), (y2)+(lw2)) + + +#define SPRITE_DEBUG_ENABLE 0 +#if SPRITE_DEBUG_ENABLE +#define SPRITE_DEBUG(x) ErrorF x +#else +#define SPRITE_DEBUG(x) +#endif + +#define MISPRITE(dev) \ + (IsFloating(dev) ? \ + (miCursorInfoPtr)dixLookupPrivate(&dev->devPrivates, miSpriteDevPrivatesKey) : \ + (miCursorInfoPtr)dixLookupPrivate(&(GetMaster(dev, MASTER_POINTER))->devPrivates, miSpriteDevPrivatesKey)) + +static void +miSpriteDisableDamage(ScreenPtr pScreen, miSpriteScreenPtr pScreenPriv) +{ + if (pScreenPriv->damageRegistered) { + DamageUnregister (&(pScreen->GetScreenPixmap(pScreen)->drawable), + pScreenPriv->pDamage); + pScreenPriv->damageRegistered = 0; + } +} + +static void +miSpriteEnableDamage(ScreenPtr pScreen, miSpriteScreenPtr pScreenPriv) +{ + if (!pScreenPriv->damageRegistered) { + pScreenPriv->damageRegistered = 1; + DamageRegister (&(pScreen->GetScreenPixmap(pScreen)->drawable), + pScreenPriv->pDamage); + } +} + +static void +miSpriteIsUp(miCursorInfoPtr pDevCursor) +{ + pDevCursor->isUp = TRUE; +} + +static void +miSpriteIsDown(miCursorInfoPtr pDevCursor) +{ + pDevCursor->isUp = FALSE; +} + +/* + * screen wrappers + */ + +static DevPrivateKeyRec miSpriteScreenKeyRec; +#define miSpriteScreenKey (&miSpriteScreenKeyRec) +#define GetSpriteScreen(pScreen) \ + (dixLookupPrivate(&(pScreen)->devPrivates, miSpriteScreenKey)) +static DevPrivateKeyRec miSpriteDevPrivatesKeyRec; +#define miSpriteDevPrivatesKey (&miSpriteDevPrivatesKeyRec) + +static Bool miSpriteCloseScreen(int i, ScreenPtr pScreen); +static void miSpriteGetImage(DrawablePtr pDrawable, int sx, int sy, + int w, int h, unsigned int format, + unsigned long planemask, char *pdstLine); +static void miSpriteGetSpans(DrawablePtr pDrawable, int wMax, + DDXPointPtr ppt, int *pwidth, int nspans, + char *pdstStart); +static void miSpriteSourceValidate(DrawablePtr pDrawable, int x, int y, + int width, int height, + unsigned int subWindowMode); +static void miSpriteCopyWindow (WindowPtr pWindow, + DDXPointRec ptOldOrg, + RegionPtr prgnSrc); +static void miSpriteBlockHandler(int i, pointer blockData, + pointer pTimeout, + pointer pReadMask); +static void miSpriteInstallColormap(ColormapPtr pMap); +static void miSpriteStoreColors(ColormapPtr pMap, int ndef, + xColorItem *pdef); + +static void miSpriteComputeSaved(DeviceIntPtr pDev, + ScreenPtr pScreen); + +static Bool miSpriteDeviceCursorInitialize(DeviceIntPtr pDev, + ScreenPtr pScreen); +static void miSpriteDeviceCursorCleanup(DeviceIntPtr pDev, + ScreenPtr pScreen); + +#define SCREEN_PROLOGUE(pPriv, pScreen, field) ((pScreen)->field = \ + (pPriv)->field) +#define SCREEN_EPILOGUE(pPriv, pScreen, field)\ + ((pPriv)->field = (pScreen)->field, (pScreen)->field = miSprite##field) + +/* + * pointer-sprite method table + */ + +static Bool miSpriteRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, + CursorPtr pCursor); +static Bool miSpriteUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, + CursorPtr pCursor); +static void miSpriteSetCursor(DeviceIntPtr pDev, ScreenPtr pScreen, + CursorPtr pCursor, int x, int y); +static void miSpriteMoveCursor(DeviceIntPtr pDev, ScreenPtr pScreen, + int x, int y); + +miPointerSpriteFuncRec miSpritePointerFuncs = { + miSpriteRealizeCursor, + miSpriteUnrealizeCursor, + miSpriteSetCursor, + miSpriteMoveCursor, + miSpriteDeviceCursorInitialize, + miSpriteDeviceCursorCleanup, +}; + +/* + * other misc functions + */ + +static void miSpriteRemoveCursor(DeviceIntPtr pDev, + ScreenPtr pScreen); +static void miSpriteSaveUnderCursor(DeviceIntPtr pDev, + ScreenPtr pScreen); +static void miSpriteRestoreCursor(DeviceIntPtr pDev, + ScreenPtr pScreen); + +static void +miSpriteRegisterBlockHandler(ScreenPtr pScreen, miSpriteScreenPtr pScreenPriv) +{ + if (!pScreenPriv->BlockHandler) { + pScreenPriv->BlockHandler = pScreen->BlockHandler; + pScreen->BlockHandler = miSpriteBlockHandler; + } +} + +static void +miSpriteReportDamage (DamagePtr pDamage, RegionPtr pRegion, void *closure) +{ + ScreenPtr pScreen = closure; + miCursorInfoPtr pCursorInfo; + DeviceIntPtr pDev; + + for (pDev = inputInfo.devices; pDev; pDev = pDev->next) + { + if (DevHasCursor(pDev)) + { + pCursorInfo = MISPRITE(pDev); + + if (pCursorInfo->isUp && + pCursorInfo->pScreen == pScreen && + RegionContainsRect(pRegion, &pCursorInfo->saved) != rgnOUT) + { + SPRITE_DEBUG(("Damage remove\n")); + miSpriteRemoveCursor (pDev, pScreen); + } + } + } +} + +/* + * miSpriteInitialize -- called from device-dependent screen + * initialization proc after all of the function pointers have + * been stored in the screen structure. + */ + +Bool +miSpriteInitialize (ScreenPtr pScreen, + miPointerScreenFuncPtr screenFuncs) +{ + miSpriteScreenPtr pScreenPriv; + VisualPtr pVisual; + + if (!DamageSetup (pScreen)) + return FALSE; + + if (!dixRegisterPrivateKey(&miSpriteScreenKeyRec, PRIVATE_SCREEN, 0)) + return FALSE; + + if (!dixRegisterPrivateKey(&miSpriteDevPrivatesKeyRec, PRIVATE_DEVICE, 0)) + return FALSE; + + pScreenPriv = malloc(sizeof (miSpriteScreenRec)); + if (!pScreenPriv) + return FALSE; + + pScreenPriv->pDamage = DamageCreate (miSpriteReportDamage, + NULL, + DamageReportRawRegion, + TRUE, + pScreen, + pScreen); + + if (!miPointerInitialize (pScreen, &miSpritePointerFuncs, screenFuncs,TRUE)) + { + free(pScreenPriv); + return FALSE; + } + for (pVisual = pScreen->visuals; + pVisual->vid != pScreen->rootVisual; + pVisual++) + ; + pScreenPriv->pVisual = pVisual; + pScreenPriv->CloseScreen = pScreen->CloseScreen; + pScreenPriv->GetImage = pScreen->GetImage; + pScreenPriv->GetSpans = pScreen->GetSpans; + pScreenPriv->SourceValidate = pScreen->SourceValidate; + + pScreenPriv->CopyWindow = pScreen->CopyWindow; + + pScreenPriv->InstallColormap = pScreen->InstallColormap; + pScreenPriv->StoreColors = pScreen->StoreColors; + + pScreenPriv->BlockHandler = NULL; + + pScreenPriv->DeviceCursorInitialize = pScreen->DeviceCursorInitialize; + pScreenPriv->DeviceCursorCleanup = pScreen->DeviceCursorCleanup; + + pScreenPriv->pInstalledMap = NULL; + pScreenPriv->pColormap = NULL; + pScreenPriv->colors[SOURCE_COLOR].red = 0; + pScreenPriv->colors[SOURCE_COLOR].green = 0; + pScreenPriv->colors[SOURCE_COLOR].blue = 0; + pScreenPriv->colors[MASK_COLOR].red = 0; + pScreenPriv->colors[MASK_COLOR].green = 0; + pScreenPriv->colors[MASK_COLOR].blue = 0; + pScreenPriv->damageRegistered = 0; + pScreenPriv->numberOfCursors = 0; + + dixSetPrivate(&pScreen->devPrivates, miSpriteScreenKey, pScreenPriv); + + pScreen->CloseScreen = miSpriteCloseScreen; + pScreen->GetImage = miSpriteGetImage; + pScreen->GetSpans = miSpriteGetSpans; + pScreen->SourceValidate = miSpriteSourceValidate; + + pScreen->CopyWindow = miSpriteCopyWindow; + pScreen->InstallColormap = miSpriteInstallColormap; + pScreen->StoreColors = miSpriteStoreColors; + + return TRUE; +} + +/* + * Screen wrappers + */ + +/* + * CloseScreen wrapper -- unwrap everything, free the private data + * and call the wrapped function + */ + +static Bool +miSpriteCloseScreen (int i, ScreenPtr pScreen) +{ + miSpriteScreenPtr pScreenPriv = GetSpriteScreen(pScreen); + + pScreen->CloseScreen = pScreenPriv->CloseScreen; + pScreen->GetImage = pScreenPriv->GetImage; + pScreen->GetSpans = pScreenPriv->GetSpans; + pScreen->SourceValidate = pScreenPriv->SourceValidate; + pScreen->InstallColormap = pScreenPriv->InstallColormap; + pScreen->StoreColors = pScreenPriv->StoreColors; + + DamageDestroy (pScreenPriv->pDamage); + + free(pScreenPriv); + + return (*pScreen->CloseScreen) (i, pScreen); +} + +static void +miSpriteGetImage (DrawablePtr pDrawable, int sx, int sy, int w, int h, + unsigned int format, unsigned long planemask, + char *pdstLine) +{ + ScreenPtr pScreen = pDrawable->pScreen; + DeviceIntPtr pDev; + miCursorInfoPtr pCursorInfo; + miSpriteScreenPtr pPriv = GetSpriteScreen(pScreen); + + SCREEN_PROLOGUE (pPriv, pScreen, GetImage); + + if (pDrawable->type == DRAWABLE_WINDOW) + { + for(pDev = inputInfo.devices; pDev; pDev = pDev->next) + { + if (DevHasCursor(pDev)) + { + pCursorInfo = MISPRITE(pDev); + if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen && + ORG_OVERLAP(&pCursorInfo->saved,pDrawable->x,pDrawable->y, + sx, sy, w, h)) + { + SPRITE_DEBUG (("GetImage remove\n")); + miSpriteRemoveCursor (pDev, pScreen); + } + } + } + } + + (*pScreen->GetImage) (pDrawable, sx, sy, w, h, + format, planemask, pdstLine); + + SCREEN_EPILOGUE (pPriv, pScreen, GetImage); +} + +static void +miSpriteGetSpans (DrawablePtr pDrawable, int wMax, DDXPointPtr ppt, + int *pwidth, int nspans, char *pdstStart) +{ + ScreenPtr pScreen = pDrawable->pScreen; + DeviceIntPtr pDev; + miCursorInfoPtr pCursorInfo; + miSpriteScreenPtr pPriv = GetSpriteScreen(pScreen); + + SCREEN_PROLOGUE (pPriv, pScreen, GetSpans); + + if (pDrawable->type == DRAWABLE_WINDOW) + { + for(pDev = inputInfo.devices; pDev; pDev = pDev->next) + { + if (DevHasCursor(pDev)) + { + pCursorInfo = MISPRITE(pDev); + + if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen) + { + DDXPointPtr pts; + int *widths; + int nPts; + int xorg, + yorg; + + xorg = pDrawable->x; + yorg = pDrawable->y; + + for (pts = ppt, widths = pwidth, nPts = nspans; + nPts--; + pts++, widths++) + { + if (SPN_OVERLAP(&pCursorInfo->saved,pts->y+yorg, + pts->x+xorg,*widths)) + { + SPRITE_DEBUG (("GetSpans remove\n")); + miSpriteRemoveCursor (pDev, pScreen); + break; + } + } + } + } + } + } + + (*pScreen->GetSpans) (pDrawable, wMax, ppt, pwidth, nspans, pdstStart); + + SCREEN_EPILOGUE (pPriv, pScreen, GetSpans); +} + +static void +miSpriteSourceValidate (DrawablePtr pDrawable, int x, int y, int width, + int height, unsigned int subWindowMode) +{ + ScreenPtr pScreen = pDrawable->pScreen; + DeviceIntPtr pDev; + miCursorInfoPtr pCursorInfo; + miSpriteScreenPtr pPriv = GetSpriteScreen(pScreen); + + SCREEN_PROLOGUE (pPriv, pScreen, SourceValidate); + + if (pDrawable->type == DRAWABLE_WINDOW) + { + for(pDev = inputInfo.devices; pDev; pDev = pDev->next) + { + if (DevHasCursor(pDev)) + { + pCursorInfo = MISPRITE(pDev); + if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen && + ORG_OVERLAP(&pCursorInfo->saved, pDrawable->x, pDrawable->y, + x, y, width, height)) + { + SPRITE_DEBUG (("SourceValidate remove\n")); + miSpriteRemoveCursor (pDev, pScreen); + } + } + } + } + + if (pScreen->SourceValidate) + (*pScreen->SourceValidate) (pDrawable, x, y, width, height, subWindowMode); + + SCREEN_EPILOGUE (pPriv, pScreen, SourceValidate); +} + +static void +miSpriteCopyWindow (WindowPtr pWindow, DDXPointRec ptOldOrg, RegionPtr prgnSrc) +{ + ScreenPtr pScreen = pWindow->drawable.pScreen; + DeviceIntPtr pDev; + miCursorInfoPtr pCursorInfo; + miSpriteScreenPtr pPriv = GetSpriteScreen(pScreen); + + SCREEN_PROLOGUE (pPriv, pScreen, CopyWindow); + + for(pDev = inputInfo.devices; pDev; pDev = pDev->next) + { + if (DevHasCursor(pDev)) + { + pCursorInfo = MISPRITE(pDev); + /* + * Damage will take care of destination check + */ + if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen && + RegionContainsRect(prgnSrc, &pCursorInfo->saved) != rgnOUT) + { + SPRITE_DEBUG (("CopyWindow remove\n")); + miSpriteRemoveCursor (pDev, pScreen); + } + } + } + + (*pScreen->CopyWindow) (pWindow, ptOldOrg, prgnSrc); + SCREEN_EPILOGUE (pPriv, pScreen, CopyWindow); +} + +static void +miSpriteBlockHandler (int i, pointer blockData, pointer pTimeout, + pointer pReadmask) +{ + ScreenPtr pScreen = screenInfo.screens[i]; + miSpriteScreenPtr pPriv = GetSpriteScreen(pScreen); + DeviceIntPtr pDev; + miCursorInfoPtr pCursorInfo; + Bool WorkToDo = FALSE; + + for(pDev = inputInfo.devices; pDev; pDev = pDev->next) + { + if (DevHasCursor(pDev)) + { + pCursorInfo = MISPRITE(pDev); + if (pCursorInfo && !pCursorInfo->isUp + && pCursorInfo->pScreen == pScreen + && pCursorInfo->shouldBeUp) + { + SPRITE_DEBUG (("BlockHandler save")); + miSpriteSaveUnderCursor (pDev, pScreen); + } + } + } + for(pDev = inputInfo.devices; pDev; pDev = pDev->next) + { + if (DevHasCursor(pDev)) + { + pCursorInfo = MISPRITE(pDev); + if (pCursorInfo && !pCursorInfo->isUp && + pCursorInfo->pScreen == pScreen && + pCursorInfo->shouldBeUp) + { + SPRITE_DEBUG (("BlockHandler restore\n")); + miSpriteRestoreCursor (pDev, pScreen); + if (!pCursorInfo->isUp) + WorkToDo = TRUE; + } + } + } + + SCREEN_PROLOGUE(pPriv, pScreen, BlockHandler); + + (*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask); + + if (WorkToDo) + SCREEN_EPILOGUE(pPriv, pScreen, BlockHandler); + else + pPriv->BlockHandler = NULL; +} + +static void +miSpriteInstallColormap (ColormapPtr pMap) +{ + ScreenPtr pScreen = pMap->pScreen; + miSpriteScreenPtr pPriv = GetSpriteScreen(pScreen); + + SCREEN_PROLOGUE(pPriv, pScreen, InstallColormap); + + (*pScreen->InstallColormap) (pMap); + + SCREEN_EPILOGUE(pPriv, pScreen, InstallColormap); + + /* InstallColormap can be called before devices are initialized. */ + pPriv->pInstalledMap = pMap; + if (pPriv->pColormap != pMap) + { + DeviceIntPtr pDev; + miCursorInfoPtr pCursorInfo; + for (pDev = inputInfo.devices; pDev; pDev = pDev->next) + { + if (DevHasCursor(pDev)) + { + pCursorInfo = MISPRITE(pDev); + pCursorInfo->checkPixels = TRUE; + if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen) + miSpriteRemoveCursor(pDev, pScreen); + } + } + + } +} + +static void +miSpriteStoreColors (ColormapPtr pMap, int ndef, xColorItem *pdef) +{ + ScreenPtr pScreen = pMap->pScreen; + miSpriteScreenPtr pPriv = GetSpriteScreen(pScreen); + int i; + int updated; + VisualPtr pVisual; + DeviceIntPtr pDev; + miCursorInfoPtr pCursorInfo; + + SCREEN_PROLOGUE(pPriv, pScreen, StoreColors); + + (*pScreen->StoreColors) (pMap, ndef, pdef); + + SCREEN_EPILOGUE(pPriv, pScreen, StoreColors); + + if (pPriv->pColormap == pMap) + { + updated = 0; + pVisual = pMap->pVisual; + if (pVisual->class == DirectColor) + { + /* Direct color - match on any of the subfields */ + +#define MaskMatch(a,b,mask) (((a) & (pVisual->mask)) == ((b) & (pVisual->mask))) + +#define UpdateDAC(dev, plane,dac,mask) {\ + if (MaskMatch (dev->colors[plane].pixel,pdef[i].pixel,mask)) {\ + dev->colors[plane].dac = pdef[i].dac; \ + updated = 1; \ + } \ +} + +#define CheckDirect(dev, plane) \ + UpdateDAC(dev, plane,red,redMask) \ + UpdateDAC(dev, plane,green,greenMask) \ + UpdateDAC(dev, plane,blue,blueMask) + + for (i = 0; i < ndef; i++) + { + CheckDirect (pPriv, SOURCE_COLOR) + CheckDirect (pPriv, MASK_COLOR) + } + } + else + { + /* PseudoColor/GrayScale - match on exact pixel */ + for (i = 0; i < ndef; i++) + { + if (pdef[i].pixel == + pPriv->colors[SOURCE_COLOR].pixel) + { + pPriv->colors[SOURCE_COLOR] = pdef[i]; + if (++updated == 2) + break; + } + if (pdef[i].pixel == + pPriv->colors[MASK_COLOR].pixel) + { + pPriv->colors[MASK_COLOR] = pdef[i]; + if (++updated == 2) + break; + } + } + } + if (updated) + { + for(pDev = inputInfo.devices; pDev; pDev = pDev->next) + { + if (DevHasCursor(pDev)) + { + pCursorInfo = MISPRITE(pDev); + pCursorInfo->checkPixels = TRUE; + if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen) + miSpriteRemoveCursor (pDev, pScreen); + } + } + } + } +} + +static void +miSpriteFindColors (miCursorInfoPtr pDevCursor, ScreenPtr pScreen) +{ + miSpriteScreenPtr pScreenPriv = GetSpriteScreen(pScreen); + CursorPtr pCursor; + xColorItem *sourceColor, *maskColor; + + pCursor = pDevCursor->pCursor; + sourceColor = &pScreenPriv->colors[SOURCE_COLOR]; + maskColor = &pScreenPriv->colors[MASK_COLOR]; + if (pScreenPriv->pColormap != pScreenPriv->pInstalledMap || + !(pCursor->foreRed == sourceColor->red && + pCursor->foreGreen == sourceColor->green && + pCursor->foreBlue == sourceColor->blue && + pCursor->backRed == maskColor->red && + pCursor->backGreen == maskColor->green && + pCursor->backBlue == maskColor->blue)) + { + pScreenPriv->pColormap = pScreenPriv->pInstalledMap; + sourceColor->red = pCursor->foreRed; + sourceColor->green = pCursor->foreGreen; + sourceColor->blue = pCursor->foreBlue; + FakeAllocColor (pScreenPriv->pColormap, sourceColor); + maskColor->red = pCursor->backRed; + maskColor->green = pCursor->backGreen; + maskColor->blue = pCursor->backBlue; + FakeAllocColor (pScreenPriv->pColormap, maskColor); + /* "free" the pixels right away, don't let this confuse you */ + FakeFreeColor(pScreenPriv->pColormap, sourceColor->pixel); + FakeFreeColor(pScreenPriv->pColormap, maskColor->pixel); + } + + pDevCursor->checkPixels = FALSE; + +} + +/* + * miPointer interface routines + */ + +#define SPRITE_PAD 8 + +static Bool +miSpriteRealizeCursor (DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor) +{ + miCursorInfoPtr pCursorInfo; + + if (IsFloating(pDev)) + return FALSE; + + pCursorInfo = MISPRITE(pDev); + + if (pCursor == pCursorInfo->pCursor) + pCursorInfo->checkPixels = TRUE; + + return miDCRealizeCursor(pScreen, pCursor); +} + +static Bool +miSpriteUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor) +{ + return miDCUnrealizeCursor(pScreen, pCursor); +} + +static void +miSpriteSetCursor (DeviceIntPtr pDev, ScreenPtr pScreen, + CursorPtr pCursor, int x, int y) +{ + miCursorInfoPtr pPointer; + miSpriteScreenPtr pScreenPriv; + + if (IsFloating(pDev)) + return; + + pPointer = MISPRITE(pDev); + pScreenPriv = GetSpriteScreen(pScreen); + + if (!pCursor) + { + if (pPointer->shouldBeUp) + --pScreenPriv->numberOfCursors; + pPointer->shouldBeUp = FALSE; + if (pPointer->isUp) + miSpriteRemoveCursor (pDev, pScreen); + if (pScreenPriv->numberOfCursors == 0) + miSpriteDisableDamage(pScreen, pScreenPriv); + pPointer->pCursor = 0; + return; + } + if (!pPointer->shouldBeUp) + pScreenPriv->numberOfCursors++; + pPointer->shouldBeUp = TRUE; + if (!pPointer->isUp) + miSpriteRegisterBlockHandler(pScreen, pScreenPriv); + if (pPointer->x == x && + pPointer->y == y && + pPointer->pCursor == pCursor && + !pPointer->checkPixels) + { + return; + } + pPointer->x = x; + pPointer->y = y; + pPointer->pCacheWin = NullWindow; + if (pPointer->checkPixels || pPointer->pCursor != pCursor) + { + pPointer->pCursor = pCursor; + miSpriteFindColors (pPointer, pScreen); + } + if (pPointer->isUp) { + /* TODO: reimplement flicker-free MoveCursor */ + SPRITE_DEBUG (("SetCursor remove %d\n", pDev->id)); + miSpriteRemoveCursor (pDev, pScreen); + } + + if (!pPointer->isUp && pPointer->pCursor) + { + SPRITE_DEBUG (("SetCursor restore %d\n", pDev->id)); + miSpriteSaveUnderCursor(pDev, pScreen); + miSpriteRestoreCursor (pDev, pScreen); + } + +} + +static void +miSpriteMoveCursor (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y) +{ + CursorPtr pCursor; + + if (IsFloating(pDev)) + return; + + pCursor = MISPRITE(pDev)->pCursor; + + miSpriteSetCursor (pDev, pScreen, pCursor, x, y); +} + + +static Bool +miSpriteDeviceCursorInitialize(DeviceIntPtr pDev, ScreenPtr pScreen) +{ + miCursorInfoPtr pCursorInfo; + int ret = FALSE; + + pCursorInfo = malloc(sizeof(miCursorInfoRec)); + if (!pCursorInfo) + return FALSE; + + pCursorInfo->pCursor = NULL; + pCursorInfo->x = 0; + pCursorInfo->y = 0; + pCursorInfo->isUp = FALSE; + pCursorInfo->shouldBeUp = FALSE; + pCursorInfo->pCacheWin = NullWindow; + pCursorInfo->isInCacheWin = FALSE; + pCursorInfo->checkPixels = TRUE; + pCursorInfo->pScreen = FALSE; + + ret = miDCDeviceInitialize(pDev, pScreen); + if (!ret) + { + free(pCursorInfo); + pCursorInfo = NULL; + } + dixSetPrivate(&pDev->devPrivates, miSpriteDevPrivatesKey, pCursorInfo); + return ret; +} + +static void +miSpriteDeviceCursorCleanup(DeviceIntPtr pDev, ScreenPtr pScreen) +{ + if (DevHasCursor(pDev)) + miDCDeviceCleanup(pDev, pScreen); +} + +/* + * undraw/draw cursor + */ + +static void +miSpriteRemoveCursor (DeviceIntPtr pDev, ScreenPtr pScreen) +{ + miSpriteScreenPtr pScreenPriv; + miCursorInfoPtr pCursorInfo; + + + if (IsFloating(pDev)) + return; + + DamageDrawInternal (pScreen, TRUE); + pScreenPriv = GetSpriteScreen(pScreen); + pCursorInfo = MISPRITE(pDev); + + miSpriteIsDown(pCursorInfo); + miSpriteRegisterBlockHandler(pScreen, pScreenPriv); + pCursorInfo->pCacheWin = NullWindow; + miSpriteDisableDamage(pScreen, pScreenPriv); + if (!miDCRestoreUnderCursor(pDev, + pScreen, + pCursorInfo->saved.x1, + pCursorInfo->saved.y1, + pCursorInfo->saved.x2 - + pCursorInfo->saved.x1, + pCursorInfo->saved.y2 - + pCursorInfo->saved.y1)) + { + miSpriteIsUp(pCursorInfo); + } + miSpriteEnableDamage(pScreen, pScreenPriv); + DamageDrawInternal (pScreen, FALSE); +} + +/* + * Called from the block handler, saves area under cursor + * before waiting for something to do. + */ + +static void +miSpriteSaveUnderCursor(DeviceIntPtr pDev, ScreenPtr pScreen) +{ + miSpriteScreenPtr pScreenPriv; + int x, y; + CursorPtr pCursor; + miCursorInfoPtr pCursorInfo; + + if (IsFloating(pDev)) + return; + + DamageDrawInternal (pScreen, TRUE); + pScreenPriv = GetSpriteScreen(pScreen); + pCursorInfo = MISPRITE(pDev); + + miSpriteComputeSaved (pDev, pScreen); + pCursor = pCursorInfo->pCursor; + + x = pCursorInfo->x - (int)pCursor->bits->xhot; + y = pCursorInfo->y - (int)pCursor->bits->yhot; + miSpriteDisableDamage(pScreen, pScreenPriv); + + miDCSaveUnderCursor(pDev, + pScreen, + pCursorInfo->saved.x1, + pCursorInfo->saved.y1, + pCursorInfo->saved.x2 - + pCursorInfo->saved.x1, + pCursorInfo->saved.y2 - + pCursorInfo->saved.y1); + SPRITE_DEBUG(("SaveUnderCursor %d\n", pDev->id)); + miSpriteEnableDamage(pScreen, pScreenPriv); + DamageDrawInternal (pScreen, FALSE); +} + + +/* + * Called from the block handler, restores the cursor + * before waiting for something to do. + */ + +static void +miSpriteRestoreCursor (DeviceIntPtr pDev, ScreenPtr pScreen) +{ + miSpriteScreenPtr pScreenPriv; + int x, y; + CursorPtr pCursor; + miCursorInfoPtr pCursorInfo; + + if (IsFloating(pDev)) + return; + + DamageDrawInternal (pScreen, TRUE); + pScreenPriv = GetSpriteScreen(pScreen); + pCursorInfo = MISPRITE(pDev); + + miSpriteComputeSaved (pDev, pScreen); + pCursor = pCursorInfo->pCursor; + + x = pCursorInfo->x - (int)pCursor->bits->xhot; + y = pCursorInfo->y - (int)pCursor->bits->yhot; + miSpriteDisableDamage(pScreen, pScreenPriv); + SPRITE_DEBUG(("RestoreCursor %d\n", pDev->id)); + if (pCursorInfo->checkPixels) + miSpriteFindColors (pCursorInfo, pScreen); + if (miDCPutUpCursor(pDev, pScreen, + pCursor, x, y, + pScreenPriv->colors[SOURCE_COLOR].pixel, + pScreenPriv->colors[MASK_COLOR].pixel)) + { + miSpriteIsUp(pCursorInfo); + pCursorInfo->pScreen = pScreen; + } + miSpriteEnableDamage(pScreen, pScreenPriv); + DamageDrawInternal (pScreen, FALSE); +} + +/* + * compute the desired area of the screen to save + */ + +static void +miSpriteComputeSaved (DeviceIntPtr pDev, ScreenPtr pScreen) +{ + int x, y, w, h; + int wpad, hpad; + CursorPtr pCursor; + miCursorInfoPtr pCursorInfo; + + if (IsFloating(pDev)) + return; + + pCursorInfo = MISPRITE(pDev); + + pCursor = pCursorInfo->pCursor; + x = pCursorInfo->x - (int)pCursor->bits->xhot; + y = pCursorInfo->y - (int)pCursor->bits->yhot; + w = pCursor->bits->width; + h = pCursor->bits->height; + wpad = SPRITE_PAD; + hpad = SPRITE_PAD; + pCursorInfo->saved.x1 = x - wpad; + pCursorInfo->saved.y1 = y - hpad; + pCursorInfo->saved.x2 = pCursorInfo->saved.x1 + w + wpad * 2; + pCursorInfo->saved.y2 = pCursorInfo->saved.y1 + h + hpad * 2; +} + diff --git a/xorg-server/miext/damage/damage.c b/xorg-server/miext/damage/damage.c index 0d5fab5bd..0fe1fb603 100644 --- a/xorg-server/miext/damage/damage.c +++ b/xorg-server/miext/damage/damage.c @@ -1,2123 +1,2127 @@ -/*
- * Copyright © 2003 Keith Packard
- *
- * Permission to use, copy, modify, distribute, and sell this software and its
- * documentation for any purpose is hereby granted without fee, provided that
- * the above copyright notice appear in all copies and that both that
- * copyright notice and this permission notice appear in supporting
- * documentation, and that the name of Keith Packard not be used in
- * advertising or publicity pertaining to distribution of the software without
- * specific, written prior permission. Keith Packard makes no
- * representations about the suitability of this software for any purpose. It
- * is provided "as is" without express or implied warranty.
- *
- * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
- * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
- * CONSEQUENTIAL DAMAGES OR ANY 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 THIS SOFTWARE.
- */
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#include <stdlib.h>
-
-#include <X11/X.h>
-#include "scrnintstr.h"
-#include "windowstr.h"
-#include <X11/fonts/font.h>
-#include "dixfontstr.h"
-#include <X11/fonts/fontstruct.h>
-#include "mi.h"
-#include "regionstr.h"
-#include "globals.h"
-#include "gcstruct.h"
-#include "damage.h"
-#include "damagestr.h"
-#ifdef COMPOSITE
-#include "cw.h"
-#endif
-
-#define wrap(priv, real, mem, func) {\
- priv->mem = real->mem; \
- real->mem = func; \
-}
-
-#define unwrap(priv, real, mem) {\
- real->mem = priv->mem; \
-}
-
-#define BOX_SAME(a,b) \
- ((a)->x1 == (b)->x1 && \
- (a)->y1 == (b)->y1 && \
- (a)->x2 == (b)->x2 && \
- (a)->y2 == (b)->y2)
-
-#define DAMAGE_VALIDATE_ENABLE 0
-#define DAMAGE_DEBUG_ENABLE 0
-#if DAMAGE_DEBUG_ENABLE
-#define DAMAGE_DEBUG(x) ErrorF x
-#else
-#define DAMAGE_DEBUG(x)
-#endif
-
-#define getPixmapDamageRef(pPixmap) ((DamagePtr *) \
- dixLookupPrivateAddr(&(pPixmap)->devPrivates, damagePixPrivateKey))
-
-#define pixmapDamage(pPixmap) damagePixPriv(pPixmap)
-
-static DevPrivateKeyRec damageScrPrivateKeyRec;
-#define damageScrPrivateKey (&damageScrPrivateKeyRec)
-static DevPrivateKeyRec damagePixPrivateKeyRec;
-#define damagePixPrivateKey (&damagePixPrivateKeyRec)
-static DevPrivateKeyRec damageGCPrivateKeyRec;
-#define damageGCPrivateKey (&damageGCPrivateKeyRec)
-static DevPrivateKeyRec damageWinPrivateKeyRec;
-#define damageWinPrivateKey (&damageWinPrivateKeyRec)
-
-static DamagePtr *
-getDrawableDamageRef (DrawablePtr pDrawable)
-{
- PixmapPtr pPixmap;
-
- if (WindowDrawable(pDrawable->type))
- {
- ScreenPtr pScreen = pDrawable->pScreen;
-
- pPixmap = 0;
- if (pScreen->GetWindowPixmap)
- pPixmap = (*pScreen->GetWindowPixmap) ((WindowPtr)pDrawable);
-
- if (!pPixmap)
- {
- damageScrPriv(pScreen);
-
- return &pScrPriv->pScreenDamage;
- }
- }
- else
- pPixmap = (PixmapPtr) pDrawable;
- return getPixmapDamageRef (pPixmap);
-}
-
-#define getDrawableDamage(pDrawable) (*getDrawableDamageRef (pDrawable))
-#define getWindowDamage(pWin) getDrawableDamage(&(pWin)->drawable)
-
-#define drawableDamage(pDrawable) \
- DamagePtr pDamage = getDrawableDamage(pDrawable)
-
-#define windowDamage(pWin) drawableDamage(&(pWin)->drawable)
-
-#define winDamageRef(pWindow) \
- DamagePtr *pPrev = (DamagePtr *) \
- dixLookupPrivateAddr(&(pWindow)->devPrivates, damageWinPrivateKey)
-
-static void
-damageReportDamage (DamagePtr pDamage, RegionPtr pDamageRegion)
-{
- BoxRec tmpBox;
- RegionRec tmpRegion;
- Bool was_empty;
-
- switch (pDamage->damageLevel) {
- case DamageReportRawRegion:
- RegionUnion(&pDamage->damage, &pDamage->damage,
- pDamageRegion);
- (*pDamage->damageReport) (pDamage, pDamageRegion, pDamage->closure);
- break;
- case DamageReportDeltaRegion:
- RegionNull(&tmpRegion);
- RegionSubtract(&tmpRegion, pDamageRegion, &pDamage->damage);
- if (RegionNotEmpty(&tmpRegion)) {
- RegionUnion(&pDamage->damage, &pDamage->damage,
- pDamageRegion);
- (*pDamage->damageReport) (pDamage, &tmpRegion, pDamage->closure);
- }
- RegionUninit(&tmpRegion);
- break;
- case DamageReportBoundingBox:
- tmpBox = *RegionExtents(&pDamage->damage);
- RegionUnion(&pDamage->damage, &pDamage->damage,
- pDamageRegion);
- if (!BOX_SAME (&tmpBox, RegionExtents(&pDamage->damage))) {
- (*pDamage->damageReport) (pDamage, &pDamage->damage,
- pDamage->closure);
- }
- break;
- case DamageReportNonEmpty:
- was_empty = !RegionNotEmpty(&pDamage->damage);
- RegionUnion(&pDamage->damage, &pDamage->damage,
- pDamageRegion);
- if (was_empty && RegionNotEmpty(&pDamage->damage)) {
- (*pDamage->damageReport) (pDamage, &pDamage->damage,
- pDamage->closure);
- }
- break;
- case DamageReportNone:
- RegionUnion(&pDamage->damage, &pDamage->damage,
- pDamageRegion);
- break;
- }
-}
-
-static void
-damageReportDamagePostRendering (DamagePtr pDamage, RegionPtr pOldDamage, RegionPtr pDamageRegion)
-{
- BoxRec tmpBox;
- RegionRec tmpRegion, newDamage;
- Bool was_empty;
-
- RegionUnion(&newDamage, pOldDamage, pDamageRegion);
-
- switch (pDamage->damageLevel) {
- case DamageReportRawRegion:
- (*pDamage->damageReportPostRendering) (pDamage, pDamageRegion, pDamage->closure);
- break;
- case DamageReportDeltaRegion:
- RegionNull(&tmpRegion);
- RegionSubtract(&tmpRegion, pDamageRegion, pOldDamage);
- if (RegionNotEmpty(&tmpRegion)) {
- (*pDamage->damageReportPostRendering) (pDamage, &tmpRegion, pDamage->closure);
- }
- RegionUninit(&tmpRegion);
- break;
- case DamageReportBoundingBox:
- tmpBox = *RegionExtents(pOldDamage);
- if (!BOX_SAME (&tmpBox, RegionExtents(&newDamage))) {
- (*pDamage->damageReportPostRendering) (pDamage, &newDamage,
- pDamage->closure);
- }
- break;
- case DamageReportNonEmpty:
- was_empty = !RegionNotEmpty(pOldDamage);
- if (was_empty && RegionNotEmpty(&newDamage)) {
- (*pDamage->damageReportPostRendering) (pDamage, &newDamage,
- pDamage->closure);
- }
- break;
- case DamageReportNone:
- break;
- }
-
- RegionUninit(&newDamage);
-}
-
-#if DAMAGE_DEBUG_ENABLE
-static void
-_damageRegionAppend (DrawablePtr pDrawable, RegionPtr pRegion, Bool clip, int subWindowMode, const char *where)
-#define damageRegionAppend(d,r,c,m) _damageRegionAppend(d,r,c,m,__FUNCTION__)
-#else
-static void
-damageRegionAppend (DrawablePtr pDrawable, RegionPtr pRegion, Bool clip,
- int subWindowMode)
-#endif
-{
- ScreenPtr pScreen = pDrawable->pScreen;
- damageScrPriv(pScreen);
- drawableDamage(pDrawable);
- DamagePtr pNext;
- RegionRec clippedRec;
- RegionPtr pDamageRegion;
- RegionRec pixClip;
- int draw_x, draw_y;
-#ifdef COMPOSITE
- int screen_x = 0, screen_y = 0;
-#endif
-
- /* short circuit for empty regions */
- if (!RegionNotEmpty(pRegion))
- return;
-
-#ifdef COMPOSITE
- /*
- * When drawing to a pixmap which is storing window contents,
- * the region presented is in pixmap relative coordinates which
- * need to be converted to screen relative coordinates
- */
- if (pDrawable->type != DRAWABLE_WINDOW)
- {
- screen_x = ((PixmapPtr) pDrawable)->screen_x - pDrawable->x;
- screen_y = ((PixmapPtr) pDrawable)->screen_y - pDrawable->y;
- }
- if (screen_x || screen_y)
- RegionTranslate(pRegion, screen_x, screen_y);
-#endif
-
- if (pDrawable->type == DRAWABLE_WINDOW &&
- ((WindowPtr)(pDrawable))->backingStore == NotUseful)
- {
- if (subWindowMode == ClipByChildren)
- {
- RegionIntersect(pRegion, pRegion,
- &((WindowPtr)(pDrawable))->clipList);
- }
- else if (subWindowMode == IncludeInferiors)
- {
- RegionPtr pTempRegion =
- NotClippedByChildren((WindowPtr)(pDrawable));
- RegionIntersect(pRegion, pRegion, pTempRegion);
- RegionDestroy(pTempRegion);
- }
- /* If subWindowMode is set to an invalid value, don't perform
- * any drawable-based clipping. */
- }
-
-
- RegionNull(&clippedRec);
- for (; pDamage; pDamage = pNext)
- {
- pNext = pDamage->pNext;
- /*
- * Check for internal damage and don't send events
- */
- if (pScrPriv->internalLevel > 0 && !pDamage->isInternal)
- {
- DAMAGE_DEBUG (("non internal damage, skipping at %d\n",
- pScrPriv->internalLevel));
- continue;
- }
- /*
- * Check for unrealized windows
- */
- if (pDamage->pDrawable->type == DRAWABLE_WINDOW &&
- !((WindowPtr) (pDamage->pDrawable))->realized)
- {
- continue;
- }
-
- draw_x = pDamage->pDrawable->x;
- draw_y = pDamage->pDrawable->y;
-#ifdef COMPOSITE
- /*
- * Need to move everyone to screen coordinates
- * XXX what about off-screen pixmaps with non-zero x/y?
- */
- if (!WindowDrawable(pDamage->pDrawable->type))
- {
- draw_x += ((PixmapPtr) pDamage->pDrawable)->screen_x;
- draw_y += ((PixmapPtr) pDamage->pDrawable)->screen_y;
- }
-#endif
-
- /*
- * Clip against border or pixmap bounds
- */
-
- pDamageRegion = pRegion;
- if (clip || pDamage->pDrawable != pDrawable)
- {
- pDamageRegion = &clippedRec;
- if (pDamage->pDrawable->type == DRAWABLE_WINDOW) {
- RegionIntersect(pDamageRegion, pRegion,
- &((WindowPtr)(pDamage->pDrawable))->borderClip);
- } else {
- BoxRec box;
- box.x1 = draw_x;
- box.y1 = draw_y;
- box.x2 = draw_x + pDamage->pDrawable->width;
- box.y2 = draw_y + pDamage->pDrawable->height;
- RegionInit(&pixClip, &box, 1);
- RegionIntersect(pDamageRegion, pRegion, &pixClip);
- RegionUninit(&pixClip);
- }
- /*
- * Short circuit empty results
- */
- if (!RegionNotEmpty(pDamageRegion))
- continue;
- }
-
- DAMAGE_DEBUG (("%s %d x %d +%d +%d (target 0x%lx monitor 0x%lx)\n",
- where,
- pDamageRegion->extents.x2 - pDamageRegion->extents.x1,
- pDamageRegion->extents.y2 - pDamageRegion->extents.y1,
- pDamageRegion->extents.x1, pDamageRegion->extents.y1,
- pDrawable->id, pDamage->pDrawable->id));
-
- /*
- * Move region to target coordinate space
- */
- if (draw_x || draw_y)
- RegionTranslate(pDamageRegion, -draw_x, -draw_y);
-
- /* Store damage region if needed after submission. */
- if (pDamage->reportAfter || pDamage->damageMarker)
- RegionUnion(&pDamage->pendingDamage,
- &pDamage->pendingDamage, pDamageRegion);
-
- /* Duplicate current damage if needed. */
- if (pDamage->damageMarker)
- RegionCopy(&pDamage->backupDamage, &pDamage->damage);
-
- /* Report damage now, if desired. */
- if (!pDamage->reportAfter) {
- if (pDamage->damageReport)
- damageReportDamage (pDamage, pDamageRegion);
- else
- RegionUnion(&pDamage->damage,
- &pDamage->damage, pDamageRegion);
- }
-
- /*
- * translate original region back
- */
- if (pDamageRegion == pRegion && (draw_x || draw_y))
- RegionTranslate(pDamageRegion, draw_x, draw_y);
- }
-#ifdef COMPOSITE
- if (screen_x || screen_y)
- RegionTranslate(pRegion, -screen_x, -screen_y);
-#endif
-
- RegionUninit(&clippedRec);
-}
-
-static void
-damageRegionProcessPending (DrawablePtr pDrawable)
-{
- drawableDamage(pDrawable);
-
- for (; pDamage != NULL; pDamage = pDamage->pNext)
- {
- /* submit damage marker whenever possible. */
- if (pDamage->damageMarker)
- (*pDamage->damageMarker) (pDrawable, pDamage, &pDamage->backupDamage, &pDamage->pendingDamage, pDamage->closure);
- if (pDamage->reportAfter) {
- /* It's possible that there is only interest in postRendering reporting. */
- if (pDamage->damageReport)
- damageReportDamage (pDamage, &pDamage->pendingDamage);
- else
- RegionUnion(&pDamage->damage, &pDamage->damage,
- &pDamage->pendingDamage);
- }
-
- if (pDamage->reportAfter || pDamage->damageMarker)
- RegionEmpty(&pDamage->pendingDamage);
- if (pDamage->damageMarker)
- RegionEmpty(&pDamage->backupDamage);
- }
-
-}
-
-#if DAMAGE_DEBUG_ENABLE
-#define damageDamageBox(d,b,m) _damageDamageBox(d,b,m,__FUNCTION__)
-static void
-_damageDamageBox (DrawablePtr pDrawable, BoxPtr pBox, int subWindowMode, const char *where)
-#else
-static void
-damageDamageBox (DrawablePtr pDrawable, BoxPtr pBox, int subWindowMode)
-#endif
-{
- RegionRec region;
-
- RegionInit(®ion, pBox, 1);
-#if DAMAGE_DEBUG_ENABLE
- _damageRegionAppend (pDrawable, ®ion, TRUE, subWindowMode, where);
-#else
- damageRegionAppend (pDrawable, ®ion, TRUE, subWindowMode);
-#endif
- RegionUninit(®ion);
-}
-
-static void damageValidateGC(GCPtr, unsigned long, DrawablePtr);
-static void damageChangeGC(GCPtr, unsigned long);
-static void damageCopyGC(GCPtr, unsigned long, GCPtr);
-static void damageDestroyGC(GCPtr);
-static void damageChangeClip(GCPtr, int, pointer, int);
-static void damageDestroyClip(GCPtr);
-static void damageCopyClip(GCPtr, GCPtr);
-
-static GCFuncs damageGCFuncs = {
- damageValidateGC, damageChangeGC, damageCopyGC, damageDestroyGC,
- damageChangeClip, damageDestroyClip, damageCopyClip
-};
-
-static GCOps damageGCOps;
-
-static Bool
-damageCreateGC(GCPtr pGC)
-{
- ScreenPtr pScreen = pGC->pScreen;
- damageScrPriv(pScreen);
- damageGCPriv(pGC);
- Bool ret;
-
- unwrap (pScrPriv, pScreen, CreateGC);
- if((ret = (*pScreen->CreateGC) (pGC))) {
- pGCPriv->ops = NULL;
- pGCPriv->funcs = pGC->funcs;
- pGC->funcs = &damageGCFuncs;
- }
- wrap (pScrPriv, pScreen, CreateGC, damageCreateGC);
-
- return ret;
-}
-
-#define DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable) \
- damageGCPriv(pGC); \
- GCFuncs *oldFuncs = pGC->funcs; \
- unwrap(pGCPriv, pGC, funcs); \
- unwrap(pGCPriv, pGC, ops); \
-
-#define DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable) \
- wrap(pGCPriv, pGC, funcs, oldFuncs); \
- wrap(pGCPriv, pGC, ops, &damageGCOps)
-
-#define DAMAGE_GC_FUNC_PROLOGUE(pGC) \
- damageGCPriv(pGC); \
- unwrap(pGCPriv, pGC, funcs); \
- if (pGCPriv->ops) unwrap(pGCPriv, pGC, ops)
-
-#define DAMAGE_GC_FUNC_EPILOGUE(pGC) \
- wrap(pGCPriv, pGC, funcs, &damageGCFuncs); \
- if (pGCPriv->ops) wrap(pGCPriv, pGC, ops, &damageGCOps)
-
-static void
-damageValidateGC(GCPtr pGC,
- unsigned long changes,
- DrawablePtr pDrawable)
-{
- DAMAGE_GC_FUNC_PROLOGUE (pGC);
- (*pGC->funcs->ValidateGC)(pGC, changes, pDrawable);
- pGCPriv->ops = pGC->ops; /* just so it's not NULL */
- DAMAGE_GC_FUNC_EPILOGUE (pGC);
-}
-
-static void
-damageDestroyGC(GCPtr pGC)
-{
- DAMAGE_GC_FUNC_PROLOGUE (pGC);
- (*pGC->funcs->DestroyGC)(pGC);
- DAMAGE_GC_FUNC_EPILOGUE (pGC);
-}
-
-static void
-damageChangeGC (GCPtr pGC,
- unsigned long mask)
-{
- DAMAGE_GC_FUNC_PROLOGUE (pGC);
- (*pGC->funcs->ChangeGC) (pGC, mask);
- DAMAGE_GC_FUNC_EPILOGUE (pGC);
-}
-
-static void
-damageCopyGC (GCPtr pGCSrc,
- unsigned long mask,
- GCPtr pGCDst)
-{
- DAMAGE_GC_FUNC_PROLOGUE (pGCDst);
- (*pGCDst->funcs->CopyGC) (pGCSrc, mask, pGCDst);
- DAMAGE_GC_FUNC_EPILOGUE (pGCDst);
-}
-
-static void
-damageChangeClip (GCPtr pGC,
- int type,
- pointer pvalue,
- int nrects)
-{
- DAMAGE_GC_FUNC_PROLOGUE (pGC);
- (*pGC->funcs->ChangeClip) (pGC, type, pvalue, nrects);
- DAMAGE_GC_FUNC_EPILOGUE (pGC);
-}
-
-static void
-damageCopyClip(GCPtr pgcDst, GCPtr pgcSrc)
-{
- DAMAGE_GC_FUNC_PROLOGUE (pgcDst);
- (* pgcDst->funcs->CopyClip)(pgcDst, pgcSrc);
- DAMAGE_GC_FUNC_EPILOGUE (pgcDst);
-}
-
-static void
-damageDestroyClip(GCPtr pGC)
-{
- DAMAGE_GC_FUNC_PROLOGUE (pGC);
- (* pGC->funcs->DestroyClip)(pGC);
- DAMAGE_GC_FUNC_EPILOGUE (pGC);
-}
-
-#define TRIM_BOX(box, pGC) if (pGC->pCompositeClip) { \
- BoxPtr extents = &pGC->pCompositeClip->extents;\
- if(box.x1 < extents->x1) box.x1 = extents->x1; \
- if(box.x2 > extents->x2) box.x2 = extents->x2; \
- if(box.y1 < extents->y1) box.y1 = extents->y1; \
- if(box.y2 > extents->y2) box.y2 = extents->y2; \
- }
-
-#define TRANSLATE_BOX(box, pDrawable) { \
- box.x1 += pDrawable->x; \
- box.x2 += pDrawable->x; \
- box.y1 += pDrawable->y; \
- box.y2 += pDrawable->y; \
- }
-
-#define TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC) { \
- TRANSLATE_BOX(box, pDrawable); \
- TRIM_BOX(box, pGC); \
- }
-
-#define BOX_NOT_EMPTY(box) \
- (((box.x2 - box.x1) > 0) && ((box.y2 - box.y1) > 0))
-
-#define checkGCDamage(d,g) (getDrawableDamage(d) && \
- (!g->pCompositeClip ||\
- RegionNotEmpty(g->pCompositeClip)))
-
-#define TRIM_PICTURE_BOX(box, pDst) { \
- BoxPtr extents = &pDst->pCompositeClip->extents;\
- if(box.x1 < extents->x1) box.x1 = extents->x1; \
- if(box.x2 > extents->x2) box.x2 = extents->x2; \
- if(box.y1 < extents->y1) box.y1 = extents->y1; \
- if(box.y2 > extents->y2) box.y2 = extents->y2; \
- }
-
-#define checkPictureDamage(p) (getDrawableDamage(p->pDrawable) && \
- RegionNotEmpty(p->pCompositeClip))
-
-static void
-damageComposite (CARD8 op,
- PicturePtr pSrc,
- PicturePtr pMask,
- PicturePtr pDst,
- INT16 xSrc,
- INT16 ySrc,
- INT16 xMask,
- INT16 yMask,
- INT16 xDst,
- INT16 yDst,
- CARD16 width,
- CARD16 height)
-{
- ScreenPtr pScreen = pDst->pDrawable->pScreen;
- PictureScreenPtr ps = GetPictureScreen(pScreen);
- damageScrPriv(pScreen);
-
- if (checkPictureDamage (pDst))
- {
- BoxRec box;
-
- box.x1 = xDst + pDst->pDrawable->x;
- box.y1 = yDst + pDst->pDrawable->y;
- box.x2 = box.x1 + width;
- box.y2 = box.y1 + height;
- TRIM_PICTURE_BOX(box, pDst);
- if (BOX_NOT_EMPTY(box))
- damageDamageBox (pDst->pDrawable, &box, pDst->subWindowMode);
- }
- unwrap (pScrPriv, ps, Composite);
- (*ps->Composite) (op,
- pSrc,
- pMask,
- pDst,
- xSrc,
- ySrc,
- xMask,
- yMask,
- xDst,
- yDst,
- width,
- height);
- damageRegionProcessPending (pDst->pDrawable);
- wrap (pScrPriv, ps, Composite, damageComposite);
-}
-
-static void
-damageGlyphs (CARD8 op,
- PicturePtr pSrc,
- PicturePtr pDst,
- PictFormatPtr maskFormat,
- INT16 xSrc,
- INT16 ySrc,
- int nlist,
- GlyphListPtr list,
- GlyphPtr *glyphs)
-{
- ScreenPtr pScreen = pDst->pDrawable->pScreen;
- PictureScreenPtr ps = GetPictureScreen(pScreen);
- damageScrPriv(pScreen);
-
- if (checkPictureDamage (pDst))
- {
- int nlistTmp = nlist;
- GlyphListPtr listTmp = list;
- GlyphPtr *glyphsTmp = glyphs;
- int x, y;
- int n;
- GlyphPtr glyph;
- BoxRec box;
- int x1, y1, x2, y2;
-
- box.x1 = 32767;
- box.y1 = 32767;
- box.x2 = -32767;
- box.y2 = -32767;
- x = pDst->pDrawable->x;
- y = pDst->pDrawable->y;
- while (nlistTmp--)
- {
- x += listTmp->xOff;
- y += listTmp->yOff;
- n = listTmp->len;
- while (n--)
- {
- glyph = *glyphsTmp++;
- x1 = x - glyph->info.x;
- y1 = y - glyph->info.y;
- x2 = x1 + glyph->info.width;
- y2 = y1 + glyph->info.height;
- if (x1 < box.x1)
- box.x1 = x1;
- if (y1 < box.y1)
- box.y1 = y1;
- if (x2 > box.x2)
- box.x2 = x2;
- if (y2 > box.y2)
- box.y2 = y2;
- x += glyph->info.xOff;
- y += glyph->info.yOff;
- }
- listTmp++;
- }
- TRIM_PICTURE_BOX (box, pDst);
- if (BOX_NOT_EMPTY(box))
- damageDamageBox (pDst->pDrawable, &box, pDst->subWindowMode);
- }
- unwrap (pScrPriv, ps, Glyphs);
- (*ps->Glyphs) (op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, list, glyphs);
- damageRegionProcessPending (pDst->pDrawable);
- wrap (pScrPriv, ps, Glyphs, damageGlyphs);
-}
-
-static void
-damageAddTraps (PicturePtr pPicture,
- INT16 x_off,
- INT16 y_off,
- int ntrap,
- xTrap *traps)
-{
- ScreenPtr pScreen = pPicture->pDrawable->pScreen;
- PictureScreenPtr ps = GetPictureScreen(pScreen);
- damageScrPriv(pScreen);
-
- if (checkPictureDamage (pPicture))
- {
- BoxRec box;
- int i;
- int x, y;
- xTrap *t = traps;
-
- box.x1 = 32767;
- box.y1 = 32767;
- box.x2 = -32767;
- box.y2 = -32767;
- x = pPicture->pDrawable->x + x_off;
- y = pPicture->pDrawable->y + y_off;
- for (i = 0; i < ntrap; i++)
- {
- pixman_fixed_t l = min (t->top.l, t->bot.l);
- pixman_fixed_t r = max (t->top.r, t->bot.r);
- int x1 = x + pixman_fixed_to_int (l);
- int x2 = x + pixman_fixed_to_int (pixman_fixed_ceil (r));
- int y1 = y + pixman_fixed_to_int (t->top.y);
- int y2 = y + pixman_fixed_to_int (pixman_fixed_ceil (t->bot.y));
-
- if (x1 < box.x1)
- box.x1 = x1;
- if (x2 > box.x2)
- box.x2 = x2;
- if (y1 < box.y1)
- box.y1 = y1;
- if (y2 > box.y2)
- box.y2 = y2;
- }
- TRIM_PICTURE_BOX (box, pPicture);
- if (BOX_NOT_EMPTY(box))
- damageDamageBox (pPicture->pDrawable, &box, pPicture->subWindowMode);
- }
- unwrap (pScrPriv, ps, AddTraps);
- (*ps->AddTraps) (pPicture, x_off, y_off, ntrap, traps);
- damageRegionProcessPending (pPicture->pDrawable);
- wrap (pScrPriv, ps, AddTraps, damageAddTraps);
-}
-
-/**********************************************************/
-
-
-static void
-damageFillSpans(DrawablePtr pDrawable,
- GC *pGC,
- int npt,
- DDXPointPtr ppt,
- int *pwidth,
- int fSorted)
-{
- DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
-
- if (npt && checkGCDamage (pDrawable, pGC))
- {
- int nptTmp = npt;
- DDXPointPtr pptTmp = ppt;
- int *pwidthTmp = pwidth;
- BoxRec box;
-
- box.x1 = pptTmp->x;
- box.x2 = box.x1 + *pwidthTmp;
- box.y2 = box.y1 = pptTmp->y;
-
- while(--nptTmp)
- {
- pptTmp++;
- pwidthTmp++;
- if(box.x1 > pptTmp->x) box.x1 = pptTmp->x;
- if(box.x2 < (pptTmp->x + *pwidthTmp))
- box.x2 = pptTmp->x + *pwidthTmp;
- if(box.y1 > pptTmp->y) box.y1 = pptTmp->y;
- else if(box.y2 < pptTmp->y) box.y2 = pptTmp->y;
- }
-
- box.y2++;
-
- if(!pGC->miTranslate) {
- TRANSLATE_BOX(box, pDrawable);
- }
- TRIM_BOX(box, pGC);
-
- if(BOX_NOT_EMPTY(box))
- damageDamageBox (pDrawable, &box, pGC->subWindowMode);
- }
-
- (*pGC->ops->FillSpans)(pDrawable, pGC, npt, ppt, pwidth, fSorted);
-
- damageRegionProcessPending (pDrawable);
- DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
-}
-
-static void
-damageSetSpans(DrawablePtr pDrawable,
- GCPtr pGC,
- char *pcharsrc,
- DDXPointPtr ppt,
- int *pwidth,
- int npt,
- int fSorted)
-{
- DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
-
- if (npt && checkGCDamage (pDrawable, pGC))
- {
- DDXPointPtr pptTmp = ppt;
- int *pwidthTmp = pwidth;
- int nptTmp = npt;
- BoxRec box;
-
- box.x1 = pptTmp->x;
- box.x2 = box.x1 + *pwidthTmp;
- box.y2 = box.y1 = pptTmp->y;
-
- while(--nptTmp)
- {
- pptTmp++;
- pwidthTmp++;
- if(box.x1 > pptTmp->x) box.x1 = pptTmp->x;
- if(box.x2 < (pptTmp->x + *pwidthTmp))
- box.x2 = pptTmp->x + *pwidthTmp;
- if(box.y1 > pptTmp->y) box.y1 = pptTmp->y;
- else if(box.y2 < pptTmp->y) box.y2 = pptTmp->y;
- }
-
- box.y2++;
-
- if(!pGC->miTranslate) {
- TRANSLATE_BOX(box, pDrawable);
- }
- TRIM_BOX(box, pGC);
-
- if(BOX_NOT_EMPTY(box))
- damageDamageBox (pDrawable, &box, pGC->subWindowMode);
- }
- (*pGC->ops->SetSpans)(pDrawable, pGC, pcharsrc, ppt, pwidth, npt, fSorted);
- damageRegionProcessPending (pDrawable);
- DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
-}
-
-static void
-damagePutImage(DrawablePtr pDrawable,
- GCPtr pGC,
- int depth,
- int x,
- int y,
- int w,
- int h,
- int leftPad,
- int format,
- char *pImage)
-{
- DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
- if (checkGCDamage (pDrawable, pGC))
- {
- BoxRec box;
-
- box.x1 = x + pDrawable->x;
- box.x2 = box.x1 + w;
- box.y1 = y + pDrawable->y;
- box.y2 = box.y1 + h;
-
- TRIM_BOX(box, pGC);
- if(BOX_NOT_EMPTY(box))
- damageDamageBox (pDrawable, &box, pGC->subWindowMode);
- }
- (*pGC->ops->PutImage)(pDrawable, pGC, depth, x, y, w, h,
- leftPad, format, pImage);
- damageRegionProcessPending (pDrawable);
- DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
-}
-
-static RegionPtr
-damageCopyArea(DrawablePtr pSrc,
- DrawablePtr pDst,
- GC *pGC,
- int srcx,
- int srcy,
- int width,
- int height,
- int dstx,
- int dsty)
-{
- RegionPtr ret;
- DAMAGE_GC_OP_PROLOGUE(pGC, pDst);
-
- if (checkGCDamage (pDst, pGC))
- {
- BoxRec box;
-
- box.x1 = dstx + pDst->x;
- box.x2 = box.x1 + width;
- box.y1 = dsty + pDst->y;
- box.y2 = box.y1 + height;
-
- TRIM_BOX(box, pGC);
- if(BOX_NOT_EMPTY(box))
- damageDamageBox (pDst, &box, pGC->subWindowMode);
- }
-
- ret = (*pGC->ops->CopyArea)(pSrc, pDst,
- pGC, srcx, srcy, width, height, dstx, dsty);
- damageRegionProcessPending (pDst);
- DAMAGE_GC_OP_EPILOGUE(pGC, pDst);
- return ret;
-}
-
-static RegionPtr
-damageCopyPlane(DrawablePtr pSrc,
- DrawablePtr pDst,
- GCPtr pGC,
- int srcx,
- int srcy,
- int width,
- int height,
- int dstx,
- int dsty,
- unsigned long bitPlane)
-{
- RegionPtr ret;
- DAMAGE_GC_OP_PROLOGUE(pGC, pDst);
-
- if (checkGCDamage (pDst, pGC))
- {
- BoxRec box;
-
- box.x1 = dstx + pDst->x;
- box.x2 = box.x1 + width;
- box.y1 = dsty + pDst->y;
- box.y2 = box.y1 + height;
-
- TRIM_BOX(box, pGC);
- if(BOX_NOT_EMPTY(box))
- damageDamageBox (pDst, &box, pGC->subWindowMode);
- }
-
- ret = (*pGC->ops->CopyPlane)(pSrc, pDst,
- pGC, srcx, srcy, width, height, dstx, dsty, bitPlane);
- damageRegionProcessPending (pDst);
- DAMAGE_GC_OP_EPILOGUE(pGC, pDst);
- return ret;
-}
-
-static void
-damagePolyPoint(DrawablePtr pDrawable,
- GCPtr pGC,
- int mode,
- int npt,
- xPoint *ppt)
-{
- DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
-
- if (npt && checkGCDamage (pDrawable, pGC))
- {
- BoxRec box;
- int nptTmp = npt;
- xPoint *pptTmp = ppt;
-
- box.x2 = box.x1 = pptTmp->x;
- box.y2 = box.y1 = pptTmp->y;
-
- /* this could be slow if the points were spread out */
-
- while(--nptTmp)
- {
- pptTmp++;
- if(box.x1 > pptTmp->x) box.x1 = pptTmp->x;
- else if(box.x2 < pptTmp->x) box.x2 = pptTmp->x;
- if(box.y1 > pptTmp->y) box.y1 = pptTmp->y;
- else if(box.y2 < pptTmp->y) box.y2 = pptTmp->y;
- }
-
- box.x2++;
- box.y2++;
-
- TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC);
- if(BOX_NOT_EMPTY(box))
- damageDamageBox (pDrawable, &box, pGC->subWindowMode);
- }
- (*pGC->ops->PolyPoint)(pDrawable, pGC, mode, npt, ppt);
- damageRegionProcessPending (pDrawable);
- DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
-}
-
-static void
-damagePolylines(DrawablePtr pDrawable,
- GCPtr pGC,
- int mode,
- int npt,
- DDXPointPtr ppt)
-{
- DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
-
- if (npt && checkGCDamage (pDrawable, pGC))
- {
- int nptTmp = npt;
- DDXPointPtr pptTmp = ppt;
- BoxRec box;
- int extra = pGC->lineWidth >> 1;
-
- box.x2 = box.x1 = pptTmp->x;
- box.y2 = box.y1 = pptTmp->y;
-
- if(nptTmp > 1)
- {
- if(pGC->joinStyle == JoinMiter)
- extra = 6 * pGC->lineWidth;
- else if(pGC->capStyle == CapProjecting)
- extra = pGC->lineWidth;
- }
-
- if(mode == CoordModePrevious)
- {
- int x = box.x1;
- int y = box.y1;
- while(--nptTmp)
- {
- pptTmp++;
- x += pptTmp->x;
- y += pptTmp->y;
- if(box.x1 > x) box.x1 = x;
- else if(box.x2 < x) box.x2 = x;
- if(box.y1 > y) box.y1 = y;
- else if(box.y2 < y) box.y2 = y;
- }
- }
- else
- {
- while(--nptTmp)
- {
- pptTmp++;
- if(box.x1 > pptTmp->x) box.x1 = pptTmp->x;
- else if(box.x2 < pptTmp->x) box.x2 = pptTmp->x;
- if(box.y1 > pptTmp->y) box.y1 = pptTmp->y;
- else if(box.y2 < pptTmp->y) box.y2 = pptTmp->y;
- }
- }
-
- box.x2++;
- box.y2++;
-
- if(extra)
- {
- box.x1 -= extra;
- box.x2 += extra;
- box.y1 -= extra;
- box.y2 += extra;
- }
-
- TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC);
- if(BOX_NOT_EMPTY(box))
- damageDamageBox (pDrawable, &box, pGC->subWindowMode);
- }
- (*pGC->ops->Polylines)(pDrawable, pGC, mode, npt, ppt);
- damageRegionProcessPending (pDrawable);
- DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
-}
-
-static void
-damagePolySegment(DrawablePtr pDrawable,
- GCPtr pGC,
- int nSeg,
- xSegment *pSeg)
-{
- DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
-
- if (nSeg && checkGCDamage (pDrawable, pGC))
- {
- BoxRec box;
- int extra = pGC->lineWidth;
- int nsegTmp = nSeg;
- xSegment *pSegTmp = pSeg;
-
- if(pGC->capStyle != CapProjecting)
- extra >>= 1;
-
- if(pSegTmp->x2 > pSegTmp->x1) {
- box.x1 = pSegTmp->x1;
- box.x2 = pSegTmp->x2;
- } else {
- box.x2 = pSegTmp->x1;
- box.x1 = pSegTmp->x2;
- }
-
- if(pSegTmp->y2 > pSegTmp->y1) {
- box.y1 = pSegTmp->y1;
- box.y2 = pSegTmp->y2;
- } else {
- box.y2 = pSegTmp->y1;
- box.y1 = pSegTmp->y2;
- }
-
- while(--nsegTmp)
- {
- pSegTmp++;
- if(pSegTmp->x2 > pSegTmp->x1)
- {
- if(pSegTmp->x1 < box.x1) box.x1 = pSegTmp->x1;
- if(pSegTmp->x2 > box.x2) box.x2 = pSegTmp->x2;
- }
- else
- {
- if(pSegTmp->x2 < box.x1) box.x1 = pSegTmp->x2;
- if(pSegTmp->x1 > box.x2) box.x2 = pSegTmp->x1;
- }
- if(pSegTmp->y2 > pSegTmp->y1)
- {
- if(pSegTmp->y1 < box.y1) box.y1 = pSegTmp->y1;
- if(pSegTmp->y2 > box.y2) box.y2 = pSegTmp->y2;
- }
- else
- {
- if(pSegTmp->y2 < box.y1) box.y1 = pSegTmp->y2;
- if(pSegTmp->y1 > box.y2) box.y2 = pSegTmp->y1;
- }
- }
-
- box.x2++;
- box.y2++;
-
- if(extra)
- {
- box.x1 -= extra;
- box.x2 += extra;
- box.y1 -= extra;
- box.y2 += extra;
- }
-
- TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC);
- if(BOX_NOT_EMPTY(box))
- damageDamageBox (pDrawable, &box, pGC->subWindowMode);
- }
- (*pGC->ops->PolySegment)(pDrawable, pGC, nSeg, pSeg);
- damageRegionProcessPending (pDrawable);
- DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
-}
-
-static void
-damagePolyRectangle(DrawablePtr pDrawable,
- GCPtr pGC,
- int nRects,
- xRectangle *pRects)
-{
- DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
-
- if (nRects && checkGCDamage (pDrawable, pGC))
- {
- BoxRec box;
- int offset1, offset2, offset3;
- int nRectsTmp = nRects;
- xRectangle *pRectsTmp = pRects;
-
- offset2 = pGC->lineWidth;
- if(!offset2) offset2 = 1;
- offset1 = offset2 >> 1;
- offset3 = offset2 - offset1;
-
- while(nRectsTmp--)
- {
- box.x1 = pRectsTmp->x - offset1;
- box.y1 = pRectsTmp->y - offset1;
- box.x2 = box.x1 + pRectsTmp->width + offset2;
- box.y2 = box.y1 + offset2;
- TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC);
- if(BOX_NOT_EMPTY(box))
- damageDamageBox (pDrawable, &box, pGC->subWindowMode);
-
- box.x1 = pRectsTmp->x - offset1;
- box.y1 = pRectsTmp->y + offset3;
- box.x2 = box.x1 + offset2;
- box.y2 = box.y1 + pRectsTmp->height - offset2;
- TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC);
- if(BOX_NOT_EMPTY(box))
- damageDamageBox (pDrawable, &box, pGC->subWindowMode);
-
- box.x1 = pRectsTmp->x + pRectsTmp->width - offset1;
- box.y1 = pRectsTmp->y + offset3;
- box.x2 = box.x1 + offset2;
- box.y2 = box.y1 + pRectsTmp->height - offset2;
- TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC);
- if(BOX_NOT_EMPTY(box))
- damageDamageBox (pDrawable, &box, pGC->subWindowMode);
-
- box.x1 = pRectsTmp->x - offset1;
- box.y1 = pRectsTmp->y + pRectsTmp->height - offset1;
- box.x2 = box.x1 + pRectsTmp->width + offset2;
- box.y2 = box.y1 + offset2;
- TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC);
- if(BOX_NOT_EMPTY(box))
- damageDamageBox (pDrawable, &box, pGC->subWindowMode);
-
- pRectsTmp++;
- }
- }
- (*pGC->ops->PolyRectangle)(pDrawable, pGC, nRects, pRects);
- damageRegionProcessPending (pDrawable);
- DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
-}
-
-static void
-damagePolyArc(DrawablePtr pDrawable,
- GCPtr pGC,
- int nArcs,
- xArc *pArcs)
-{
- DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
-
- if (nArcs && checkGCDamage (pDrawable, pGC))
- {
- int extra = pGC->lineWidth >> 1;
- BoxRec box;
- int nArcsTmp = nArcs;
- xArc *pArcsTmp = pArcs;
-
- box.x1 = pArcsTmp->x;
- box.x2 = box.x1 + pArcsTmp->width;
- box.y1 = pArcsTmp->y;
- box.y2 = box.y1 + pArcsTmp->height;
-
- while(--nArcsTmp)
- {
- pArcsTmp++;
- if(box.x1 > pArcsTmp->x)
- box.x1 = pArcsTmp->x;
- if(box.x2 < (pArcsTmp->x + pArcsTmp->width))
- box.x2 = pArcsTmp->x + pArcsTmp->width;
- if(box.y1 > pArcsTmp->y)
- box.y1 = pArcsTmp->y;
- if(box.y2 < (pArcsTmp->y + pArcsTmp->height))
- box.y2 = pArcsTmp->y + pArcsTmp->height;
- }
-
- if(extra)
- {
- box.x1 -= extra;
- box.x2 += extra;
- box.y1 -= extra;
- box.y2 += extra;
- }
-
- box.x2++;
- box.y2++;
-
- TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC);
- if(BOX_NOT_EMPTY(box))
- damageDamageBox (pDrawable, &box, pGC->subWindowMode);
- }
- (*pGC->ops->PolyArc)(pDrawable, pGC, nArcs, pArcs);
- damageRegionProcessPending (pDrawable);
- DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
-}
-
-static void
-damageFillPolygon(DrawablePtr pDrawable,
- GCPtr pGC,
- int shape,
- int mode,
- int npt,
- DDXPointPtr ppt)
-{
- DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
-
- if (npt > 2 && checkGCDamage (pDrawable, pGC))
- {
- DDXPointPtr pptTmp = ppt;
- int nptTmp = npt;
- BoxRec box;
-
- box.x2 = box.x1 = pptTmp->x;
- box.y2 = box.y1 = pptTmp->y;
-
- if(mode != CoordModeOrigin)
- {
- int x = box.x1;
- int y = box.y1;
- while(--nptTmp)
- {
- pptTmp++;
- x += pptTmp->x;
- y += pptTmp->y;
- if(box.x1 > x) box.x1 = x;
- else if(box.x2 < x) box.x2 = x;
- if(box.y1 > y) box.y1 = y;
- else if(box.y2 < y) box.y2 = y;
- }
- }
- else
- {
- while(--nptTmp)
- {
- pptTmp++;
- if(box.x1 > pptTmp->x) box.x1 = pptTmp->x;
- else if(box.x2 < pptTmp->x) box.x2 = pptTmp->x;
- if(box.y1 > pptTmp->y) box.y1 = pptTmp->y;
- else if(box.y2 < pptTmp->y) box.y2 = pptTmp->y;
- }
- }
-
- box.x2++;
- box.y2++;
-
- TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC);
- if(BOX_NOT_EMPTY(box))
- damageDamageBox (pDrawable, &box, pGC->subWindowMode);
- }
-
- (*pGC->ops->FillPolygon)(pDrawable, pGC, shape, mode, npt, ppt);
- damageRegionProcessPending (pDrawable);
- DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
-}
-
-
-static void
-damagePolyFillRect(DrawablePtr pDrawable,
- GCPtr pGC,
- int nRects,
- xRectangle *pRects)
-{
- DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
- if (nRects && checkGCDamage (pDrawable, pGC))
- {
- BoxRec box;
- xRectangle *pRectsTmp = pRects;
- int nRectsTmp = nRects;
-
- box.x1 = pRectsTmp->x;
- box.x2 = box.x1 + pRectsTmp->width;
- box.y1 = pRectsTmp->y;
- box.y2 = box.y1 + pRectsTmp->height;
-
- while(--nRectsTmp)
- {
- pRectsTmp++;
- if(box.x1 > pRectsTmp->x) box.x1 = pRectsTmp->x;
- if(box.x2 < (pRectsTmp->x + pRectsTmp->width))
- box.x2 = pRectsTmp->x + pRectsTmp->width;
- if(box.y1 > pRectsTmp->y) box.y1 = pRectsTmp->y;
- if(box.y2 < (pRectsTmp->y + pRectsTmp->height))
- box.y2 = pRectsTmp->y + pRectsTmp->height;
- }
-
- TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC);
- if(BOX_NOT_EMPTY(box))
- damageDamageBox (pDrawable, &box, pGC->subWindowMode);
- }
- (*pGC->ops->PolyFillRect)(pDrawable, pGC, nRects, pRects);
- damageRegionProcessPending (pDrawable);
- DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
-}
-
-
-static void
-damagePolyFillArc(DrawablePtr pDrawable,
- GCPtr pGC,
- int nArcs,
- xArc *pArcs)
-{
- DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
-
- if (nArcs && checkGCDamage (pDrawable, pGC))
- {
- BoxRec box;
- int nArcsTmp = nArcs;
- xArc *pArcsTmp = pArcs;
-
- box.x1 = pArcsTmp->x;
- box.x2 = box.x1 + pArcsTmp->width;
- box.y1 = pArcsTmp->y;
- box.y2 = box.y1 + pArcsTmp->height;
-
- while(--nArcsTmp)
- {
- pArcsTmp++;
- if(box.x1 > pArcsTmp->x)
- box.x1 = pArcsTmp->x;
- if(box.x2 < (pArcsTmp->x + pArcsTmp->width))
- box.x2 = pArcsTmp->x + pArcsTmp->width;
- if(box.y1 > pArcsTmp->y)
- box.y1 = pArcsTmp->y;
- if(box.y2 < (pArcsTmp->y + pArcsTmp->height))
- box.y2 = pArcsTmp->y + pArcsTmp->height;
- }
-
- TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC);
- if(BOX_NOT_EMPTY(box))
- damageDamageBox (pDrawable, &box, pGC->subWindowMode);
- }
- (*pGC->ops->PolyFillArc)(pDrawable, pGC, nArcs, pArcs);
- damageRegionProcessPending (pDrawable);
- DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
-}
-
-/*
- * general Poly/Image text function. Extract glyph information,
- * compute bounding box and remove cursor if it is overlapped.
- */
-
-static void
-damageDamageChars (DrawablePtr pDrawable,
- FontPtr font,
- int x,
- int y,
- unsigned int n,
- CharInfoPtr *charinfo,
- Bool imageblt,
- int subWindowMode)
-{
- ExtentInfoRec extents;
- BoxRec box;
-
- QueryGlyphExtents(font, charinfo, n, &extents);
- if (imageblt)
- {
- if (extents.overallWidth > extents.overallRight)
- extents.overallRight = extents.overallWidth;
- if (extents.overallWidth < extents.overallLeft)
- extents.overallLeft = extents.overallWidth;
- if (extents.overallLeft > 0)
- extents.overallLeft = 0;
- if (extents.fontAscent > extents.overallAscent)
- extents.overallAscent = extents.fontAscent;
- if (extents.fontDescent > extents.overallDescent)
- extents.overallDescent = extents.fontDescent;
- }
- box.x1 = x + extents.overallLeft;
- box.y1 = y - extents.overallAscent;
- box.x2 = x + extents.overallRight;
- box.y2 = y + extents.overallDescent;
- damageDamageBox (pDrawable, &box, subWindowMode);
-}
-
-/*
- * values for textType:
- */
-#define TT_POLY8 0
-#define TT_IMAGE8 1
-#define TT_POLY16 2
-#define TT_IMAGE16 3
-
-static int
-damageText (DrawablePtr pDrawable,
- GCPtr pGC,
- int x,
- int y,
- unsigned long count,
- char *chars,
- FontEncoding fontEncoding,
- Bool textType)
-{
- CharInfoPtr *charinfo;
- CharInfoPtr *info;
- unsigned long i;
- unsigned int n;
- int w;
- Bool imageblt;
-
- imageblt = (textType == TT_IMAGE8) || (textType == TT_IMAGE16);
-
- charinfo = malloc(count * sizeof(CharInfoPtr));
- if (!charinfo)
- return x;
-
- GetGlyphs(pGC->font, count, (unsigned char *)chars,
- fontEncoding, &i, charinfo);
- n = (unsigned int)i;
- w = 0;
- if (!imageblt)
- for (info = charinfo; i--; info++)
- w += (*info)->metrics.characterWidth;
-
- if (n != 0) {
- damageDamageChars (pDrawable, pGC->font, x + pDrawable->x, y + pDrawable->y, n,
- charinfo, imageblt, pGC->subWindowMode);
- if (imageblt)
- (*pGC->ops->ImageGlyphBlt)(pDrawable, pGC, x, y, n, charinfo,
- FONTGLYPHS(pGC->font));
- else
- (*pGC->ops->PolyGlyphBlt)(pDrawable, pGC, x, y, n, charinfo,
- FONTGLYPHS(pGC->font));
- }
- free(charinfo);
- return x + w;
-}
-
-static int
-damagePolyText8(DrawablePtr pDrawable,
- GCPtr pGC,
- int x,
- int y,
- int count,
- char *chars)
-{
- DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
-
- if (checkGCDamage (pDrawable, pGC))
- x = damageText (pDrawable, pGC, x, y, (unsigned long) count, chars,
- Linear8Bit, TT_POLY8);
- else
- x = (*pGC->ops->PolyText8)(pDrawable, pGC, x, y, count, chars);
- damageRegionProcessPending (pDrawable);
- DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
- return x;
-}
-
-static int
-damagePolyText16(DrawablePtr pDrawable,
- GCPtr pGC,
- int x,
- int y,
- int count,
- unsigned short *chars)
-{
- DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
-
- if (checkGCDamage (pDrawable, pGC))
- x = damageText (pDrawable, pGC, x, y, (unsigned long) count, (char *) chars,
- FONTLASTROW(pGC->font) == 0 ? Linear16Bit : TwoD16Bit,
- TT_POLY16);
- else
- x = (*pGC->ops->PolyText16)(pDrawable, pGC, x, y, count, chars);
- damageRegionProcessPending (pDrawable);
- DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
- return x;
-}
-
-static void
-damageImageText8(DrawablePtr pDrawable,
- GCPtr pGC,
- int x,
- int y,
- int count,
- char *chars)
-{
- DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
-
- if (checkGCDamage (pDrawable, pGC))
- damageText (pDrawable, pGC, x, y, (unsigned long) count, chars,
- Linear8Bit, TT_IMAGE8);
- else
- (*pGC->ops->ImageText8)(pDrawable, pGC, x, y, count, chars);
- damageRegionProcessPending (pDrawable);
- DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
-}
-
-static void
-damageImageText16(DrawablePtr pDrawable,
- GCPtr pGC,
- int x,
- int y,
- int count,
- unsigned short *chars)
-{
- DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
-
- if (checkGCDamage (pDrawable, pGC))
- damageText (pDrawable, pGC, x, y, (unsigned long) count, (char *) chars,
- FONTLASTROW(pGC->font) == 0 ? Linear16Bit : TwoD16Bit,
- TT_IMAGE16);
- else
- (*pGC->ops->ImageText16)(pDrawable, pGC, x, y, count, chars);
- damageRegionProcessPending (pDrawable);
- DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
-}
-
-
-static void
-damageImageGlyphBlt(DrawablePtr pDrawable,
- GCPtr pGC,
- int x,
- int y,
- unsigned int nglyph,
- CharInfoPtr *ppci,
- pointer pglyphBase)
-{
- DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
- damageDamageChars (pDrawable, pGC->font, x + pDrawable->x, y + pDrawable->y,
- nglyph, ppci, TRUE, pGC->subWindowMode);
- (*pGC->ops->ImageGlyphBlt)(pDrawable, pGC, x, y, nglyph,
- ppci, pglyphBase);
- damageRegionProcessPending (pDrawable);
- DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
-}
-
-static void
-damagePolyGlyphBlt(DrawablePtr pDrawable,
- GCPtr pGC,
- int x,
- int y,
- unsigned int nglyph,
- CharInfoPtr *ppci,
- pointer pglyphBase)
-{
- DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
- damageDamageChars (pDrawable, pGC->font, x + pDrawable->x, y + pDrawable->y,
- nglyph, ppci, FALSE, pGC->subWindowMode);
- (*pGC->ops->PolyGlyphBlt)(pDrawable, pGC, x, y, nglyph,
- ppci, pglyphBase);
- damageRegionProcessPending (pDrawable);
- DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
-}
-
-static void
-damagePushPixels(GCPtr pGC,
- PixmapPtr pBitMap,
- DrawablePtr pDrawable,
- int dx,
- int dy,
- int xOrg,
- int yOrg)
-{
- DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
- if(checkGCDamage (pDrawable, pGC))
- {
- BoxRec box;
-
- box.x1 = xOrg;
- box.y1 = yOrg;
-
- if(!pGC->miTranslate) {
- box.x1 += pDrawable->x;
- box.y1 += pDrawable->y;
- }
-
- box.x2 = box.x1 + dx;
- box.y2 = box.y1 + dy;
-
- TRIM_BOX(box, pGC);
- if(BOX_NOT_EMPTY(box))
- damageDamageBox (pDrawable, &box, pGC->subWindowMode);
- }
- (*pGC->ops->PushPixels)(pGC, pBitMap, pDrawable, dx, dy, xOrg, yOrg);
- damageRegionProcessPending (pDrawable);
- DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
-}
-
-static void
-damageRemoveDamage (DamagePtr *pPrev, DamagePtr pDamage)
-{
- while (*pPrev)
- {
- if (*pPrev == pDamage)
- {
- *pPrev = pDamage->pNext;
- return;
- }
- pPrev = &(*pPrev)->pNext;
- }
-#if DAMAGE_VALIDATE_ENABLE
- ErrorF ("Damage not on list\n");
- OsAbort ();
-#endif
-}
-
-static void
-damageInsertDamage (DamagePtr *pPrev, DamagePtr pDamage)
-{
-#if DAMAGE_VALIDATE_ENABLE
- DamagePtr pOld;
-
- for (pOld = *pPrev; pOld; pOld = pOld->pNext)
- if (pOld == pDamage) {
- ErrorF ("Damage already on list\n");
- OsAbort ();
- }
-#endif
- pDamage->pNext = *pPrev;
- *pPrev = pDamage;
-}
-
-static Bool
-damageDestroyPixmap (PixmapPtr pPixmap)
-{
- ScreenPtr pScreen = pPixmap->drawable.pScreen;
- damageScrPriv(pScreen);
-
- if (pPixmap->refcnt == 1)
- {
- DamagePtr *pPrev = getPixmapDamageRef (pPixmap);
- DamagePtr pDamage;
-
- while ((pDamage = *pPrev))
- {
- damageRemoveDamage (pPrev, pDamage);
- if (!pDamage->isWindow)
- DamageDestroy (pDamage);
- }
- }
- unwrap (pScrPriv, pScreen, DestroyPixmap);
- (*pScreen->DestroyPixmap) (pPixmap);
- wrap (pScrPriv, pScreen, DestroyPixmap, damageDestroyPixmap);
- return TRUE;
-}
-
-static void
-damageCopyWindow(WindowPtr pWindow,
- DDXPointRec ptOldOrg,
- RegionPtr prgnSrc)
-{
- ScreenPtr pScreen = pWindow->drawable.pScreen;
- damageScrPriv(pScreen);
-
- if (getWindowDamage (pWindow))
- {
- int dx = pWindow->drawable.x - ptOldOrg.x;
- int dy = pWindow->drawable.y - ptOldOrg.y;
-
- /*
- * The region comes in source relative, but the damage occurs
- * at the destination location. Translate back and forth.
- */
- RegionTranslate(prgnSrc, dx, dy);
- damageRegionAppend (&pWindow->drawable, prgnSrc, FALSE, -1);
- RegionTranslate(prgnSrc, -dx, -dy);
- }
- unwrap (pScrPriv, pScreen, CopyWindow);
- (*pScreen->CopyWindow) (pWindow, ptOldOrg, prgnSrc);
- damageRegionProcessPending (&pWindow->drawable);
- wrap (pScrPriv, pScreen, CopyWindow, damageCopyWindow);
-}
-
-static GCOps damageGCOps = {
- damageFillSpans, damageSetSpans,
- damagePutImage, damageCopyArea,
- damageCopyPlane, damagePolyPoint,
- damagePolylines, damagePolySegment,
- damagePolyRectangle, damagePolyArc,
- damageFillPolygon, damagePolyFillRect,
- damagePolyFillArc, damagePolyText8,
- damagePolyText16, damageImageText8,
- damageImageText16, damageImageGlyphBlt,
- damagePolyGlyphBlt, damagePushPixels,
-};
-
-static void
-damageSetWindowPixmap (WindowPtr pWindow, PixmapPtr pPixmap)
-{
- DamagePtr pDamage;
- ScreenPtr pScreen = pWindow->drawable.pScreen;
- damageScrPriv(pScreen);
-
- if ((pDamage = damageGetWinPriv(pWindow)))
- {
- PixmapPtr pOldPixmap = (*pScreen->GetWindowPixmap) (pWindow);
- DamagePtr *pPrev = getPixmapDamageRef(pOldPixmap);
-
- while (pDamage)
- {
- damageRemoveDamage (pPrev, pDamage);
- pDamage = pDamage->pNextWin;
- }
- }
- unwrap (pScrPriv, pScreen, SetWindowPixmap);
- (*pScreen->SetWindowPixmap) (pWindow, pPixmap);
- wrap (pScrPriv, pScreen, SetWindowPixmap, damageSetWindowPixmap);
- if ((pDamage = damageGetWinPriv(pWindow)))
- {
- DamagePtr *pPrev = getPixmapDamageRef(pPixmap);
-
- while (pDamage)
- {
- damageInsertDamage (pPrev, pDamage);
- pDamage = pDamage->pNextWin;
- }
- }
-}
-
-static Bool
-damageDestroyWindow (WindowPtr pWindow)
-{
- DamagePtr pDamage;
- ScreenPtr pScreen = pWindow->drawable.pScreen;
- Bool ret;
- damageScrPriv(pScreen);
-
- while ((pDamage = damageGetWinPriv(pWindow)))
- {
- DamageUnregister (&pWindow->drawable, pDamage);
- DamageDestroy (pDamage);
- }
- unwrap (pScrPriv, pScreen, DestroyWindow);
- ret = (*pScreen->DestroyWindow) (pWindow);
- wrap (pScrPriv, pScreen, DestroyWindow, damageDestroyWindow);
- return ret;
-}
-
-static Bool
-damageCloseScreen (int i, ScreenPtr pScreen)
-{
- damageScrPriv(pScreen);
-
- unwrap (pScrPriv, pScreen, DestroyPixmap);
- unwrap (pScrPriv, pScreen, CreateGC);
- unwrap (pScrPriv, pScreen, CopyWindow);
- unwrap (pScrPriv, pScreen, CloseScreen);
- free(pScrPriv);
- return (*pScreen->CloseScreen) (i, pScreen);
-}
-
-/**
- * Default implementations of the damage management functions.
- */
-void miDamageCreate (DamagePtr pDamage)
-{
-}
-
-void miDamageRegister (DrawablePtr pDrawable, DamagePtr pDamage)
-{
-}
-
-void miDamageUnregister (DrawablePtr pDrawable, DamagePtr pDamage)
-{
-}
-
-void miDamageDestroy (DamagePtr pDamage)
-{
-}
-
-/**
- * Public functions for consumption outside this file.
- */
-
-Bool
-DamageSetup (ScreenPtr pScreen)
-{
- DamageScrPrivPtr pScrPriv;
- PictureScreenPtr ps = GetPictureScreenIfSet(pScreen);
- const DamageScreenFuncsRec miFuncs = {
- miDamageCreate, miDamageRegister, miDamageUnregister, miDamageDestroy
- };
-
- if (!dixRegisterPrivateKey(&damageScrPrivateKeyRec, PRIVATE_SCREEN, 0))
- return FALSE;
-
- if (dixLookupPrivate(&pScreen->devPrivates, damageScrPrivateKey))
- return TRUE;
-
- if (!dixRegisterPrivateKey(&damageGCPrivateKeyRec, PRIVATE_GC, sizeof(DamageGCPrivRec)))
- return FALSE;
-
- if (!dixRegisterPrivateKey(&damagePixPrivateKeyRec, PRIVATE_PIXMAP, 0))
- return FALSE;
-
- if (!dixRegisterPrivateKey(&damageWinPrivateKeyRec, PRIVATE_WINDOW, 0))
- return FALSE;
-
- pScrPriv = malloc(sizeof (DamageScrPrivRec));
- if (!pScrPriv)
- return FALSE;
-
- pScrPriv->internalLevel = 0;
- pScrPriv->pScreenDamage = 0;
-
- wrap (pScrPriv, pScreen, DestroyPixmap, damageDestroyPixmap);
- wrap (pScrPriv, pScreen, CreateGC, damageCreateGC);
- wrap (pScrPriv, pScreen, DestroyWindow, damageDestroyWindow);
- wrap (pScrPriv, pScreen, SetWindowPixmap, damageSetWindowPixmap);
- wrap (pScrPriv, pScreen, CopyWindow, damageCopyWindow);
- wrap (pScrPriv, pScreen, CloseScreen, damageCloseScreen);
- if (ps) {
- wrap (pScrPriv, ps, Glyphs, damageGlyphs);
- wrap (pScrPriv, ps, Composite, damageComposite);
- wrap (pScrPriv, ps, AddTraps, damageAddTraps);
- }
-
- pScrPriv->funcs = miFuncs;
-
- dixSetPrivate(&pScreen->devPrivates, damageScrPrivateKey, pScrPriv);
- return TRUE;
-}
-
-DamagePtr
-DamageCreate (DamageReportFunc damageReport,
- DamageDestroyFunc damageDestroy,
- DamageReportLevel damageLevel,
- Bool isInternal,
- ScreenPtr pScreen,
- void *closure)
-{
- damageScrPriv(pScreen);
- DamagePtr pDamage;
-
- pDamage = dixAllocateObjectWithPrivates(DamageRec, PRIVATE_DAMAGE);
- if (!pDamage)
- return 0;
- pDamage->pNext = 0;
- pDamage->pNextWin = 0;
- RegionNull(&pDamage->damage);
- RegionNull(&pDamage->pendingDamage);
-
- pDamage->damageLevel = damageLevel;
- pDamage->isInternal = isInternal;
- pDamage->closure = closure;
- pDamage->isWindow = FALSE;
- pDamage->pDrawable = 0;
- pDamage->reportAfter = FALSE;
-
- pDamage->damageReport = damageReport;
- pDamage->damageReportPostRendering = NULL;
- pDamage->damageDestroy = damageDestroy;
- pDamage->damageMarker = NULL;
- pDamage->pScreen = pScreen;
-
- (*pScrPriv->funcs.Create) (pDamage);
-
- return pDamage;
-}
-
-void
-DamageRegister (DrawablePtr pDrawable,
- DamagePtr pDamage)
-{
- ScreenPtr pScreen = pDrawable->pScreen;
- damageScrPriv(pScreen);
-
-#if DAMAGE_VALIDATE_ENABLE
- if (pDrawable->pScreen != pDamage->pScreen)
- {
- ErrorF ("DamageRegister called with mismatched screens\n");
- OsAbort ();
- }
-#endif
-
- if (pDrawable->type == DRAWABLE_WINDOW)
- {
- WindowPtr pWindow = (WindowPtr) pDrawable;
- winDamageRef(pWindow);
-
-#if DAMAGE_VALIDATE_ENABLE
- DamagePtr pOld;
-
- for (pOld = *pPrev; pOld; pOld = pOld->pNextWin)
- if (pOld == pDamage) {
- ErrorF ("Damage already on window list\n");
- OsAbort ();
- }
-#endif
- pDamage->pNextWin = *pPrev;
- *pPrev = pDamage;
- pDamage->isWindow = TRUE;
- }
- else
- pDamage->isWindow = FALSE;
- pDamage->pDrawable = pDrawable;
- damageInsertDamage (getDrawableDamageRef (pDrawable), pDamage);
- (*pScrPriv->funcs.Register) (pDrawable, pDamage);
-}
-
-void
-DamageDrawInternal (ScreenPtr pScreen, Bool enable)
-{
- damageScrPriv (pScreen);
-
- pScrPriv->internalLevel += enable ? 1 : -1;
-}
-
-void
-DamageUnregister (DrawablePtr pDrawable,
- DamagePtr pDamage)
-{
- ScreenPtr pScreen = pDrawable->pScreen;
- damageScrPriv(pScreen);
-
- (*pScrPriv->funcs.Unregister) (pDrawable, pDamage);
-
- if (pDrawable->type == DRAWABLE_WINDOW)
- {
- WindowPtr pWindow = (WindowPtr) pDrawable;
- winDamageRef (pWindow);
-#if DAMAGE_VALIDATE_ENABLE
- int found = 0;
-#endif
-
- while (*pPrev)
- {
- if (*pPrev == pDamage)
- {
- *pPrev = pDamage->pNextWin;
-#if DAMAGE_VALIDATE_ENABLE
- found = 1;
-#endif
- break;
- }
- pPrev = &(*pPrev)->pNextWin;
- }
-#if DAMAGE_VALIDATE_ENABLE
- if (!found) {
- ErrorF ("Damage not on window list\n");
- OsAbort ();
- }
-#endif
- }
- pDamage->pDrawable = 0;
- damageRemoveDamage (getDrawableDamageRef (pDrawable), pDamage);
-}
-
-void
-DamageDestroy (DamagePtr pDamage)
-{
- ScreenPtr pScreen = pDamage->pScreen;
- damageScrPriv(pScreen);
-
- if (pDamage->damageDestroy)
- (*pDamage->damageDestroy) (pDamage, pDamage->closure);
- (*pScrPriv->funcs.Destroy) (pDamage);
- RegionUninit(&pDamage->damage);
- RegionUninit(&pDamage->pendingDamage);
- dixFreeObjectWithPrivates(pDamage, PRIVATE_DAMAGE);
-}
-
-Bool
-DamageSubtract (DamagePtr pDamage,
- const RegionPtr pRegion)
-{
- RegionPtr pClip;
- RegionRec pixmapClip;
- DrawablePtr pDrawable = pDamage->pDrawable;
-
- RegionSubtract(&pDamage->damage, &pDamage->damage, pRegion);
- if (pDrawable)
- {
- if (pDrawable->type == DRAWABLE_WINDOW)
- pClip = &((WindowPtr) pDrawable)->borderClip;
- else
- {
- BoxRec box;
-
- box.x1 = pDrawable->x;
- box.y1 = pDrawable->y;
- box.x2 = pDrawable->x + pDrawable->width;
- box.y2 = pDrawable->y + pDrawable->height;
- RegionInit(&pixmapClip, &box, 1);
- pClip = &pixmapClip;
- }
- RegionTranslate(&pDamage->damage, pDrawable->x, pDrawable->y);
- RegionIntersect(&pDamage->damage, &pDamage->damage, pClip);
- RegionTranslate(&pDamage->damage, -pDrawable->x, -pDrawable->y);
- if (pDrawable->type != DRAWABLE_WINDOW)
- RegionUninit(&pixmapClip);
- }
- return RegionNotEmpty(&pDamage->damage);
-}
-
-void
-DamageEmpty (DamagePtr pDamage)
-{
- RegionEmpty(&pDamage->damage);
-}
-
-RegionPtr
-DamageRegion (DamagePtr pDamage)
-{
- return &pDamage->damage;
-}
-
-RegionPtr
-DamagePendingRegion (DamagePtr pDamage)
-{
- return &pDamage->pendingDamage;
-}
-
-void
-DamageRegionAppend (DrawablePtr pDrawable, RegionPtr pRegion)
-{
- damageRegionAppend (pDrawable, pRegion, FALSE, -1);
-}
-
-void
-DamageRegionProcessPending (DrawablePtr pDrawable)
-{
- damageRegionProcessPending (pDrawable);
-}
-
-/* If a damage marker is provided, then this function must be called after rendering is done. */
-/* Please do call back so any future enhancements can assume this function is called. */
-/* There are no strict timing requirements for calling this function, just as soon as (is cheaply) possible. */
-void
-DamageRegionRendered (DrawablePtr pDrawable, DamagePtr pDamage, RegionPtr pOldDamage, RegionPtr pRegion)
-{
- if (pDamage->damageReportPostRendering)
- damageReportDamagePostRendering (pDamage, pOldDamage, pRegion);
-}
-
-/* This call is very odd, i'm leaving it intact for API sake, but please don't use it. */
-void
-DamageDamageRegion (DrawablePtr pDrawable,
- RegionPtr pRegion)
-{
- damageRegionAppend (pDrawable, pRegion, FALSE, -1);
-
- /* Go back and report this damage for DamagePtrs with reportAfter set, since
- * this call isn't part of an in-progress drawing op in the call chain and
- * the DDX probably just wants to know about it right away.
- */
- damageRegionProcessPending (pDrawable);
-}
-
-void
-DamageSetReportAfterOp (DamagePtr pDamage, Bool reportAfter)
-{
- pDamage->reportAfter = reportAfter;
-}
-
-void
-DamageSetPostRenderingFunctions(DamagePtr pDamage, DamageReportFunc damageReportPostRendering,
- DamageMarkerFunc damageMarker)
-{
- pDamage->damageReportPostRendering = damageReportPostRendering;
- pDamage->damageMarker = damageMarker;
-}
-
-DamageScreenFuncsPtr
-DamageGetScreenFuncs (ScreenPtr pScreen)
-{
- damageScrPriv(pScreen);
- return &pScrPriv->funcs;
-}
+/* + * Copyright © 2003 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY 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 THIS SOFTWARE. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include <stdlib.h> + +#include <X11/X.h> +#include "scrnintstr.h" +#include "windowstr.h" +#include <X11/fonts/font.h> +#include "dixfontstr.h" +#include <X11/fonts/fontstruct.h> +#include "mi.h" +#include "regionstr.h" +#include "globals.h" +#include "gcstruct.h" +#include "damage.h" +#include "damagestr.h" +#ifdef COMPOSITE +#include "cw.h" +#endif + +#define wrap(priv, real, mem, func) {\ + priv->mem = real->mem; \ + real->mem = func; \ +} + +#define unwrap(priv, real, mem) {\ + real->mem = priv->mem; \ +} + +#define BOX_SAME(a,b) \ + ((a)->x1 == (b)->x1 && \ + (a)->y1 == (b)->y1 && \ + (a)->x2 == (b)->x2 && \ + (a)->y2 == (b)->y2) + +#define DAMAGE_VALIDATE_ENABLE 0 +#define DAMAGE_DEBUG_ENABLE 0 +#if DAMAGE_DEBUG_ENABLE +#define DAMAGE_DEBUG(x) ErrorF x +#else +#define DAMAGE_DEBUG(x) +#endif + +#define getPixmapDamageRef(pPixmap) ((DamagePtr *) \ + dixLookupPrivateAddr(&(pPixmap)->devPrivates, damagePixPrivateKey)) + +#define pixmapDamage(pPixmap) damagePixPriv(pPixmap) + +static DevPrivateKeyRec damageScrPrivateKeyRec; +#define damageScrPrivateKey (&damageScrPrivateKeyRec) +static DevPrivateKeyRec damagePixPrivateKeyRec; +#define damagePixPrivateKey (&damagePixPrivateKeyRec) +static DevPrivateKeyRec damageGCPrivateKeyRec; +#define damageGCPrivateKey (&damageGCPrivateKeyRec) +static DevPrivateKeyRec damageWinPrivateKeyRec; +#define damageWinPrivateKey (&damageWinPrivateKeyRec) + +static DamagePtr * +getDrawableDamageRef (DrawablePtr pDrawable) +{ + PixmapPtr pPixmap; + + if (WindowDrawable(pDrawable->type)) + { + ScreenPtr pScreen = pDrawable->pScreen; + + pPixmap = 0; + if (pScreen->GetWindowPixmap +#ifdef ROOTLESS_WORKAROUND + && ((WindowPtr)pDrawable)->viewable +#endif + ) + pPixmap = (*pScreen->GetWindowPixmap) ((WindowPtr)pDrawable); + + if (!pPixmap) + { + damageScrPriv(pScreen); + + return &pScrPriv->pScreenDamage; + } + } + else + pPixmap = (PixmapPtr) pDrawable; + return getPixmapDamageRef (pPixmap); +} + +#define getDrawableDamage(pDrawable) (*getDrawableDamageRef (pDrawable)) +#define getWindowDamage(pWin) getDrawableDamage(&(pWin)->drawable) + +#define drawableDamage(pDrawable) \ + DamagePtr pDamage = getDrawableDamage(pDrawable) + +#define windowDamage(pWin) drawableDamage(&(pWin)->drawable) + +#define winDamageRef(pWindow) \ + DamagePtr *pPrev = (DamagePtr *) \ + dixLookupPrivateAddr(&(pWindow)->devPrivates, damageWinPrivateKey) + +static void +damageReportDamage (DamagePtr pDamage, RegionPtr pDamageRegion) +{ + BoxRec tmpBox; + RegionRec tmpRegion; + Bool was_empty; + + switch (pDamage->damageLevel) { + case DamageReportRawRegion: + RegionUnion(&pDamage->damage, &pDamage->damage, + pDamageRegion); + (*pDamage->damageReport) (pDamage, pDamageRegion, pDamage->closure); + break; + case DamageReportDeltaRegion: + RegionNull(&tmpRegion); + RegionSubtract(&tmpRegion, pDamageRegion, &pDamage->damage); + if (RegionNotEmpty(&tmpRegion)) { + RegionUnion(&pDamage->damage, &pDamage->damage, + pDamageRegion); + (*pDamage->damageReport) (pDamage, &tmpRegion, pDamage->closure); + } + RegionUninit(&tmpRegion); + break; + case DamageReportBoundingBox: + tmpBox = *RegionExtents(&pDamage->damage); + RegionUnion(&pDamage->damage, &pDamage->damage, + pDamageRegion); + if (!BOX_SAME (&tmpBox, RegionExtents(&pDamage->damage))) { + (*pDamage->damageReport) (pDamage, &pDamage->damage, + pDamage->closure); + } + break; + case DamageReportNonEmpty: + was_empty = !RegionNotEmpty(&pDamage->damage); + RegionUnion(&pDamage->damage, &pDamage->damage, + pDamageRegion); + if (was_empty && RegionNotEmpty(&pDamage->damage)) { + (*pDamage->damageReport) (pDamage, &pDamage->damage, + pDamage->closure); + } + break; + case DamageReportNone: + RegionUnion(&pDamage->damage, &pDamage->damage, + pDamageRegion); + break; + } +} + +static void +damageReportDamagePostRendering (DamagePtr pDamage, RegionPtr pOldDamage, RegionPtr pDamageRegion) +{ + BoxRec tmpBox; + RegionRec tmpRegion, newDamage; + Bool was_empty; + + RegionUnion(&newDamage, pOldDamage, pDamageRegion); + + switch (pDamage->damageLevel) { + case DamageReportRawRegion: + (*pDamage->damageReportPostRendering) (pDamage, pDamageRegion, pDamage->closure); + break; + case DamageReportDeltaRegion: + RegionNull(&tmpRegion); + RegionSubtract(&tmpRegion, pDamageRegion, pOldDamage); + if (RegionNotEmpty(&tmpRegion)) { + (*pDamage->damageReportPostRendering) (pDamage, &tmpRegion, pDamage->closure); + } + RegionUninit(&tmpRegion); + break; + case DamageReportBoundingBox: + tmpBox = *RegionExtents(pOldDamage); + if (!BOX_SAME (&tmpBox, RegionExtents(&newDamage))) { + (*pDamage->damageReportPostRendering) (pDamage, &newDamage, + pDamage->closure); + } + break; + case DamageReportNonEmpty: + was_empty = !RegionNotEmpty(pOldDamage); + if (was_empty && RegionNotEmpty(&newDamage)) { + (*pDamage->damageReportPostRendering) (pDamage, &newDamage, + pDamage->closure); + } + break; + case DamageReportNone: + break; + } + + RegionUninit(&newDamage); +} + +#if DAMAGE_DEBUG_ENABLE +static void +_damageRegionAppend (DrawablePtr pDrawable, RegionPtr pRegion, Bool clip, int subWindowMode, const char *where) +#define damageRegionAppend(d,r,c,m) _damageRegionAppend(d,r,c,m,__FUNCTION__) +#else +static void +damageRegionAppend (DrawablePtr pDrawable, RegionPtr pRegion, Bool clip, + int subWindowMode) +#endif +{ + ScreenPtr pScreen = pDrawable->pScreen; + damageScrPriv(pScreen); + drawableDamage(pDrawable); + DamagePtr pNext; + RegionRec clippedRec; + RegionPtr pDamageRegion; + RegionRec pixClip; + int draw_x, draw_y; +#ifdef COMPOSITE + int screen_x = 0, screen_y = 0; +#endif + + /* short circuit for empty regions */ + if (!RegionNotEmpty(pRegion)) + return; + +#ifdef COMPOSITE + /* + * When drawing to a pixmap which is storing window contents, + * the region presented is in pixmap relative coordinates which + * need to be converted to screen relative coordinates + */ + if (pDrawable->type != DRAWABLE_WINDOW) + { + screen_x = ((PixmapPtr) pDrawable)->screen_x - pDrawable->x; + screen_y = ((PixmapPtr) pDrawable)->screen_y - pDrawable->y; + } + if (screen_x || screen_y) + RegionTranslate(pRegion, screen_x, screen_y); +#endif + + if (pDrawable->type == DRAWABLE_WINDOW && + ((WindowPtr)(pDrawable))->backingStore == NotUseful) + { + if (subWindowMode == ClipByChildren) + { + RegionIntersect(pRegion, pRegion, + &((WindowPtr)(pDrawable))->clipList); + } + else if (subWindowMode == IncludeInferiors) + { + RegionPtr pTempRegion = + NotClippedByChildren((WindowPtr)(pDrawable)); + RegionIntersect(pRegion, pRegion, pTempRegion); + RegionDestroy(pTempRegion); + } + /* If subWindowMode is set to an invalid value, don't perform + * any drawable-based clipping. */ + } + + + RegionNull(&clippedRec); + for (; pDamage; pDamage = pNext) + { + pNext = pDamage->pNext; + /* + * Check for internal damage and don't send events + */ + if (pScrPriv->internalLevel > 0 && !pDamage->isInternal) + { + DAMAGE_DEBUG (("non internal damage, skipping at %d\n", + pScrPriv->internalLevel)); + continue; + } + /* + * Check for unrealized windows + */ + if (pDamage->pDrawable->type == DRAWABLE_WINDOW && + !((WindowPtr) (pDamage->pDrawable))->realized) + { + continue; + } + + draw_x = pDamage->pDrawable->x; + draw_y = pDamage->pDrawable->y; +#ifdef COMPOSITE + /* + * Need to move everyone to screen coordinates + * XXX what about off-screen pixmaps with non-zero x/y? + */ + if (!WindowDrawable(pDamage->pDrawable->type)) + { + draw_x += ((PixmapPtr) pDamage->pDrawable)->screen_x; + draw_y += ((PixmapPtr) pDamage->pDrawable)->screen_y; + } +#endif + + /* + * Clip against border or pixmap bounds + */ + + pDamageRegion = pRegion; + if (clip || pDamage->pDrawable != pDrawable) + { + pDamageRegion = &clippedRec; + if (pDamage->pDrawable->type == DRAWABLE_WINDOW) { + RegionIntersect(pDamageRegion, pRegion, + &((WindowPtr)(pDamage->pDrawable))->borderClip); + } else { + BoxRec box; + box.x1 = draw_x; + box.y1 = draw_y; + box.x2 = draw_x + pDamage->pDrawable->width; + box.y2 = draw_y + pDamage->pDrawable->height; + RegionInit(&pixClip, &box, 1); + RegionIntersect(pDamageRegion, pRegion, &pixClip); + RegionUninit(&pixClip); + } + /* + * Short circuit empty results + */ + if (!RegionNotEmpty(pDamageRegion)) + continue; + } + + DAMAGE_DEBUG (("%s %d x %d +%d +%d (target 0x%lx monitor 0x%lx)\n", + where, + pDamageRegion->extents.x2 - pDamageRegion->extents.x1, + pDamageRegion->extents.y2 - pDamageRegion->extents.y1, + pDamageRegion->extents.x1, pDamageRegion->extents.y1, + pDrawable->id, pDamage->pDrawable->id)); + + /* + * Move region to target coordinate space + */ + if (draw_x || draw_y) + RegionTranslate(pDamageRegion, -draw_x, -draw_y); + + /* Store damage region if needed after submission. */ + if (pDamage->reportAfter || pDamage->damageMarker) + RegionUnion(&pDamage->pendingDamage, + &pDamage->pendingDamage, pDamageRegion); + + /* Duplicate current damage if needed. */ + if (pDamage->damageMarker) + RegionCopy(&pDamage->backupDamage, &pDamage->damage); + + /* Report damage now, if desired. */ + if (!pDamage->reportAfter) { + if (pDamage->damageReport) + damageReportDamage (pDamage, pDamageRegion); + else + RegionUnion(&pDamage->damage, + &pDamage->damage, pDamageRegion); + } + + /* + * translate original region back + */ + if (pDamageRegion == pRegion && (draw_x || draw_y)) + RegionTranslate(pDamageRegion, draw_x, draw_y); + } +#ifdef COMPOSITE + if (screen_x || screen_y) + RegionTranslate(pRegion, -screen_x, -screen_y); +#endif + + RegionUninit(&clippedRec); +} + +static void +damageRegionProcessPending (DrawablePtr pDrawable) +{ + drawableDamage(pDrawable); + + for (; pDamage != NULL; pDamage = pDamage->pNext) + { + /* submit damage marker whenever possible. */ + if (pDamage->damageMarker) + (*pDamage->damageMarker) (pDrawable, pDamage, &pDamage->backupDamage, &pDamage->pendingDamage, pDamage->closure); + if (pDamage->reportAfter) { + /* It's possible that there is only interest in postRendering reporting. */ + if (pDamage->damageReport) + damageReportDamage (pDamage, &pDamage->pendingDamage); + else + RegionUnion(&pDamage->damage, &pDamage->damage, + &pDamage->pendingDamage); + } + + if (pDamage->reportAfter || pDamage->damageMarker) + RegionEmpty(&pDamage->pendingDamage); + if (pDamage->damageMarker) + RegionEmpty(&pDamage->backupDamage); + } + +} + +#if DAMAGE_DEBUG_ENABLE +#define damageDamageBox(d,b,m) _damageDamageBox(d,b,m,__FUNCTION__) +static void +_damageDamageBox (DrawablePtr pDrawable, BoxPtr pBox, int subWindowMode, const char *where) +#else +static void +damageDamageBox (DrawablePtr pDrawable, BoxPtr pBox, int subWindowMode) +#endif +{ + RegionRec region; + + RegionInit(®ion, pBox, 1); +#if DAMAGE_DEBUG_ENABLE + _damageRegionAppend (pDrawable, ®ion, TRUE, subWindowMode, where); +#else + damageRegionAppend (pDrawable, ®ion, TRUE, subWindowMode); +#endif + RegionUninit(®ion); +} + +static void damageValidateGC(GCPtr, unsigned long, DrawablePtr); +static void damageChangeGC(GCPtr, unsigned long); +static void damageCopyGC(GCPtr, unsigned long, GCPtr); +static void damageDestroyGC(GCPtr); +static void damageChangeClip(GCPtr, int, pointer, int); +static void damageDestroyClip(GCPtr); +static void damageCopyClip(GCPtr, GCPtr); + +static GCFuncs damageGCFuncs = { + damageValidateGC, damageChangeGC, damageCopyGC, damageDestroyGC, + damageChangeClip, damageDestroyClip, damageCopyClip +}; + +static GCOps damageGCOps; + +static Bool +damageCreateGC(GCPtr pGC) +{ + ScreenPtr pScreen = pGC->pScreen; + damageScrPriv(pScreen); + damageGCPriv(pGC); + Bool ret; + + unwrap (pScrPriv, pScreen, CreateGC); + if((ret = (*pScreen->CreateGC) (pGC))) { + pGCPriv->ops = NULL; + pGCPriv->funcs = pGC->funcs; + pGC->funcs = &damageGCFuncs; + } + wrap (pScrPriv, pScreen, CreateGC, damageCreateGC); + + return ret; +} + +#define DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable) \ + damageGCPriv(pGC); \ + GCFuncs *oldFuncs = pGC->funcs; \ + unwrap(pGCPriv, pGC, funcs); \ + unwrap(pGCPriv, pGC, ops); \ + +#define DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable) \ + wrap(pGCPriv, pGC, funcs, oldFuncs); \ + wrap(pGCPriv, pGC, ops, &damageGCOps) + +#define DAMAGE_GC_FUNC_PROLOGUE(pGC) \ + damageGCPriv(pGC); \ + unwrap(pGCPriv, pGC, funcs); \ + if (pGCPriv->ops) unwrap(pGCPriv, pGC, ops) + +#define DAMAGE_GC_FUNC_EPILOGUE(pGC) \ + wrap(pGCPriv, pGC, funcs, &damageGCFuncs); \ + if (pGCPriv->ops) wrap(pGCPriv, pGC, ops, &damageGCOps) + +static void +damageValidateGC(GCPtr pGC, + unsigned long changes, + DrawablePtr pDrawable) +{ + DAMAGE_GC_FUNC_PROLOGUE (pGC); + (*pGC->funcs->ValidateGC)(pGC, changes, pDrawable); + pGCPriv->ops = pGC->ops; /* just so it's not NULL */ + DAMAGE_GC_FUNC_EPILOGUE (pGC); +} + +static void +damageDestroyGC(GCPtr pGC) +{ + DAMAGE_GC_FUNC_PROLOGUE (pGC); + (*pGC->funcs->DestroyGC)(pGC); + DAMAGE_GC_FUNC_EPILOGUE (pGC); +} + +static void +damageChangeGC (GCPtr pGC, + unsigned long mask) +{ + DAMAGE_GC_FUNC_PROLOGUE (pGC); + (*pGC->funcs->ChangeGC) (pGC, mask); + DAMAGE_GC_FUNC_EPILOGUE (pGC); +} + +static void +damageCopyGC (GCPtr pGCSrc, + unsigned long mask, + GCPtr pGCDst) +{ + DAMAGE_GC_FUNC_PROLOGUE (pGCDst); + (*pGCDst->funcs->CopyGC) (pGCSrc, mask, pGCDst); + DAMAGE_GC_FUNC_EPILOGUE (pGCDst); +} + +static void +damageChangeClip (GCPtr pGC, + int type, + pointer pvalue, + int nrects) +{ + DAMAGE_GC_FUNC_PROLOGUE (pGC); + (*pGC->funcs->ChangeClip) (pGC, type, pvalue, nrects); + DAMAGE_GC_FUNC_EPILOGUE (pGC); +} + +static void +damageCopyClip(GCPtr pgcDst, GCPtr pgcSrc) +{ + DAMAGE_GC_FUNC_PROLOGUE (pgcDst); + (* pgcDst->funcs->CopyClip)(pgcDst, pgcSrc); + DAMAGE_GC_FUNC_EPILOGUE (pgcDst); +} + +static void +damageDestroyClip(GCPtr pGC) +{ + DAMAGE_GC_FUNC_PROLOGUE (pGC); + (* pGC->funcs->DestroyClip)(pGC); + DAMAGE_GC_FUNC_EPILOGUE (pGC); +} + +#define TRIM_BOX(box, pGC) if (pGC->pCompositeClip) { \ + BoxPtr extents = &pGC->pCompositeClip->extents;\ + if(box.x1 < extents->x1) box.x1 = extents->x1; \ + if(box.x2 > extents->x2) box.x2 = extents->x2; \ + if(box.y1 < extents->y1) box.y1 = extents->y1; \ + if(box.y2 > extents->y2) box.y2 = extents->y2; \ + } + +#define TRANSLATE_BOX(box, pDrawable) { \ + box.x1 += pDrawable->x; \ + box.x2 += pDrawable->x; \ + box.y1 += pDrawable->y; \ + box.y2 += pDrawable->y; \ + } + +#define TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC) { \ + TRANSLATE_BOX(box, pDrawable); \ + TRIM_BOX(box, pGC); \ + } + +#define BOX_NOT_EMPTY(box) \ + (((box.x2 - box.x1) > 0) && ((box.y2 - box.y1) > 0)) + +#define checkGCDamage(d,g) (getDrawableDamage(d) && \ + (!g->pCompositeClip ||\ + RegionNotEmpty(g->pCompositeClip))) + +#define TRIM_PICTURE_BOX(box, pDst) { \ + BoxPtr extents = &pDst->pCompositeClip->extents;\ + if(box.x1 < extents->x1) box.x1 = extents->x1; \ + if(box.x2 > extents->x2) box.x2 = extents->x2; \ + if(box.y1 < extents->y1) box.y1 = extents->y1; \ + if(box.y2 > extents->y2) box.y2 = extents->y2; \ + } + +#define checkPictureDamage(p) (getDrawableDamage(p->pDrawable) && \ + RegionNotEmpty(p->pCompositeClip)) + +static void +damageComposite (CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, + INT16 yDst, + CARD16 width, + CARD16 height) +{ + ScreenPtr pScreen = pDst->pDrawable->pScreen; + PictureScreenPtr ps = GetPictureScreen(pScreen); + damageScrPriv(pScreen); + + if (checkPictureDamage (pDst)) + { + BoxRec box; + + box.x1 = xDst + pDst->pDrawable->x; + box.y1 = yDst + pDst->pDrawable->y; + box.x2 = box.x1 + width; + box.y2 = box.y1 + height; + TRIM_PICTURE_BOX(box, pDst); + if (BOX_NOT_EMPTY(box)) + damageDamageBox (pDst->pDrawable, &box, pDst->subWindowMode); + } + unwrap (pScrPriv, ps, Composite); + (*ps->Composite) (op, + pSrc, + pMask, + pDst, + xSrc, + ySrc, + xMask, + yMask, + xDst, + yDst, + width, + height); + damageRegionProcessPending (pDst->pDrawable); + wrap (pScrPriv, ps, Composite, damageComposite); +} + +static void +damageGlyphs (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int nlist, + GlyphListPtr list, + GlyphPtr *glyphs) +{ + ScreenPtr pScreen = pDst->pDrawable->pScreen; + PictureScreenPtr ps = GetPictureScreen(pScreen); + damageScrPriv(pScreen); + + if (checkPictureDamage (pDst)) + { + int nlistTmp = nlist; + GlyphListPtr listTmp = list; + GlyphPtr *glyphsTmp = glyphs; + int x, y; + int n; + GlyphPtr glyph; + BoxRec box; + int x1, y1, x2, y2; + + box.x1 = 32767; + box.y1 = 32767; + box.x2 = -32767; + box.y2 = -32767; + x = pDst->pDrawable->x; + y = pDst->pDrawable->y; + while (nlistTmp--) + { + x += listTmp->xOff; + y += listTmp->yOff; + n = listTmp->len; + while (n--) + { + glyph = *glyphsTmp++; + x1 = x - glyph->info.x; + y1 = y - glyph->info.y; + x2 = x1 + glyph->info.width; + y2 = y1 + glyph->info.height; + if (x1 < box.x1) + box.x1 = x1; + if (y1 < box.y1) + box.y1 = y1; + if (x2 > box.x2) + box.x2 = x2; + if (y2 > box.y2) + box.y2 = y2; + x += glyph->info.xOff; + y += glyph->info.yOff; + } + listTmp++; + } + TRIM_PICTURE_BOX (box, pDst); + if (BOX_NOT_EMPTY(box)) + damageDamageBox (pDst->pDrawable, &box, pDst->subWindowMode); + } + unwrap (pScrPriv, ps, Glyphs); + (*ps->Glyphs) (op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, list, glyphs); + damageRegionProcessPending (pDst->pDrawable); + wrap (pScrPriv, ps, Glyphs, damageGlyphs); +} + +static void +damageAddTraps (PicturePtr pPicture, + INT16 x_off, + INT16 y_off, + int ntrap, + xTrap *traps) +{ + ScreenPtr pScreen = pPicture->pDrawable->pScreen; + PictureScreenPtr ps = GetPictureScreen(pScreen); + damageScrPriv(pScreen); + + if (checkPictureDamage (pPicture)) + { + BoxRec box; + int i; + int x, y; + xTrap *t = traps; + + box.x1 = 32767; + box.y1 = 32767; + box.x2 = -32767; + box.y2 = -32767; + x = pPicture->pDrawable->x + x_off; + y = pPicture->pDrawable->y + y_off; + for (i = 0; i < ntrap; i++) + { + pixman_fixed_t l = min (t->top.l, t->bot.l); + pixman_fixed_t r = max (t->top.r, t->bot.r); + int x1 = x + pixman_fixed_to_int (l); + int x2 = x + pixman_fixed_to_int (pixman_fixed_ceil (r)); + int y1 = y + pixman_fixed_to_int (t->top.y); + int y2 = y + pixman_fixed_to_int (pixman_fixed_ceil (t->bot.y)); + + if (x1 < box.x1) + box.x1 = x1; + if (x2 > box.x2) + box.x2 = x2; + if (y1 < box.y1) + box.y1 = y1; + if (y2 > box.y2) + box.y2 = y2; + } + TRIM_PICTURE_BOX (box, pPicture); + if (BOX_NOT_EMPTY(box)) + damageDamageBox (pPicture->pDrawable, &box, pPicture->subWindowMode); + } + unwrap (pScrPriv, ps, AddTraps); + (*ps->AddTraps) (pPicture, x_off, y_off, ntrap, traps); + damageRegionProcessPending (pPicture->pDrawable); + wrap (pScrPriv, ps, AddTraps, damageAddTraps); +} + +/**********************************************************/ + + +static void +damageFillSpans(DrawablePtr pDrawable, + GC *pGC, + int npt, + DDXPointPtr ppt, + int *pwidth, + int fSorted) +{ + DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); + + if (npt && checkGCDamage (pDrawable, pGC)) + { + int nptTmp = npt; + DDXPointPtr pptTmp = ppt; + int *pwidthTmp = pwidth; + BoxRec box; + + box.x1 = pptTmp->x; + box.x2 = box.x1 + *pwidthTmp; + box.y2 = box.y1 = pptTmp->y; + + while(--nptTmp) + { + pptTmp++; + pwidthTmp++; + if(box.x1 > pptTmp->x) box.x1 = pptTmp->x; + if(box.x2 < (pptTmp->x + *pwidthTmp)) + box.x2 = pptTmp->x + *pwidthTmp; + if(box.y1 > pptTmp->y) box.y1 = pptTmp->y; + else if(box.y2 < pptTmp->y) box.y2 = pptTmp->y; + } + + box.y2++; + + if(!pGC->miTranslate) { + TRANSLATE_BOX(box, pDrawable); + } + TRIM_BOX(box, pGC); + + if(BOX_NOT_EMPTY(box)) + damageDamageBox (pDrawable, &box, pGC->subWindowMode); + } + + (*pGC->ops->FillSpans)(pDrawable, pGC, npt, ppt, pwidth, fSorted); + + damageRegionProcessPending (pDrawable); + DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); +} + +static void +damageSetSpans(DrawablePtr pDrawable, + GCPtr pGC, + char *pcharsrc, + DDXPointPtr ppt, + int *pwidth, + int npt, + int fSorted) +{ + DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); + + if (npt && checkGCDamage (pDrawable, pGC)) + { + DDXPointPtr pptTmp = ppt; + int *pwidthTmp = pwidth; + int nptTmp = npt; + BoxRec box; + + box.x1 = pptTmp->x; + box.x2 = box.x1 + *pwidthTmp; + box.y2 = box.y1 = pptTmp->y; + + while(--nptTmp) + { + pptTmp++; + pwidthTmp++; + if(box.x1 > pptTmp->x) box.x1 = pptTmp->x; + if(box.x2 < (pptTmp->x + *pwidthTmp)) + box.x2 = pptTmp->x + *pwidthTmp; + if(box.y1 > pptTmp->y) box.y1 = pptTmp->y; + else if(box.y2 < pptTmp->y) box.y2 = pptTmp->y; + } + + box.y2++; + + if(!pGC->miTranslate) { + TRANSLATE_BOX(box, pDrawable); + } + TRIM_BOX(box, pGC); + + if(BOX_NOT_EMPTY(box)) + damageDamageBox (pDrawable, &box, pGC->subWindowMode); + } + (*pGC->ops->SetSpans)(pDrawable, pGC, pcharsrc, ppt, pwidth, npt, fSorted); + damageRegionProcessPending (pDrawable); + DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); +} + +static void +damagePutImage(DrawablePtr pDrawable, + GCPtr pGC, + int depth, + int x, + int y, + int w, + int h, + int leftPad, + int format, + char *pImage) +{ + DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); + if (checkGCDamage (pDrawable, pGC)) + { + BoxRec box; + + box.x1 = x + pDrawable->x; + box.x2 = box.x1 + w; + box.y1 = y + pDrawable->y; + box.y2 = box.y1 + h; + + TRIM_BOX(box, pGC); + if(BOX_NOT_EMPTY(box)) + damageDamageBox (pDrawable, &box, pGC->subWindowMode); + } + (*pGC->ops->PutImage)(pDrawable, pGC, depth, x, y, w, h, + leftPad, format, pImage); + damageRegionProcessPending (pDrawable); + DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); +} + +static RegionPtr +damageCopyArea(DrawablePtr pSrc, + DrawablePtr pDst, + GC *pGC, + int srcx, + int srcy, + int width, + int height, + int dstx, + int dsty) +{ + RegionPtr ret; + DAMAGE_GC_OP_PROLOGUE(pGC, pDst); + + if (checkGCDamage (pDst, pGC)) + { + BoxRec box; + + box.x1 = dstx + pDst->x; + box.x2 = box.x1 + width; + box.y1 = dsty + pDst->y; + box.y2 = box.y1 + height; + + TRIM_BOX(box, pGC); + if(BOX_NOT_EMPTY(box)) + damageDamageBox (pDst, &box, pGC->subWindowMode); + } + + ret = (*pGC->ops->CopyArea)(pSrc, pDst, + pGC, srcx, srcy, width, height, dstx, dsty); + damageRegionProcessPending (pDst); + DAMAGE_GC_OP_EPILOGUE(pGC, pDst); + return ret; +} + +static RegionPtr +damageCopyPlane(DrawablePtr pSrc, + DrawablePtr pDst, + GCPtr pGC, + int srcx, + int srcy, + int width, + int height, + int dstx, + int dsty, + unsigned long bitPlane) +{ + RegionPtr ret; + DAMAGE_GC_OP_PROLOGUE(pGC, pDst); + + if (checkGCDamage (pDst, pGC)) + { + BoxRec box; + + box.x1 = dstx + pDst->x; + box.x2 = box.x1 + width; + box.y1 = dsty + pDst->y; + box.y2 = box.y1 + height; + + TRIM_BOX(box, pGC); + if(BOX_NOT_EMPTY(box)) + damageDamageBox (pDst, &box, pGC->subWindowMode); + } + + ret = (*pGC->ops->CopyPlane)(pSrc, pDst, + pGC, srcx, srcy, width, height, dstx, dsty, bitPlane); + damageRegionProcessPending (pDst); + DAMAGE_GC_OP_EPILOGUE(pGC, pDst); + return ret; +} + +static void +damagePolyPoint(DrawablePtr pDrawable, + GCPtr pGC, + int mode, + int npt, + xPoint *ppt) +{ + DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); + + if (npt && checkGCDamage (pDrawable, pGC)) + { + BoxRec box; + int nptTmp = npt; + xPoint *pptTmp = ppt; + + box.x2 = box.x1 = pptTmp->x; + box.y2 = box.y1 = pptTmp->y; + + /* this could be slow if the points were spread out */ + + while(--nptTmp) + { + pptTmp++; + if(box.x1 > pptTmp->x) box.x1 = pptTmp->x; + else if(box.x2 < pptTmp->x) box.x2 = pptTmp->x; + if(box.y1 > pptTmp->y) box.y1 = pptTmp->y; + else if(box.y2 < pptTmp->y) box.y2 = pptTmp->y; + } + + box.x2++; + box.y2++; + + TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC); + if(BOX_NOT_EMPTY(box)) + damageDamageBox (pDrawable, &box, pGC->subWindowMode); + } + (*pGC->ops->PolyPoint)(pDrawable, pGC, mode, npt, ppt); + damageRegionProcessPending (pDrawable); + DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); +} + +static void +damagePolylines(DrawablePtr pDrawable, + GCPtr pGC, + int mode, + int npt, + DDXPointPtr ppt) +{ + DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); + + if (npt && checkGCDamage (pDrawable, pGC)) + { + int nptTmp = npt; + DDXPointPtr pptTmp = ppt; + BoxRec box; + int extra = pGC->lineWidth >> 1; + + box.x2 = box.x1 = pptTmp->x; + box.y2 = box.y1 = pptTmp->y; + + if(nptTmp > 1) + { + if(pGC->joinStyle == JoinMiter) + extra = 6 * pGC->lineWidth; + else if(pGC->capStyle == CapProjecting) + extra = pGC->lineWidth; + } + + if(mode == CoordModePrevious) + { + int x = box.x1; + int y = box.y1; + while(--nptTmp) + { + pptTmp++; + x += pptTmp->x; + y += pptTmp->y; + if(box.x1 > x) box.x1 = x; + else if(box.x2 < x) box.x2 = x; + if(box.y1 > y) box.y1 = y; + else if(box.y2 < y) box.y2 = y; + } + } + else + { + while(--nptTmp) + { + pptTmp++; + if(box.x1 > pptTmp->x) box.x1 = pptTmp->x; + else if(box.x2 < pptTmp->x) box.x2 = pptTmp->x; + if(box.y1 > pptTmp->y) box.y1 = pptTmp->y; + else if(box.y2 < pptTmp->y) box.y2 = pptTmp->y; + } + } + + box.x2++; + box.y2++; + + if(extra) + { + box.x1 -= extra; + box.x2 += extra; + box.y1 -= extra; + box.y2 += extra; + } + + TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC); + if(BOX_NOT_EMPTY(box)) + damageDamageBox (pDrawable, &box, pGC->subWindowMode); + } + (*pGC->ops->Polylines)(pDrawable, pGC, mode, npt, ppt); + damageRegionProcessPending (pDrawable); + DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); +} + +static void +damagePolySegment(DrawablePtr pDrawable, + GCPtr pGC, + int nSeg, + xSegment *pSeg) +{ + DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); + + if (nSeg && checkGCDamage (pDrawable, pGC)) + { + BoxRec box; + int extra = pGC->lineWidth; + int nsegTmp = nSeg; + xSegment *pSegTmp = pSeg; + + if(pGC->capStyle != CapProjecting) + extra >>= 1; + + if(pSegTmp->x2 > pSegTmp->x1) { + box.x1 = pSegTmp->x1; + box.x2 = pSegTmp->x2; + } else { + box.x2 = pSegTmp->x1; + box.x1 = pSegTmp->x2; + } + + if(pSegTmp->y2 > pSegTmp->y1) { + box.y1 = pSegTmp->y1; + box.y2 = pSegTmp->y2; + } else { + box.y2 = pSegTmp->y1; + box.y1 = pSegTmp->y2; + } + + while(--nsegTmp) + { + pSegTmp++; + if(pSegTmp->x2 > pSegTmp->x1) + { + if(pSegTmp->x1 < box.x1) box.x1 = pSegTmp->x1; + if(pSegTmp->x2 > box.x2) box.x2 = pSegTmp->x2; + } + else + { + if(pSegTmp->x2 < box.x1) box.x1 = pSegTmp->x2; + if(pSegTmp->x1 > box.x2) box.x2 = pSegTmp->x1; + } + if(pSegTmp->y2 > pSegTmp->y1) + { + if(pSegTmp->y1 < box.y1) box.y1 = pSegTmp->y1; + if(pSegTmp->y2 > box.y2) box.y2 = pSegTmp->y2; + } + else + { + if(pSegTmp->y2 < box.y1) box.y1 = pSegTmp->y2; + if(pSegTmp->y1 > box.y2) box.y2 = pSegTmp->y1; + } + } + + box.x2++; + box.y2++; + + if(extra) + { + box.x1 -= extra; + box.x2 += extra; + box.y1 -= extra; + box.y2 += extra; + } + + TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC); + if(BOX_NOT_EMPTY(box)) + damageDamageBox (pDrawable, &box, pGC->subWindowMode); + } + (*pGC->ops->PolySegment)(pDrawable, pGC, nSeg, pSeg); + damageRegionProcessPending (pDrawable); + DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); +} + +static void +damagePolyRectangle(DrawablePtr pDrawable, + GCPtr pGC, + int nRects, + xRectangle *pRects) +{ + DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); + + if (nRects && checkGCDamage (pDrawable, pGC)) + { + BoxRec box; + int offset1, offset2, offset3; + int nRectsTmp = nRects; + xRectangle *pRectsTmp = pRects; + + offset2 = pGC->lineWidth; + if(!offset2) offset2 = 1; + offset1 = offset2 >> 1; + offset3 = offset2 - offset1; + + while(nRectsTmp--) + { + box.x1 = pRectsTmp->x - offset1; + box.y1 = pRectsTmp->y - offset1; + box.x2 = box.x1 + pRectsTmp->width + offset2; + box.y2 = box.y1 + offset2; + TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC); + if(BOX_NOT_EMPTY(box)) + damageDamageBox (pDrawable, &box, pGC->subWindowMode); + + box.x1 = pRectsTmp->x - offset1; + box.y1 = pRectsTmp->y + offset3; + box.x2 = box.x1 + offset2; + box.y2 = box.y1 + pRectsTmp->height - offset2; + TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC); + if(BOX_NOT_EMPTY(box)) + damageDamageBox (pDrawable, &box, pGC->subWindowMode); + + box.x1 = pRectsTmp->x + pRectsTmp->width - offset1; + box.y1 = pRectsTmp->y + offset3; + box.x2 = box.x1 + offset2; + box.y2 = box.y1 + pRectsTmp->height - offset2; + TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC); + if(BOX_NOT_EMPTY(box)) + damageDamageBox (pDrawable, &box, pGC->subWindowMode); + + box.x1 = pRectsTmp->x - offset1; + box.y1 = pRectsTmp->y + pRectsTmp->height - offset1; + box.x2 = box.x1 + pRectsTmp->width + offset2; + box.y2 = box.y1 + offset2; + TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC); + if(BOX_NOT_EMPTY(box)) + damageDamageBox (pDrawable, &box, pGC->subWindowMode); + + pRectsTmp++; + } + } + (*pGC->ops->PolyRectangle)(pDrawable, pGC, nRects, pRects); + damageRegionProcessPending (pDrawable); + DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); +} + +static void +damagePolyArc(DrawablePtr pDrawable, + GCPtr pGC, + int nArcs, + xArc *pArcs) +{ + DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); + + if (nArcs && checkGCDamage (pDrawable, pGC)) + { + int extra = pGC->lineWidth >> 1; + BoxRec box; + int nArcsTmp = nArcs; + xArc *pArcsTmp = pArcs; + + box.x1 = pArcsTmp->x; + box.x2 = box.x1 + pArcsTmp->width; + box.y1 = pArcsTmp->y; + box.y2 = box.y1 + pArcsTmp->height; + + while(--nArcsTmp) + { + pArcsTmp++; + if(box.x1 > pArcsTmp->x) + box.x1 = pArcsTmp->x; + if(box.x2 < (pArcsTmp->x + pArcsTmp->width)) + box.x2 = pArcsTmp->x + pArcsTmp->width; + if(box.y1 > pArcsTmp->y) + box.y1 = pArcsTmp->y; + if(box.y2 < (pArcsTmp->y + pArcsTmp->height)) + box.y2 = pArcsTmp->y + pArcsTmp->height; + } + + if(extra) + { + box.x1 -= extra; + box.x2 += extra; + box.y1 -= extra; + box.y2 += extra; + } + + box.x2++; + box.y2++; + + TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC); + if(BOX_NOT_EMPTY(box)) + damageDamageBox (pDrawable, &box, pGC->subWindowMode); + } + (*pGC->ops->PolyArc)(pDrawable, pGC, nArcs, pArcs); + damageRegionProcessPending (pDrawable); + DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); +} + +static void +damageFillPolygon(DrawablePtr pDrawable, + GCPtr pGC, + int shape, + int mode, + int npt, + DDXPointPtr ppt) +{ + DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); + + if (npt > 2 && checkGCDamage (pDrawable, pGC)) + { + DDXPointPtr pptTmp = ppt; + int nptTmp = npt; + BoxRec box; + + box.x2 = box.x1 = pptTmp->x; + box.y2 = box.y1 = pptTmp->y; + + if(mode != CoordModeOrigin) + { + int x = box.x1; + int y = box.y1; + while(--nptTmp) + { + pptTmp++; + x += pptTmp->x; + y += pptTmp->y; + if(box.x1 > x) box.x1 = x; + else if(box.x2 < x) box.x2 = x; + if(box.y1 > y) box.y1 = y; + else if(box.y2 < y) box.y2 = y; + } + } + else + { + while(--nptTmp) + { + pptTmp++; + if(box.x1 > pptTmp->x) box.x1 = pptTmp->x; + else if(box.x2 < pptTmp->x) box.x2 = pptTmp->x; + if(box.y1 > pptTmp->y) box.y1 = pptTmp->y; + else if(box.y2 < pptTmp->y) box.y2 = pptTmp->y; + } + } + + box.x2++; + box.y2++; + + TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC); + if(BOX_NOT_EMPTY(box)) + damageDamageBox (pDrawable, &box, pGC->subWindowMode); + } + + (*pGC->ops->FillPolygon)(pDrawable, pGC, shape, mode, npt, ppt); + damageRegionProcessPending (pDrawable); + DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); +} + + +static void +damagePolyFillRect(DrawablePtr pDrawable, + GCPtr pGC, + int nRects, + xRectangle *pRects) +{ + DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); + if (nRects && checkGCDamage (pDrawable, pGC)) + { + BoxRec box; + xRectangle *pRectsTmp = pRects; + int nRectsTmp = nRects; + + box.x1 = pRectsTmp->x; + box.x2 = box.x1 + pRectsTmp->width; + box.y1 = pRectsTmp->y; + box.y2 = box.y1 + pRectsTmp->height; + + while(--nRectsTmp) + { + pRectsTmp++; + if(box.x1 > pRectsTmp->x) box.x1 = pRectsTmp->x; + if(box.x2 < (pRectsTmp->x + pRectsTmp->width)) + box.x2 = pRectsTmp->x + pRectsTmp->width; + if(box.y1 > pRectsTmp->y) box.y1 = pRectsTmp->y; + if(box.y2 < (pRectsTmp->y + pRectsTmp->height)) + box.y2 = pRectsTmp->y + pRectsTmp->height; + } + + TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC); + if(BOX_NOT_EMPTY(box)) + damageDamageBox (pDrawable, &box, pGC->subWindowMode); + } + (*pGC->ops->PolyFillRect)(pDrawable, pGC, nRects, pRects); + damageRegionProcessPending (pDrawable); + DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); +} + + +static void +damagePolyFillArc(DrawablePtr pDrawable, + GCPtr pGC, + int nArcs, + xArc *pArcs) +{ + DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); + + if (nArcs && checkGCDamage (pDrawable, pGC)) + { + BoxRec box; + int nArcsTmp = nArcs; + xArc *pArcsTmp = pArcs; + + box.x1 = pArcsTmp->x; + box.x2 = box.x1 + pArcsTmp->width; + box.y1 = pArcsTmp->y; + box.y2 = box.y1 + pArcsTmp->height; + + while(--nArcsTmp) + { + pArcsTmp++; + if(box.x1 > pArcsTmp->x) + box.x1 = pArcsTmp->x; + if(box.x2 < (pArcsTmp->x + pArcsTmp->width)) + box.x2 = pArcsTmp->x + pArcsTmp->width; + if(box.y1 > pArcsTmp->y) + box.y1 = pArcsTmp->y; + if(box.y2 < (pArcsTmp->y + pArcsTmp->height)) + box.y2 = pArcsTmp->y + pArcsTmp->height; + } + + TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC); + if(BOX_NOT_EMPTY(box)) + damageDamageBox (pDrawable, &box, pGC->subWindowMode); + } + (*pGC->ops->PolyFillArc)(pDrawable, pGC, nArcs, pArcs); + damageRegionProcessPending (pDrawable); + DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); +} + +/* + * general Poly/Image text function. Extract glyph information, + * compute bounding box and remove cursor if it is overlapped. + */ + +static void +damageDamageChars (DrawablePtr pDrawable, + FontPtr font, + int x, + int y, + unsigned int n, + CharInfoPtr *charinfo, + Bool imageblt, + int subWindowMode) +{ + ExtentInfoRec extents; + BoxRec box; + + QueryGlyphExtents(font, charinfo, n, &extents); + if (imageblt) + { + if (extents.overallWidth > extents.overallRight) + extents.overallRight = extents.overallWidth; + if (extents.overallWidth < extents.overallLeft) + extents.overallLeft = extents.overallWidth; + if (extents.overallLeft > 0) + extents.overallLeft = 0; + if (extents.fontAscent > extents.overallAscent) + extents.overallAscent = extents.fontAscent; + if (extents.fontDescent > extents.overallDescent) + extents.overallDescent = extents.fontDescent; + } + box.x1 = x + extents.overallLeft; + box.y1 = y - extents.overallAscent; + box.x2 = x + extents.overallRight; + box.y2 = y + extents.overallDescent; + damageDamageBox (pDrawable, &box, subWindowMode); +} + +/* + * values for textType: + */ +#define TT_POLY8 0 +#define TT_IMAGE8 1 +#define TT_POLY16 2 +#define TT_IMAGE16 3 + +static int +damageText (DrawablePtr pDrawable, + GCPtr pGC, + int x, + int y, + unsigned long count, + char *chars, + FontEncoding fontEncoding, + Bool textType) +{ + CharInfoPtr *charinfo; + CharInfoPtr *info; + unsigned long i; + unsigned int n; + int w; + Bool imageblt; + + imageblt = (textType == TT_IMAGE8) || (textType == TT_IMAGE16); + + charinfo = malloc(count * sizeof(CharInfoPtr)); + if (!charinfo) + return x; + + GetGlyphs(pGC->font, count, (unsigned char *)chars, + fontEncoding, &i, charinfo); + n = (unsigned int)i; + w = 0; + if (!imageblt) + for (info = charinfo; i--; info++) + w += (*info)->metrics.characterWidth; + + if (n != 0) { + damageDamageChars (pDrawable, pGC->font, x + pDrawable->x, y + pDrawable->y, n, + charinfo, imageblt, pGC->subWindowMode); + if (imageblt) + (*pGC->ops->ImageGlyphBlt)(pDrawable, pGC, x, y, n, charinfo, + FONTGLYPHS(pGC->font)); + else + (*pGC->ops->PolyGlyphBlt)(pDrawable, pGC, x, y, n, charinfo, + FONTGLYPHS(pGC->font)); + } + free(charinfo); + return x + w; +} + +static int +damagePolyText8(DrawablePtr pDrawable, + GCPtr pGC, + int x, + int y, + int count, + char *chars) +{ + DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); + + if (checkGCDamage (pDrawable, pGC)) + x = damageText (pDrawable, pGC, x, y, (unsigned long) count, chars, + Linear8Bit, TT_POLY8); + else + x = (*pGC->ops->PolyText8)(pDrawable, pGC, x, y, count, chars); + damageRegionProcessPending (pDrawable); + DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); + return x; +} + +static int +damagePolyText16(DrawablePtr pDrawable, + GCPtr pGC, + int x, + int y, + int count, + unsigned short *chars) +{ + DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); + + if (checkGCDamage (pDrawable, pGC)) + x = damageText (pDrawable, pGC, x, y, (unsigned long) count, (char *) chars, + FONTLASTROW(pGC->font) == 0 ? Linear16Bit : TwoD16Bit, + TT_POLY16); + else + x = (*pGC->ops->PolyText16)(pDrawable, pGC, x, y, count, chars); + damageRegionProcessPending (pDrawable); + DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); + return x; +} + +static void +damageImageText8(DrawablePtr pDrawable, + GCPtr pGC, + int x, + int y, + int count, + char *chars) +{ + DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); + + if (checkGCDamage (pDrawable, pGC)) + damageText (pDrawable, pGC, x, y, (unsigned long) count, chars, + Linear8Bit, TT_IMAGE8); + else + (*pGC->ops->ImageText8)(pDrawable, pGC, x, y, count, chars); + damageRegionProcessPending (pDrawable); + DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); +} + +static void +damageImageText16(DrawablePtr pDrawable, + GCPtr pGC, + int x, + int y, + int count, + unsigned short *chars) +{ + DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); + + if (checkGCDamage (pDrawable, pGC)) + damageText (pDrawable, pGC, x, y, (unsigned long) count, (char *) chars, + FONTLASTROW(pGC->font) == 0 ? Linear16Bit : TwoD16Bit, + TT_IMAGE16); + else + (*pGC->ops->ImageText16)(pDrawable, pGC, x, y, count, chars); + damageRegionProcessPending (pDrawable); + DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); +} + + +static void +damageImageGlyphBlt(DrawablePtr pDrawable, + GCPtr pGC, + int x, + int y, + unsigned int nglyph, + CharInfoPtr *ppci, + pointer pglyphBase) +{ + DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); + damageDamageChars (pDrawable, pGC->font, x + pDrawable->x, y + pDrawable->y, + nglyph, ppci, TRUE, pGC->subWindowMode); + (*pGC->ops->ImageGlyphBlt)(pDrawable, pGC, x, y, nglyph, + ppci, pglyphBase); + damageRegionProcessPending (pDrawable); + DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); +} + +static void +damagePolyGlyphBlt(DrawablePtr pDrawable, + GCPtr pGC, + int x, + int y, + unsigned int nglyph, + CharInfoPtr *ppci, + pointer pglyphBase) +{ + DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); + damageDamageChars (pDrawable, pGC->font, x + pDrawable->x, y + pDrawable->y, + nglyph, ppci, FALSE, pGC->subWindowMode); + (*pGC->ops->PolyGlyphBlt)(pDrawable, pGC, x, y, nglyph, + ppci, pglyphBase); + damageRegionProcessPending (pDrawable); + DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); +} + +static void +damagePushPixels(GCPtr pGC, + PixmapPtr pBitMap, + DrawablePtr pDrawable, + int dx, + int dy, + int xOrg, + int yOrg) +{ + DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); + if(checkGCDamage (pDrawable, pGC)) + { + BoxRec box; + + box.x1 = xOrg; + box.y1 = yOrg; + + if(!pGC->miTranslate) { + box.x1 += pDrawable->x; + box.y1 += pDrawable->y; + } + + box.x2 = box.x1 + dx; + box.y2 = box.y1 + dy; + + TRIM_BOX(box, pGC); + if(BOX_NOT_EMPTY(box)) + damageDamageBox (pDrawable, &box, pGC->subWindowMode); + } + (*pGC->ops->PushPixels)(pGC, pBitMap, pDrawable, dx, dy, xOrg, yOrg); + damageRegionProcessPending (pDrawable); + DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); +} + +static void +damageRemoveDamage (DamagePtr *pPrev, DamagePtr pDamage) +{ + while (*pPrev) + { + if (*pPrev == pDamage) + { + *pPrev = pDamage->pNext; + return; + } + pPrev = &(*pPrev)->pNext; + } +#if DAMAGE_VALIDATE_ENABLE + ErrorF ("Damage not on list\n"); + OsAbort (); +#endif +} + +static void +damageInsertDamage (DamagePtr *pPrev, DamagePtr pDamage) +{ +#if DAMAGE_VALIDATE_ENABLE + DamagePtr pOld; + + for (pOld = *pPrev; pOld; pOld = pOld->pNext) + if (pOld == pDamage) { + ErrorF ("Damage already on list\n"); + OsAbort (); + } +#endif + pDamage->pNext = *pPrev; + *pPrev = pDamage; +} + +static Bool +damageDestroyPixmap (PixmapPtr pPixmap) +{ + ScreenPtr pScreen = pPixmap->drawable.pScreen; + damageScrPriv(pScreen); + + if (pPixmap->refcnt == 1) + { + DamagePtr *pPrev = getPixmapDamageRef (pPixmap); + DamagePtr pDamage; + + while ((pDamage = *pPrev)) + { + damageRemoveDamage (pPrev, pDamage); + if (!pDamage->isWindow) + DamageDestroy (pDamage); + } + } + unwrap (pScrPriv, pScreen, DestroyPixmap); + (*pScreen->DestroyPixmap) (pPixmap); + wrap (pScrPriv, pScreen, DestroyPixmap, damageDestroyPixmap); + return TRUE; +} + +static void +damageCopyWindow(WindowPtr pWindow, + DDXPointRec ptOldOrg, + RegionPtr prgnSrc) +{ + ScreenPtr pScreen = pWindow->drawable.pScreen; + damageScrPriv(pScreen); + + if (getWindowDamage (pWindow)) + { + int dx = pWindow->drawable.x - ptOldOrg.x; + int dy = pWindow->drawable.y - ptOldOrg.y; + + /* + * The region comes in source relative, but the damage occurs + * at the destination location. Translate back and forth. + */ + RegionTranslate(prgnSrc, dx, dy); + damageRegionAppend (&pWindow->drawable, prgnSrc, FALSE, -1); + RegionTranslate(prgnSrc, -dx, -dy); + } + unwrap (pScrPriv, pScreen, CopyWindow); + (*pScreen->CopyWindow) (pWindow, ptOldOrg, prgnSrc); + damageRegionProcessPending (&pWindow->drawable); + wrap (pScrPriv, pScreen, CopyWindow, damageCopyWindow); +} + +static GCOps damageGCOps = { + damageFillSpans, damageSetSpans, + damagePutImage, damageCopyArea, + damageCopyPlane, damagePolyPoint, + damagePolylines, damagePolySegment, + damagePolyRectangle, damagePolyArc, + damageFillPolygon, damagePolyFillRect, + damagePolyFillArc, damagePolyText8, + damagePolyText16, damageImageText8, + damageImageText16, damageImageGlyphBlt, + damagePolyGlyphBlt, damagePushPixels, +}; + +static void +damageSetWindowPixmap (WindowPtr pWindow, PixmapPtr pPixmap) +{ + DamagePtr pDamage; + ScreenPtr pScreen = pWindow->drawable.pScreen; + damageScrPriv(pScreen); + + if ((pDamage = damageGetWinPriv(pWindow))) + { + PixmapPtr pOldPixmap = (*pScreen->GetWindowPixmap) (pWindow); + DamagePtr *pPrev = getPixmapDamageRef(pOldPixmap); + + while (pDamage) + { + damageRemoveDamage (pPrev, pDamage); + pDamage = pDamage->pNextWin; + } + } + unwrap (pScrPriv, pScreen, SetWindowPixmap); + (*pScreen->SetWindowPixmap) (pWindow, pPixmap); + wrap (pScrPriv, pScreen, SetWindowPixmap, damageSetWindowPixmap); + if ((pDamage = damageGetWinPriv(pWindow))) + { + DamagePtr *pPrev = getPixmapDamageRef(pPixmap); + + while (pDamage) + { + damageInsertDamage (pPrev, pDamage); + pDamage = pDamage->pNextWin; + } + } +} + +static Bool +damageDestroyWindow (WindowPtr pWindow) +{ + DamagePtr pDamage; + ScreenPtr pScreen = pWindow->drawable.pScreen; + Bool ret; + damageScrPriv(pScreen); + + while ((pDamage = damageGetWinPriv(pWindow))) + { + DamageUnregister (&pWindow->drawable, pDamage); + DamageDestroy (pDamage); + } + unwrap (pScrPriv, pScreen, DestroyWindow); + ret = (*pScreen->DestroyWindow) (pWindow); + wrap (pScrPriv, pScreen, DestroyWindow, damageDestroyWindow); + return ret; +} + +static Bool +damageCloseScreen (int i, ScreenPtr pScreen) +{ + damageScrPriv(pScreen); + + unwrap (pScrPriv, pScreen, DestroyPixmap); + unwrap (pScrPriv, pScreen, CreateGC); + unwrap (pScrPriv, pScreen, CopyWindow); + unwrap (pScrPriv, pScreen, CloseScreen); + free(pScrPriv); + return (*pScreen->CloseScreen) (i, pScreen); +} + +/** + * Default implementations of the damage management functions. + */ +void miDamageCreate (DamagePtr pDamage) +{ +} + +void miDamageRegister (DrawablePtr pDrawable, DamagePtr pDamage) +{ +} + +void miDamageUnregister (DrawablePtr pDrawable, DamagePtr pDamage) +{ +} + +void miDamageDestroy (DamagePtr pDamage) +{ +} + +/** + * Public functions for consumption outside this file. + */ + +Bool +DamageSetup (ScreenPtr pScreen) +{ + DamageScrPrivPtr pScrPriv; + PictureScreenPtr ps = GetPictureScreenIfSet(pScreen); + const DamageScreenFuncsRec miFuncs = { + miDamageCreate, miDamageRegister, miDamageUnregister, miDamageDestroy + }; + + if (!dixRegisterPrivateKey(&damageScrPrivateKeyRec, PRIVATE_SCREEN, 0)) + return FALSE; + + if (dixLookupPrivate(&pScreen->devPrivates, damageScrPrivateKey)) + return TRUE; + + if (!dixRegisterPrivateKey(&damageGCPrivateKeyRec, PRIVATE_GC, sizeof(DamageGCPrivRec))) + return FALSE; + + if (!dixRegisterPrivateKey(&damagePixPrivateKeyRec, PRIVATE_PIXMAP, 0)) + return FALSE; + + if (!dixRegisterPrivateKey(&damageWinPrivateKeyRec, PRIVATE_WINDOW, 0)) + return FALSE; + + pScrPriv = malloc(sizeof (DamageScrPrivRec)); + if (!pScrPriv) + return FALSE; + + pScrPriv->internalLevel = 0; + pScrPriv->pScreenDamage = 0; + + wrap (pScrPriv, pScreen, DestroyPixmap, damageDestroyPixmap); + wrap (pScrPriv, pScreen, CreateGC, damageCreateGC); + wrap (pScrPriv, pScreen, DestroyWindow, damageDestroyWindow); + wrap (pScrPriv, pScreen, SetWindowPixmap, damageSetWindowPixmap); + wrap (pScrPriv, pScreen, CopyWindow, damageCopyWindow); + wrap (pScrPriv, pScreen, CloseScreen, damageCloseScreen); + if (ps) { + wrap (pScrPriv, ps, Glyphs, damageGlyphs); + wrap (pScrPriv, ps, Composite, damageComposite); + wrap (pScrPriv, ps, AddTraps, damageAddTraps); + } + + pScrPriv->funcs = miFuncs; + + dixSetPrivate(&pScreen->devPrivates, damageScrPrivateKey, pScrPriv); + return TRUE; +} + +DamagePtr +DamageCreate (DamageReportFunc damageReport, + DamageDestroyFunc damageDestroy, + DamageReportLevel damageLevel, + Bool isInternal, + ScreenPtr pScreen, + void *closure) +{ + damageScrPriv(pScreen); + DamagePtr pDamage; + + pDamage = dixAllocateObjectWithPrivates(DamageRec, PRIVATE_DAMAGE); + if (!pDamage) + return 0; + pDamage->pNext = 0; + pDamage->pNextWin = 0; + RegionNull(&pDamage->damage); + RegionNull(&pDamage->pendingDamage); + + pDamage->damageLevel = damageLevel; + pDamage->isInternal = isInternal; + pDamage->closure = closure; + pDamage->isWindow = FALSE; + pDamage->pDrawable = 0; + pDamage->reportAfter = FALSE; + + pDamage->damageReport = damageReport; + pDamage->damageReportPostRendering = NULL; + pDamage->damageDestroy = damageDestroy; + pDamage->damageMarker = NULL; + pDamage->pScreen = pScreen; + + (*pScrPriv->funcs.Create) (pDamage); + + return pDamage; +} + +void +DamageRegister (DrawablePtr pDrawable, + DamagePtr pDamage) +{ + ScreenPtr pScreen = pDrawable->pScreen; + damageScrPriv(pScreen); + +#if DAMAGE_VALIDATE_ENABLE + if (pDrawable->pScreen != pDamage->pScreen) + { + ErrorF ("DamageRegister called with mismatched screens\n"); + OsAbort (); + } +#endif + + if (pDrawable->type == DRAWABLE_WINDOW) + { + WindowPtr pWindow = (WindowPtr) pDrawable; + winDamageRef(pWindow); + +#if DAMAGE_VALIDATE_ENABLE + DamagePtr pOld; + + for (pOld = *pPrev; pOld; pOld = pOld->pNextWin) + if (pOld == pDamage) { + ErrorF ("Damage already on window list\n"); + OsAbort (); + } +#endif + pDamage->pNextWin = *pPrev; + *pPrev = pDamage; + pDamage->isWindow = TRUE; + } + else + pDamage->isWindow = FALSE; + pDamage->pDrawable = pDrawable; + damageInsertDamage (getDrawableDamageRef (pDrawable), pDamage); + (*pScrPriv->funcs.Register) (pDrawable, pDamage); +} + +void +DamageDrawInternal (ScreenPtr pScreen, Bool enable) +{ + damageScrPriv (pScreen); + + pScrPriv->internalLevel += enable ? 1 : -1; +} + +void +DamageUnregister (DrawablePtr pDrawable, + DamagePtr pDamage) +{ + ScreenPtr pScreen = pDrawable->pScreen; + damageScrPriv(pScreen); + + (*pScrPriv->funcs.Unregister) (pDrawable, pDamage); + + if (pDrawable->type == DRAWABLE_WINDOW) + { + WindowPtr pWindow = (WindowPtr) pDrawable; + winDamageRef (pWindow); +#if DAMAGE_VALIDATE_ENABLE + int found = 0; +#endif + + while (*pPrev) + { + if (*pPrev == pDamage) + { + *pPrev = pDamage->pNextWin; +#if DAMAGE_VALIDATE_ENABLE + found = 1; +#endif + break; + } + pPrev = &(*pPrev)->pNextWin; + } +#if DAMAGE_VALIDATE_ENABLE + if (!found) { + ErrorF ("Damage not on window list\n"); + OsAbort (); + } +#endif + } + pDamage->pDrawable = 0; + damageRemoveDamage (getDrawableDamageRef (pDrawable), pDamage); +} + +void +DamageDestroy (DamagePtr pDamage) +{ + ScreenPtr pScreen = pDamage->pScreen; + damageScrPriv(pScreen); + + if (pDamage->damageDestroy) + (*pDamage->damageDestroy) (pDamage, pDamage->closure); + (*pScrPriv->funcs.Destroy) (pDamage); + RegionUninit(&pDamage->damage); + RegionUninit(&pDamage->pendingDamage); + dixFreeObjectWithPrivates(pDamage, PRIVATE_DAMAGE); +} + +Bool +DamageSubtract (DamagePtr pDamage, + const RegionPtr pRegion) +{ + RegionPtr pClip; + RegionRec pixmapClip; + DrawablePtr pDrawable = pDamage->pDrawable; + + RegionSubtract(&pDamage->damage, &pDamage->damage, pRegion); + if (pDrawable) + { + if (pDrawable->type == DRAWABLE_WINDOW) + pClip = &((WindowPtr) pDrawable)->borderClip; + else + { + BoxRec box; + + box.x1 = pDrawable->x; + box.y1 = pDrawable->y; + box.x2 = pDrawable->x + pDrawable->width; + box.y2 = pDrawable->y + pDrawable->height; + RegionInit(&pixmapClip, &box, 1); + pClip = &pixmapClip; + } + RegionTranslate(&pDamage->damage, pDrawable->x, pDrawable->y); + RegionIntersect(&pDamage->damage, &pDamage->damage, pClip); + RegionTranslate(&pDamage->damage, -pDrawable->x, -pDrawable->y); + if (pDrawable->type != DRAWABLE_WINDOW) + RegionUninit(&pixmapClip); + } + return RegionNotEmpty(&pDamage->damage); +} + +void +DamageEmpty (DamagePtr pDamage) +{ + RegionEmpty(&pDamage->damage); +} + +RegionPtr +DamageRegion (DamagePtr pDamage) +{ + return &pDamage->damage; +} + +RegionPtr +DamagePendingRegion (DamagePtr pDamage) +{ + return &pDamage->pendingDamage; +} + +void +DamageRegionAppend (DrawablePtr pDrawable, RegionPtr pRegion) +{ + damageRegionAppend (pDrawable, pRegion, FALSE, -1); +} + +void +DamageRegionProcessPending (DrawablePtr pDrawable) +{ + damageRegionProcessPending (pDrawable); +} + +/* If a damage marker is provided, then this function must be called after rendering is done. */ +/* Please do call back so any future enhancements can assume this function is called. */ +/* There are no strict timing requirements for calling this function, just as soon as (is cheaply) possible. */ +void +DamageRegionRendered (DrawablePtr pDrawable, DamagePtr pDamage, RegionPtr pOldDamage, RegionPtr pRegion) +{ + if (pDamage->damageReportPostRendering) + damageReportDamagePostRendering (pDamage, pOldDamage, pRegion); +} + +/* This call is very odd, i'm leaving it intact for API sake, but please don't use it. */ +void +DamageDamageRegion (DrawablePtr pDrawable, + RegionPtr pRegion) +{ + damageRegionAppend (pDrawable, pRegion, FALSE, -1); + + /* Go back and report this damage for DamagePtrs with reportAfter set, since + * this call isn't part of an in-progress drawing op in the call chain and + * the DDX probably just wants to know about it right away. + */ + damageRegionProcessPending (pDrawable); +} + +void +DamageSetReportAfterOp (DamagePtr pDamage, Bool reportAfter) +{ + pDamage->reportAfter = reportAfter; +} + +void +DamageSetPostRenderingFunctions(DamagePtr pDamage, DamageReportFunc damageReportPostRendering, + DamageMarkerFunc damageMarker) +{ + pDamage->damageReportPostRendering = damageReportPostRendering; + pDamage->damageMarker = damageMarker; +} + +DamageScreenFuncsPtr +DamageGetScreenFuncs (ScreenPtr pScreen) +{ + damageScrPriv(pScreen); + return &pScrPriv->funcs; +} diff --git a/xorg-server/os/Makefile.am b/xorg-server/os/Makefile.am index 3e4f2c591..91ca110f4 100644 --- a/xorg-server/os/Makefile.am +++ b/xorg-server/os/Makefile.am @@ -1,25 +1,18 @@ -noinst_LTLIBRARIES = libos.la liblog.la +noinst_LTLIBRARIES = libos.la AM_CFLAGS = $(DIX_CFLAGS) $(SHA1_CFLAGS) SECURERPC_SRCS = rpcauth.c XDMCP_SRCS = xdmcp.c STRLCAT_SRCS = strlcat.c strlcpy.c - -# Build a convenience library liblog.la that will be added into -# libos.la. The split is done so that log.c can be built with -# different compiler options. -liblog_la_SOURCES = log.c -# Add flags needed for proper backtraces of functions marked with GCC -# __attribute__((noreturn)). Currently those flags are needed for -# FatalError and AbortServer in log.c. -liblog_la_CFLAGS = $(AM_CFLAGS) $(ARM_BACKTRACE_CFLAGS) +XORG_SRCS = log.c libos_la_SOURCES = \ WaitFor.c \ access.c \ auth.c \ backtrace.c \ + client.c \ connection.c \ io.c \ mitauth.c \ @@ -32,8 +25,9 @@ libos_la_SOURCES = \ xdmauth.c \ xsha1.c \ xstrans.c \ - xprintf.c -libos_la_LIBADD = @SHA1_LIBS@ $(DLOPEN_LIBS) liblog.la + xprintf.c \ + $(XORG_SRCS) +libos_la_LIBADD = @SHA1_LIBS@ $(DLOPEN_LIBS) if SECURE_RPC libos_la_SOURCES += $(SECURERPC_SRCS) diff --git a/xorg-server/os/client.c b/xorg-server/os/client.c new file mode 100644 index 000000000..1311855d5 --- /dev/null +++ b/xorg-server/os/client.c @@ -0,0 +1,310 @@ +/* + * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). All + * rights reserved. + * Copyright (c) 1993, 2010, Oracle and/or its affiliates. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +/** + * @file + * + * This file contains functionality for identifying clients by various + * means. The primary purpose of identification is to simply aid in + * finding out which clients are using X server and how they are using + * it. For example, it's often necessary to monitor what requests + * clients are executing (to spot bad behaviour) and how they are + * allocating resources in X server (to spot excessive resource + * usage). + * + * This framework automatically allocates information, that can be + * used for client identification, when a client connects to the + * server. The information is freed when the client disconnects. The + * allocated information is just a collection of various IDs, such as + * PID and process name for local clients, that are likely to be + * useful in analyzing X server usage. + * + * Users of the framework can query ID information about clients at + * any time. To avoid repeated polling of IDs the users can also + * subscribe for notifications about the availability of ID + * information. IDs have been allocated before ClientStateCallback is + * called with ClientStateInitial state. Similarly the IDs will be + * released after ClientStateCallback is called with ClientStateGone + * state. + * + * Author: Rami Ylimäki <rami.ylimaki@vincit.fi> + */ + +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> + +#include "client.h" +#include "os.h" +#include "dixstruct.h" + +/** + * Try to determine a PID for a client from its connection + * information. This should be called only once when new client has + * connected, use GetClientPid to determine the PID at other times. + * + * @param[in] client Connection linked to some process. + * + * @return PID of the client. Error (-1) if PID can't be determined + * for the client. + * + * @see GetClientPid + */ +pid_t DetermineClientPid(struct _Client *client) +{ + LocalClientCredRec *lcc = NULL; + pid_t pid = -1; + + if (client == NullClient) + return pid; + + if (client == serverClient) + return getpid(); + + if (GetLocalClientCreds(client, &lcc) != -1) + { + if (lcc->fieldsSet & LCC_PID_SET) + pid = lcc->pid; + FreeLocalClientCreds(lcc); + } + + return pid; +} + +/** + * Try to determine a command line string for a client based on its + * PID. Note that mapping PID to a command hasn't been implemented for + * some operating systems. This should be called only once when a new + * client has connected, use GetClientCmdName/Args to determine the + * string at other times. + * + * @param[in] pid Process ID of a client. + + * @param[out] cmdname Client process name without arguments. You must + * release this by calling free. On error NULL is + * returned. Pass NULL if you aren't interested in + * this value. + * @param[out] cmdargs Arguments to client process. Useful for + * identifying a client that is executed from a + * launcher program. You must release this by + * calling free. On error NULL is returned. Pass + * NULL if you aren't interested in this value. + * + * @see GetClientCmdName/Args + */ +void DetermineClientCmd(pid_t pid, const char **cmdname, const char **cmdargs) +{ + char path[PATH_MAX + 1]; + int totsize = 0; + int cmdsize = 0; + int argsize = 0; + int fd = 0; + + if (cmdname) + *cmdname = NULL; + if (cmdargs) + *cmdargs = NULL; + + if (pid == -1) + return; + + /* Check if /proc/pid/cmdline exists. It's not supported on all + * operating systems. */ + if (snprintf(path, sizeof(path), "/proc/%d/cmdline", pid) < 0) + return; + fd = open(path, O_RDONLY); + if (fd < 0) + return; + + /* Read the contents of /proc/pid/cmdline. It should contain the + * process name and arguments. */ + totsize = read(fd, path, sizeof(path)); + if (totsize <= 0) + return; + if (close(fd) < 0) + return; + path[totsize - 1] = '\0'; + + /* Contruct the process name without arguments. */ + cmdsize = strlen(path) + 1; + if (cmdname) + { + char *name = malloc(cmdsize); + if (name) + { + strncpy(name, path, cmdsize); + name[cmdsize - 1] = '\0'; + *cmdname = name; + } + } + + /* Construct the arguments for client process. */ + argsize = totsize - cmdsize; + if (cmdargs && (argsize > 0)) + { + char *args = malloc(argsize); + if (args) + { + int i = 0; + for (i = 0; i < (argsize - 1); ++i) + { + const char c = path[cmdsize + i]; + args[i] = (c == '\0') ? ' ' : c; + } + args[argsize - 1] = '\0'; + *cmdargs = args; + } + } +} + +/** + * Called when a new client connects. Allocates client ID information. + * + * @param[in] client Recently connected client. + */ +void ReserveClientIds(struct _Client *client) +{ +#ifdef CLIENTIDS + if (client == NullClient) + return; + + assert(!client->clientIds); + client->clientIds = calloc(1, sizeof(ClientIdRec)); + if (!client->clientIds) + return; + + client->clientIds->pid = DetermineClientPid(client); + if (client->clientIds->pid != -1) + DetermineClientCmd(client->clientIds->pid, &client->clientIds->cmdname, &client->clientIds->cmdargs); + + DebugF("client(%lx): Reserved pid(%d).\n", + client->clientAsMask, client->clientIds->pid); + DebugF("client(%lx): Reserved cmdname(%s) and cmdargs(%s).\n", + client->clientAsMask, + client->clientIds->cmdname ? client->clientIds->cmdname : "NULL", + client->clientIds->cmdargs ? client->clientIds->cmdargs : "NULL"); +#endif /* CLIENTIDS */ +} + +/** + * Called when an existing client disconnects. Frees client ID + * information. + * + * @param[in] client Recently disconnected client. + */ +void ReleaseClientIds(struct _Client *client) +{ +#ifdef CLIENTIDS + if (client == NullClient) + return; + + if (!client->clientIds) + return; + + DebugF("client(%lx): Released pid(%d).\n", + client->clientAsMask, client->clientIds->pid); + DebugF("client(%lx): Released cmdline(%s) and cmdargs(%s).\n", + client->clientAsMask, + client->clientIds->cmdname ? client->clientIds->cmdname : "NULL", + client->clientIds->cmdargs ? client->clientIds->cmdargs : "NULL"); + + free((void *) client->clientIds->cmdname); /* const char * */ + free((void *) client->clientIds->cmdargs); /* const char * */ + free(client->clientIds); + client->clientIds = NULL; +#endif /* CLIENTIDS */ +} + +/** + * Get cached PID of a client. + * + * param[in] client Client whose PID has been already cached. + * + * @return Cached client PID. Error (-1) if called: + * - before ClientStateInitial client state notification + * - after ClientStateGone client state notification + * - for remote clients + * + * @see DetermineClientPid + */ +pid_t GetClientPid(struct _Client *client) +{ + if (client == NullClient) + return -1; + + if (!client->clientIds) + return -1; + + return client->clientIds->pid; +} + +/** + * Get cached command name string of a client. + * + * param[in] client Client whose command line string has been already + * cached. + * + * @return Cached client command name. Error (NULL) if called: + * - before ClientStateInitial client state notification + * - after ClientStateGone client state notification + * - for remote clients + * - on OS that doesn't support mapping of PID to command line + * + * @see DetermineClientCmd + */ +const char *GetClientCmdName(struct _Client *client) +{ + if (client == NullClient) + return NULL; + + if (!client->clientIds) + return NULL; + + return client->clientIds->cmdname; +} + +/** + * Get cached command arguments string of a client. + * + * param[in] client Client whose command line string has been already + * cached. + * + * @return Cached client command arguments. Error (NULL) if called: + * - before ClientStateInitial client state notification + * - after ClientStateGone client state notification + * - for remote clients + * - on OS that doesn't support mapping of PID to command line + * + * @see DetermineClientCmd + */ +const char *GetClientCmdArgs(struct _Client *client) +{ + if (client == NullClient) + return NULL; + + if (!client->clientIds) + return NULL; + + return client->clientIds->cmdargs; +} diff --git a/xorg-server/record/record.c b/xorg-server/record/record.c index facaebb02..df3f9c6ec 100644 --- a/xorg-server/record/record.c +++ b/xorg-server/record/record.c @@ -807,6 +807,7 @@ RecordADeviceEvent(CallbackListPtr *pcbl, pointer nulldata, pointer calldata) RecordContextPtr pContext; RecordClientsAndProtocolPtr pRCAP; int eci; /* enabled context index */ + int count; for (eci = 0; eci < numEnabledContexts; eci++) { @@ -821,9 +822,11 @@ RecordADeviceEvent(CallbackListPtr *pcbl, pointer nulldata, pointer calldata) /* TODO check return values */ if (IsMaster(pei->device)) { - xEvent xE; - EventToCore(pei->event, &xE); - RecordSendProtocolEvents(pRCAP, pContext, &xE, 1); + xEvent *core_events; + EventToCore(pei->event, &core_events, &count); + RecordSendProtocolEvents(pRCAP, pContext, core_events, + count); + free(core_events); } EventToXI(pei->event, &xi_events, &count); diff --git a/xorg-server/render/mipict.c b/xorg-server/render/mipict.c index 56d874e25..3b7388879 100644 --- a/xorg-server/render/mipict.c +++ b/xorg-server/render/mipict.c @@ -1,644 +1,644 @@ -/*
- *
- * Copyright © 1999 Keith Packard
- *
- * Permission to use, copy, modify, distribute, and sell this software and its
- * documentation for any purpose is hereby granted without fee, provided that
- * the above copyright notice appear in all copies and that both that
- * copyright notice and this permission notice appear in supporting
- * documentation, and that the name of Keith Packard not be used in
- * advertising or publicity pertaining to distribution of the software without
- * specific, written prior permission. Keith Packard makes no
- * representations about the suitability of this software for any purpose. It
- * is provided "as is" without express or implied warranty.
- *
- * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
- * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
- * CONSEQUENTIAL DAMAGES OR ANY 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 THIS SOFTWARE.
- */
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#include "scrnintstr.h"
-#include "gcstruct.h"
-#include "pixmapstr.h"
-#include "windowstr.h"
-#include "mi.h"
-#include "picturestr.h"
-#include "mipict.h"
-
-#ifndef __GNUC__
-#define __inline
-#endif
-
-int
-miCreatePicture (PicturePtr pPicture)
-{
- return Success;
-}
-
-void
-miDestroyPicture (PicturePtr pPicture)
-{
- if (pPicture->freeCompClip)
- RegionDestroy(pPicture->pCompositeClip);
-}
-
-void
-miDestroyPictureClip (PicturePtr pPicture)
-{
- switch (pPicture->clientClipType) {
- case CT_NONE:
- return;
- case CT_PIXMAP:
- (*pPicture->pDrawable->pScreen->DestroyPixmap) ((PixmapPtr) (pPicture->clientClip));
- break;
- default:
- /*
- * we know we'll never have a list of rectangles, since ChangeClip
- * immediately turns them into a region
- */
- RegionDestroy(pPicture->clientClip);
- break;
- }
- pPicture->clientClip = NULL;
- pPicture->clientClipType = CT_NONE;
-}
-
-int
-miChangePictureClip (PicturePtr pPicture,
- int type,
- pointer value,
- int n)
-{
- ScreenPtr pScreen = pPicture->pDrawable->pScreen;
- PictureScreenPtr ps = GetPictureScreen(pScreen);
- pointer clientClip;
- int clientClipType;
-
- switch (type) {
- case CT_PIXMAP:
- /* convert the pixmap to a region */
- clientClip = (pointer) BitmapToRegion(pScreen, (PixmapPtr) value);
- if (!clientClip)
- return BadAlloc;
- clientClipType = CT_REGION;
- (*pScreen->DestroyPixmap) ((PixmapPtr) value);
- break;
- case CT_REGION:
- clientClip = value;
- clientClipType = CT_REGION;
- break;
- case CT_NONE:
- clientClip = 0;
- clientClipType = CT_NONE;
- break;
- default:
- clientClip = (pointer) RegionFromRects(n,
- (xRectangle *) value,
- type);
- if (!clientClip)
- return BadAlloc;
- clientClipType = CT_REGION;
- free(value);
- break;
- }
- (*ps->DestroyPictureClip) (pPicture);
- pPicture->clientClip = clientClip;
- pPicture->clientClipType = clientClipType;
- pPicture->stateChanges |= CPClipMask;
- return Success;
-}
-
-void
-miChangePicture (PicturePtr pPicture,
- Mask mask)
-{
- return;
-}
-
-void
-miValidatePicture (PicturePtr pPicture,
- Mask mask)
-{
- DrawablePtr pDrawable = pPicture->pDrawable;
-
- if ((mask & (CPClipXOrigin|CPClipYOrigin|CPClipMask|CPSubwindowMode)) ||
- (pDrawable->serialNumber != (pPicture->serialNumber & DRAWABLE_SERIAL_BITS)))
- {
- if (pDrawable->type == DRAWABLE_WINDOW)
- {
- WindowPtr pWin = (WindowPtr) pDrawable;
- RegionPtr pregWin;
- Bool freeTmpClip, freeCompClip;
-
- if (pPicture->subWindowMode == IncludeInferiors)
- {
- pregWin = NotClippedByChildren(pWin);
- freeTmpClip = TRUE;
- }
- else
- {
- pregWin = &pWin->clipList;
- freeTmpClip = FALSE;
- }
- freeCompClip = pPicture->freeCompClip;
-
- /*
- * if there is no client clip, we can get by with just keeping the
- * pointer we got, and remembering whether or not should destroy
- * (or maybe re-use) it later. this way, we avoid unnecessary
- * copying of regions. (this wins especially if many clients clip
- * by children and have no client clip.)
- */
- if (pPicture->clientClipType == CT_NONE)
- {
- if (freeCompClip)
- RegionDestroy(pPicture->pCompositeClip);
- pPicture->pCompositeClip = pregWin;
- pPicture->freeCompClip = freeTmpClip;
- }
- else
- {
- /*
- * we need one 'real' region to put into the composite clip. if
- * pregWin the current composite clip are real, we can get rid of
- * one. if pregWin is real and the current composite clip isn't,
- * use pregWin for the composite clip. if the current composite
- * clip is real and pregWin isn't, use the current composite
- * clip. if neither is real, create a new region.
- */
-
- RegionTranslate(pPicture->clientClip,
- pDrawable->x + pPicture->clipOrigin.x,
- pDrawable->y + pPicture->clipOrigin.y);
-
- if (freeCompClip)
- {
- RegionIntersect(pPicture->pCompositeClip,
- pregWin, pPicture->clientClip);
- if (freeTmpClip)
- RegionDestroy(pregWin);
- }
- else if (freeTmpClip)
- {
- RegionIntersect(pregWin, pregWin, pPicture->clientClip);
- pPicture->pCompositeClip = pregWin;
- }
- else
- {
- pPicture->pCompositeClip = RegionCreate(NullBox, 0);
- RegionIntersect(pPicture->pCompositeClip,
- pregWin, pPicture->clientClip);
- }
- pPicture->freeCompClip = TRUE;
- RegionTranslate(pPicture->clientClip,
- -(pDrawable->x + pPicture->clipOrigin.x),
- -(pDrawable->y + pPicture->clipOrigin.y));
- }
- } /* end of composite clip for a window */
- else
- {
- BoxRec pixbounds;
-
- /* XXX should we translate by drawable.x/y here ? */
- /* If you want pixmaps in offscreen memory, yes */
- pixbounds.x1 = pDrawable->x;
- pixbounds.y1 = pDrawable->y;
- pixbounds.x2 = pDrawable->x + pDrawable->width;
- pixbounds.y2 = pDrawable->y + pDrawable->height;
-
- if (pPicture->freeCompClip)
- {
- RegionReset(pPicture->pCompositeClip, &pixbounds);
- }
- else
- {
- pPicture->freeCompClip = TRUE;
- pPicture->pCompositeClip = RegionCreate(&pixbounds, 1);
- }
-
- if (pPicture->clientClipType == CT_REGION)
- {
- if(pDrawable->x || pDrawable->y) {
- RegionTranslate(pPicture->clientClip,
- pDrawable->x + pPicture->clipOrigin.x,
- pDrawable->y + pPicture->clipOrigin.y);
- RegionIntersect(pPicture->pCompositeClip,
- pPicture->pCompositeClip, pPicture->clientClip);
- RegionTranslate(pPicture->clientClip,
- -(pDrawable->x + pPicture->clipOrigin.x),
- -(pDrawable->y + pPicture->clipOrigin.y));
- } else {
- RegionTranslate(pPicture->pCompositeClip,
- -pPicture->clipOrigin.x, -pPicture->clipOrigin.y);
- RegionIntersect(pPicture->pCompositeClip,
- pPicture->pCompositeClip, pPicture->clientClip);
- RegionTranslate(pPicture->pCompositeClip,
- pPicture->clipOrigin.x, pPicture->clipOrigin.y);
- }
- }
- } /* end of composite clip for pixmap */
- }
-}
-
-int
-miChangePictureTransform (PicturePtr pPicture,
- PictTransform *transform)
-{
- return Success;
-}
-
-int
-miChangePictureFilter (PicturePtr pPicture,
- int filter,
- xFixed *params,
- int nparams)
-{
- return Success;
-}
-
-#define BOUND(v) (INT16) ((v) < MINSHORT ? MINSHORT : (v) > MAXSHORT ? MAXSHORT : (v))
-
-static inline pixman_bool_t
-miClipPictureReg (pixman_region16_t * pRegion,
- pixman_region16_t * pClip,
- int dx,
- int dy)
-{
- if (pixman_region_n_rects(pRegion) == 1 &&
- pixman_region_n_rects(pClip) == 1)
- {
- pixman_box16_t * pRbox = pixman_region_rectangles(pRegion, NULL);
- pixman_box16_t * pCbox = pixman_region_rectangles(pClip, NULL);
- int v;
-
- if (pRbox->x1 < (v = pCbox->x1 + dx))
- pRbox->x1 = BOUND(v);
- if (pRbox->x2 > (v = pCbox->x2 + dx))
- pRbox->x2 = BOUND(v);
- if (pRbox->y1 < (v = pCbox->y1 + dy))
- pRbox->y1 = BOUND(v);
- if (pRbox->y2 > (v = pCbox->y2 + dy))
- pRbox->y2 = BOUND(v);
- if (pRbox->x1 >= pRbox->x2 ||
- pRbox->y1 >= pRbox->y2)
- {
- pixman_region_init (pRegion);
- }
- }
- else if (!pixman_region_not_empty (pClip))
- return FALSE;
- else
- {
- if (dx || dy)
- pixman_region_translate (pRegion, -dx, -dy);
- if (!pixman_region_intersect (pRegion, pRegion, pClip))
- return FALSE;
- if (dx || dy)
- pixman_region_translate(pRegion, dx, dy);
- }
- return pixman_region_not_empty(pRegion);
-}
-
-static __inline Bool
-miClipPictureSrc (RegionPtr pRegion,
- PicturePtr pPicture,
- int dx,
- int dy)
-{
- if (pPicture->clientClipType != CT_NONE)
- {
- Bool result;
-
- pixman_region_translate ( pPicture->clientClip,
- pPicture->clipOrigin.x + dx,
- pPicture->clipOrigin.y + dy);
-
- result = RegionIntersect(pRegion, pRegion, pPicture->clientClip);
-
- pixman_region_translate ( pPicture->clientClip,
- - (pPicture->clipOrigin.x + dx),
- - (pPicture->clipOrigin.y + dy));
-
- if (!result)
- return FALSE;
- }
- return TRUE;
-}
-
-void
-miCompositeSourceValidate (PicturePtr pPicture,
- INT16 x,
- INT16 y,
- CARD16 width,
- CARD16 height)
-{
- DrawablePtr pDrawable = pPicture->pDrawable;
- ScreenPtr pScreen;
-
- if (!pDrawable)
- return;
-
- pScreen = pDrawable->pScreen;
-
- if (pScreen->SourceValidate)
- {
- if (pPicture->transform)
- {
- xPoint points[4];
- int i;
- int xmin, ymin, xmax, ymax;
-
-#define VectorSet(i,_x,_y) { points[i].x = _x; points[i].y = _y; }
- VectorSet (0, x, y);
- VectorSet (1, x + width, y);
- VectorSet (2, x, y + height);
- VectorSet (3, x + width, y + height);
- xmin = ymin = 32767;
- xmax = ymax = -32737;
- for (i = 0; i < 4; i++)
- {
- PictVector t;
- t.vector[0] = IntToxFixed (points[i].x);
- t.vector[1] = IntToxFixed (points[i].y);
- t.vector[2] = xFixed1;
- if (pixman_transform_point (pPicture->transform, &t))
- {
- int tx = xFixedToInt (t.vector[0]);
- int ty = xFixedToInt (t.vector[1]);
- if (tx < xmin) xmin = tx;
- if (tx > xmax) xmax = tx;
- if (ty < ymin) ymin = ty;
- if (ty > ymax) ymax = ty;
- }
- }
- x = xmin;
- y = ymin;
- width = xmax - xmin;
- height = ymax - ymin;
- }
- x += pPicture->pDrawable->x;
- y += pPicture->pDrawable->y;
- (*pScreen->SourceValidate) (pDrawable, x, y, width, height,
- pPicture->subWindowMode);
- }
-}
-
-/*
- * returns FALSE if the final region is empty. Indistinguishable from
- * an allocation failure, but rendering ignores those anyways.
- */
-
-Bool
-miComputeCompositeRegion (RegionPtr pRegion,
- PicturePtr pSrc,
- PicturePtr pMask,
- PicturePtr pDst,
- INT16 xSrc,
- INT16 ySrc,
- INT16 xMask,
- INT16 yMask,
- INT16 xDst,
- INT16 yDst,
- CARD16 width,
- CARD16 height)
-{
-
- int v;
-
- pRegion->extents.x1 = xDst;
- v = xDst + width;
- pRegion->extents.x2 = BOUND(v);
- pRegion->extents.y1 = yDst;
- v = yDst + height;
- pRegion->extents.y2 = BOUND(v);
- pRegion->data = 0;
- /* Check for empty operation */
- if (pRegion->extents.x1 >= pRegion->extents.x2 ||
- pRegion->extents.y1 >= pRegion->extents.y2)
- {
- pixman_region_init (pRegion);
- return FALSE;
- }
- /* clip against dst */
- if (!miClipPictureReg (pRegion, pDst->pCompositeClip, 0, 0))
- {
- pixman_region_fini (pRegion);
- return FALSE;
- }
- if (pDst->alphaMap)
- {
- if (!miClipPictureReg (pRegion, pDst->alphaMap->pCompositeClip,
- -pDst->alphaOrigin.x,
- -pDst->alphaOrigin.y))
- {
- pixman_region_fini (pRegion);
- return FALSE;
- }
- }
- /* clip against src */
- if (!miClipPictureSrc (pRegion, pSrc, xDst - xSrc, yDst - ySrc))
- {
- pixman_region_fini (pRegion);
- return FALSE;
- }
- if (pSrc->alphaMap)
- {
- if (!miClipPictureSrc (pRegion, pSrc->alphaMap,
- xDst - (xSrc - pSrc->alphaOrigin.x),
- yDst - (ySrc - pSrc->alphaOrigin.y)))
- {
- pixman_region_fini (pRegion);
- return FALSE;
- }
- }
- /* clip against mask */
- if (pMask)
- {
- if (!miClipPictureSrc (pRegion, pMask, xDst - xMask, yDst - yMask))
- {
- pixman_region_fini (pRegion);
- return FALSE;
- }
- if (pMask->alphaMap)
- {
- if (!miClipPictureSrc (pRegion, pMask->alphaMap,
- xDst - (xMask - pMask->alphaOrigin.x),
- yDst - (yMask - pMask->alphaOrigin.y)))
- {
- pixman_region_fini (pRegion);
- return FALSE;
- }
- }
- }
-
-
- miCompositeSourceValidate (pSrc, xSrc, ySrc, width, height);
- if (pMask)
- miCompositeSourceValidate (pMask, xMask, yMask, width, height);
-
- return TRUE;
-}
-
-void
-miRenderColorToPixel (PictFormatPtr format,
- xRenderColor *color,
- CARD32 *pixel)
-{
- CARD32 r, g, b, a;
- miIndexedPtr pIndexed;
-
- switch (format->type) {
- case PictTypeDirect:
- r = color->red >> (16 - Ones (format->direct.redMask));
- g = color->green >> (16 - Ones (format->direct.greenMask));
- b = color->blue >> (16 - Ones (format->direct.blueMask));
- a = color->alpha >> (16 - Ones (format->direct.alphaMask));
- r = r << format->direct.red;
- g = g << format->direct.green;
- b = b << format->direct.blue;
- a = a << format->direct.alpha;
- *pixel = r|g|b|a;
- break;
- case PictTypeIndexed:
- pIndexed = (miIndexedPtr) (format->index.devPrivate);
- if (pIndexed->color)
- {
- r = color->red >> 11;
- g = color->green >> 11;
- b = color->blue >> 11;
- *pixel = miIndexToEnt15 (pIndexed, (r << 10) | (g << 5) | b);
- }
- else
- {
- r = color->red >> 8;
- g = color->green >> 8;
- b = color->blue >> 8;
- *pixel = miIndexToEntY24 (pIndexed, (r << 16) | (g << 8) | b);
- }
- break;
- }
-}
-
-static CARD16
-miFillColor (CARD32 pixel, int bits)
-{
- while (bits < 16)
- {
- pixel |= pixel << bits;
- bits <<= 1;
- }
- return (CARD16) pixel;
-}
-
-Bool
-miIsSolidAlpha (PicturePtr pSrc)
-{
- ScreenPtr pScreen;
- char line[1];
-
- if (!pSrc->pDrawable)
- return FALSE;
-
- pScreen = pSrc->pDrawable->pScreen;
-
- /* Alpha-only */
- if (PICT_FORMAT_TYPE (pSrc->format) != PICT_TYPE_A)
- return FALSE;
- /* repeat */
- if (!pSrc->repeat)
- return FALSE;
- /* 1x1 */
- if (pSrc->pDrawable->width != 1 || pSrc->pDrawable->height != 1)
- return FALSE;
- line[0] = 1;
- (*pScreen->GetImage) (pSrc->pDrawable, 0, 0, 1, 1, ZPixmap, ~0L, line);
- switch (pSrc->pDrawable->bitsPerPixel) {
- case 1:
- return (CARD8) line[0] == 1 || (CARD8) line[0] == 0x80;
- case 4:
- return (CARD8) line[0] == 0xf || (CARD8) line[0] == 0xf0;
- case 8:
- return (CARD8) line[0] == 0xff;
- default:
- return FALSE;
- }
-}
-
-void
-miRenderPixelToColor (PictFormatPtr format,
- CARD32 pixel,
- xRenderColor *color)
-{
- CARD32 r, g, b, a;
- miIndexedPtr pIndexed;
-
- switch (format->type) {
- case PictTypeDirect:
- r = (pixel >> format->direct.red) & format->direct.redMask;
- g = (pixel >> format->direct.green) & format->direct.greenMask;
- b = (pixel >> format->direct.blue) & format->direct.blueMask;
- a = (pixel >> format->direct.alpha) & format->direct.alphaMask;
- color->red = miFillColor (r, Ones (format->direct.redMask));
- color->green = miFillColor (g, Ones (format->direct.greenMask));
- color->blue = miFillColor (b, Ones (format->direct.blueMask));
- color->alpha = miFillColor (a, Ones (format->direct.alphaMask));
- break;
- case PictTypeIndexed:
- pIndexed = (miIndexedPtr) (format->index.devPrivate);
- pixel = pIndexed->rgba[pixel & (MI_MAX_INDEXED-1)];
- r = (pixel >> 16) & 0xff;
- g = (pixel >> 8) & 0xff;
- b = (pixel ) & 0xff;
- color->red = miFillColor (r, 8);
- color->green = miFillColor (g, 8);
- color->blue = miFillColor (b, 8);
- color->alpha = 0xffff;
- break;
- }
-}
-
-Bool
-miPictureInit (ScreenPtr pScreen, PictFormatPtr formats, int nformats)
-{
- PictureScreenPtr ps;
-
- if (!PictureInit (pScreen, formats, nformats))
- return FALSE;
- ps = GetPictureScreen(pScreen);
- ps->CreatePicture = miCreatePicture;
- ps->DestroyPicture = miDestroyPicture;
- ps->ChangePictureClip = miChangePictureClip;
- ps->DestroyPictureClip = miDestroyPictureClip;
- ps->ChangePicture = miChangePicture;
- ps->ValidatePicture = miValidatePicture;
- ps->InitIndexed = miInitIndexed;
- ps->CloseIndexed = miCloseIndexed;
- ps->UpdateIndexed = miUpdateIndexed;
- ps->ChangePictureTransform = miChangePictureTransform;
- ps->ChangePictureFilter = miChangePictureFilter;
- ps->RealizeGlyph = miRealizeGlyph;
- ps->UnrealizeGlyph = miUnrealizeGlyph;
-
- /* MI rendering routines */
- ps->Composite = 0; /* requires DDX support */
- ps->Glyphs = miGlyphs;
- ps->CompositeRects = miCompositeRects;
- ps->Trapezoids = miTrapezoids;
- ps->Triangles = miTriangles;
- ps->TriStrip = miTriStrip;
- ps->TriFan = miTriFan;
-
- ps->RasterizeTrapezoid = 0; /* requires DDX support */
- ps->AddTraps = 0; /* requires DDX support */
- ps->AddTriangles = 0; /* requires DDX support */
-
- return TRUE;
-}
+/* + * + * Copyright © 1999 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY 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 THIS SOFTWARE. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include "scrnintstr.h" +#include "gcstruct.h" +#include "pixmapstr.h" +#include "windowstr.h" +#include "mi.h" +#include "picturestr.h" +#include "mipict.h" + +#ifndef __GNUC__ +#define __inline +#endif + +int +miCreatePicture (PicturePtr pPicture) +{ + return Success; +} + +void +miDestroyPicture (PicturePtr pPicture) +{ + if (pPicture->freeCompClip) + RegionDestroy(pPicture->pCompositeClip); +} + +void +miDestroyPictureClip (PicturePtr pPicture) +{ + switch (pPicture->clientClipType) { + case CT_NONE: + return; + case CT_PIXMAP: + (*pPicture->pDrawable->pScreen->DestroyPixmap) ((PixmapPtr) (pPicture->clientClip)); + break; + default: + /* + * we know we'll never have a list of rectangles, since ChangeClip + * immediately turns them into a region + */ + RegionDestroy(pPicture->clientClip); + break; + } + pPicture->clientClip = NULL; + pPicture->clientClipType = CT_NONE; +} + +int +miChangePictureClip (PicturePtr pPicture, + int type, + pointer value, + int n) +{ + ScreenPtr pScreen = pPicture->pDrawable->pScreen; + PictureScreenPtr ps = GetPictureScreen(pScreen); + pointer clientClip; + int clientClipType; + + switch (type) { + case CT_PIXMAP: + /* convert the pixmap to a region */ + clientClip = (pointer) BitmapToRegion(pScreen, (PixmapPtr) value); + if (!clientClip) + return BadAlloc; + clientClipType = CT_REGION; + (*pScreen->DestroyPixmap) ((PixmapPtr) value); + break; + case CT_REGION: + clientClip = value; + clientClipType = CT_REGION; + break; + case CT_NONE: + clientClip = 0; + clientClipType = CT_NONE; + break; + default: + clientClip = (pointer) RegionFromRects(n, + (xRectangle *) value, + type); + if (!clientClip) + return BadAlloc; + clientClipType = CT_REGION; + free(value); + break; + } + (*ps->DestroyPictureClip) (pPicture); + pPicture->clientClip = clientClip; + pPicture->clientClipType = clientClipType; + pPicture->stateChanges |= CPClipMask; + return Success; +} + +void +miChangePicture (PicturePtr pPicture, + Mask mask) +{ + return; +} + +void +miValidatePicture (PicturePtr pPicture, + Mask mask) +{ + DrawablePtr pDrawable = pPicture->pDrawable; + + if ((mask & (CPClipXOrigin|CPClipYOrigin|CPClipMask|CPSubwindowMode)) || + (pDrawable->serialNumber != (pPicture->serialNumber & DRAWABLE_SERIAL_BITS))) + { + if (pDrawable->type == DRAWABLE_WINDOW) + { + WindowPtr pWin = (WindowPtr) pDrawable; + RegionPtr pregWin; + Bool freeTmpClip, freeCompClip; + + if (pPicture->subWindowMode == IncludeInferiors) + { + pregWin = NotClippedByChildren(pWin); + freeTmpClip = TRUE; + } + else + { + pregWin = &pWin->clipList; + freeTmpClip = FALSE; + } + freeCompClip = pPicture->freeCompClip; + + /* + * if there is no client clip, we can get by with just keeping the + * pointer we got, and remembering whether or not should destroy + * (or maybe re-use) it later. this way, we avoid unnecessary + * copying of regions. (this wins especially if many clients clip + * by children and have no client clip.) + */ + if (pPicture->clientClipType == CT_NONE) + { + if (freeCompClip) + RegionDestroy(pPicture->pCompositeClip); + pPicture->pCompositeClip = pregWin; + pPicture->freeCompClip = freeTmpClip; + } + else + { + /* + * we need one 'real' region to put into the composite clip. if + * pregWin the current composite clip are real, we can get rid of + * one. if pregWin is real and the current composite clip isn't, + * use pregWin for the composite clip. if the current composite + * clip is real and pregWin isn't, use the current composite + * clip. if neither is real, create a new region. + */ + + RegionTranslate(pPicture->clientClip, + pDrawable->x + pPicture->clipOrigin.x, + pDrawable->y + pPicture->clipOrigin.y); + + if (freeCompClip) + { + RegionIntersect(pPicture->pCompositeClip, + pregWin, pPicture->clientClip); + if (freeTmpClip) + RegionDestroy(pregWin); + } + else if (freeTmpClip) + { + RegionIntersect(pregWin, pregWin, pPicture->clientClip); + pPicture->pCompositeClip = pregWin; + } + else + { + pPicture->pCompositeClip = RegionCreate(NullBox, 0); + RegionIntersect(pPicture->pCompositeClip, + pregWin, pPicture->clientClip); + } + pPicture->freeCompClip = TRUE; + RegionTranslate(pPicture->clientClip, + -(pDrawable->x + pPicture->clipOrigin.x), + -(pDrawable->y + pPicture->clipOrigin.y)); + } + } /* end of composite clip for a window */ + else + { + BoxRec pixbounds; + + /* XXX should we translate by drawable.x/y here ? */ + /* If you want pixmaps in offscreen memory, yes */ + pixbounds.x1 = pDrawable->x; + pixbounds.y1 = pDrawable->y; + pixbounds.x2 = pDrawable->x + pDrawable->width; + pixbounds.y2 = pDrawable->y + pDrawable->height; + + if (pPicture->freeCompClip) + { + RegionReset(pPicture->pCompositeClip, &pixbounds); + } + else + { + pPicture->freeCompClip = TRUE; + pPicture->pCompositeClip = RegionCreate(&pixbounds, 1); + } + + if (pPicture->clientClipType == CT_REGION) + { + if(pDrawable->x || pDrawable->y) { + RegionTranslate(pPicture->clientClip, + pDrawable->x + pPicture->clipOrigin.x, + pDrawable->y + pPicture->clipOrigin.y); + RegionIntersect(pPicture->pCompositeClip, + pPicture->pCompositeClip, pPicture->clientClip); + RegionTranslate(pPicture->clientClip, + -(pDrawable->x + pPicture->clipOrigin.x), + -(pDrawable->y + pPicture->clipOrigin.y)); + } else { + RegionTranslate(pPicture->pCompositeClip, + -pPicture->clipOrigin.x, -pPicture->clipOrigin.y); + RegionIntersect(pPicture->pCompositeClip, + pPicture->pCompositeClip, pPicture->clientClip); + RegionTranslate(pPicture->pCompositeClip, + pPicture->clipOrigin.x, pPicture->clipOrigin.y); + } + } + } /* end of composite clip for pixmap */ + } +} + +int +miChangePictureTransform (PicturePtr pPicture, + PictTransform *transform) +{ + return Success; +} + +int +miChangePictureFilter (PicturePtr pPicture, + int filter, + xFixed *params, + int nparams) +{ + return Success; +} + +#define BOUND(v) (INT16) ((v) < MINSHORT ? MINSHORT : (v) > MAXSHORT ? MAXSHORT : (v)) + +static inline pixman_bool_t +miClipPictureReg (pixman_region16_t * pRegion, + pixman_region16_t * pClip, + int dx, + int dy) +{ + if (pixman_region_n_rects(pRegion) == 1 && + pixman_region_n_rects(pClip) == 1) + { + pixman_box16_t * pRbox = pixman_region_rectangles(pRegion, NULL); + pixman_box16_t * pCbox = pixman_region_rectangles(pClip, NULL); + int v; + + if (pRbox->x1 < (v = pCbox->x1 + dx)) + pRbox->x1 = BOUND(v); + if (pRbox->x2 > (v = pCbox->x2 + dx)) + pRbox->x2 = BOUND(v); + if (pRbox->y1 < (v = pCbox->y1 + dy)) + pRbox->y1 = BOUND(v); + if (pRbox->y2 > (v = pCbox->y2 + dy)) + pRbox->y2 = BOUND(v); + if (pRbox->x1 >= pRbox->x2 || + pRbox->y1 >= pRbox->y2) + { + pixman_region_init (pRegion); + } + } + else if (!pixman_region_not_empty (pClip)) + return FALSE; + else + { + if (dx || dy) + pixman_region_translate (pRegion, -dx, -dy); + if (!pixman_region_intersect (pRegion, pRegion, pClip)) + return FALSE; + if (dx || dy) + pixman_region_translate(pRegion, dx, dy); + } + return pixman_region_not_empty(pRegion); +} + +static __inline Bool +miClipPictureSrc (RegionPtr pRegion, + PicturePtr pPicture, + int dx, + int dy) +{ + if (pPicture->clientClipType != CT_NONE) + { + Bool result; + + pixman_region_translate ( pPicture->clientClip, + pPicture->clipOrigin.x + dx, + pPicture->clipOrigin.y + dy); + + result = RegionIntersect(pRegion, pRegion, pPicture->clientClip); + + pixman_region_translate ( pPicture->clientClip, + - (pPicture->clipOrigin.x + dx), + - (pPicture->clipOrigin.y + dy)); + + if (!result) + return FALSE; + } + return TRUE; +} + +void +miCompositeSourceValidate (PicturePtr pPicture, + INT16 x, + INT16 y, + CARD16 width, + CARD16 height) +{ + DrawablePtr pDrawable = pPicture->pDrawable; + ScreenPtr pScreen; + + if (!pDrawable) + return; + + pScreen = pDrawable->pScreen; + + if (pScreen->SourceValidate) + { + if (pPicture->transform) + { + xPoint points[4]; + int i; + int xmin, ymin, xmax, ymax; + +#define VectorSet(i,_x,_y) { points[i].x = _x; points[i].y = _y; } + VectorSet (0, x, y); + VectorSet (1, x + width, y); + VectorSet (2, x, y + height); + VectorSet (3, x + width, y + height); + xmin = ymin = 32767; + xmax = ymax = -32737; + for (i = 0; i < 4; i++) + { + PictVector t; + t.vector[0] = IntToxFixed (points[i].x); + t.vector[1] = IntToxFixed (points[i].y); + t.vector[2] = xFixed1; + if (pixman_transform_point (pPicture->transform, &t)) + { + int tx = xFixedToInt (t.vector[0]); + int ty = xFixedToInt (t.vector[1]); + if (tx < xmin) xmin = tx; + if (tx > xmax) xmax = tx; + if (ty < ymin) ymin = ty; + if (ty > ymax) ymax = ty; + } + } + x = xmin; + y = ymin; + width = xmax - xmin; + height = ymax - ymin; + } + x += pPicture->pDrawable->x; + y += pPicture->pDrawable->y; + (*pScreen->SourceValidate) (pDrawable, x, y, width, height, + pPicture->subWindowMode); + } +} + +/* + * returns FALSE if the final region is empty. Indistinguishable from + * an allocation failure, but rendering ignores those anyways. + */ + +Bool +miComputeCompositeRegion (RegionPtr pRegion, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, + INT16 yDst, + CARD16 width, + CARD16 height) +{ + + int v; + + pRegion->extents.x1 = xDst; + v = xDst + width; + pRegion->extents.x2 = BOUND(v); + pRegion->extents.y1 = yDst; + v = yDst + height; + pRegion->extents.y2 = BOUND(v); + pRegion->data = 0; + /* Check for empty operation */ + if (pRegion->extents.x1 >= pRegion->extents.x2 || + pRegion->extents.y1 >= pRegion->extents.y2) + { + pixman_region_init (pRegion); + return FALSE; + } + /* clip against dst */ + if (!miClipPictureReg (pRegion, pDst->pCompositeClip, 0, 0)) + { + pixman_region_fini (pRegion); + return FALSE; + } + if (pDst->alphaMap) + { + if (!miClipPictureReg (pRegion, pDst->alphaMap->pCompositeClip, + -pDst->alphaOrigin.x, + -pDst->alphaOrigin.y)) + { + pixman_region_fini (pRegion); + return FALSE; + } + } + /* clip against src */ + if (!miClipPictureSrc (pRegion, pSrc, xDst - xSrc, yDst - ySrc)) + { + pixman_region_fini (pRegion); + return FALSE; + } + if (pSrc->alphaMap) + { + if (!miClipPictureSrc (pRegion, pSrc->alphaMap, + xDst - (xSrc - pSrc->alphaOrigin.x), + yDst - (ySrc - pSrc->alphaOrigin.y))) + { + pixman_region_fini (pRegion); + return FALSE; + } + } + /* clip against mask */ + if (pMask) + { + if (!miClipPictureSrc (pRegion, pMask, xDst - xMask, yDst - yMask)) + { + pixman_region_fini (pRegion); + return FALSE; + } + if (pMask->alphaMap) + { + if (!miClipPictureSrc (pRegion, pMask->alphaMap, + xDst - (xMask - pMask->alphaOrigin.x), + yDst - (yMask - pMask->alphaOrigin.y))) + { + pixman_region_fini (pRegion); + return FALSE; + } + } + } + + + miCompositeSourceValidate (pSrc, xSrc, ySrc, width, height); + if (pMask) + miCompositeSourceValidate (pMask, xMask, yMask, width, height); + + return TRUE; +} + +void +miRenderColorToPixel (PictFormatPtr format, + xRenderColor *color, + CARD32 *pixel) +{ + CARD32 r, g, b, a; + miIndexedPtr pIndexed; + + switch (format->type) { + case PictTypeDirect: + r = color->red >> (16 - Ones (format->direct.redMask)); + g = color->green >> (16 - Ones (format->direct.greenMask)); + b = color->blue >> (16 - Ones (format->direct.blueMask)); + a = color->alpha >> (16 - Ones (format->direct.alphaMask)); + r = r << format->direct.red; + g = g << format->direct.green; + b = b << format->direct.blue; + a = a << format->direct.alpha; + *pixel = r|g|b|a; + break; + case PictTypeIndexed: + pIndexed = (miIndexedPtr) (format->index.devPrivate); + if (pIndexed->color) + { + r = color->red >> 11; + g = color->green >> 11; + b = color->blue >> 11; + *pixel = miIndexToEnt15 (pIndexed, (r << 10) | (g << 5) | b); + } + else + { + r = color->red >> 8; + g = color->green >> 8; + b = color->blue >> 8; + *pixel = miIndexToEntY24 (pIndexed, (r << 16) | (g << 8) | b); + } + break; + } +} + +static CARD16 +miFillColor (CARD32 pixel, int bits) +{ + while (bits < 16) + { + pixel |= pixel << bits; + bits <<= 1; + } + return (CARD16) pixel; +} + +Bool +miIsSolidAlpha (PicturePtr pSrc) +{ + ScreenPtr pScreen; + char line[1]; + + if (!pSrc->pDrawable) + return FALSE; + + pScreen = pSrc->pDrawable->pScreen; + + /* Alpha-only */ + if (PICT_FORMAT_TYPE (pSrc->format) != PICT_TYPE_A) + return FALSE; + /* repeat */ + if (!pSrc->repeat) + return FALSE; + /* 1x1 */ + if (pSrc->pDrawable->width != 1 || pSrc->pDrawable->height != 1) + return FALSE; + line[0] = 1; + (*pScreen->GetImage) (pSrc->pDrawable, 0, 0, 1, 1, ZPixmap, ~0L, line); + switch (pSrc->pDrawable->bitsPerPixel) { + case 1: + return (CARD8) line[0] == 1 || (CARD8) line[0] == 0x80; + case 4: + return (CARD8) line[0] == 0xf || (CARD8) line[0] == 0xf0; + case 8: + return (CARD8) line[0] == 0xff; + default: + return FALSE; + } +} + +void +miRenderPixelToColor (PictFormatPtr format, + CARD32 pixel, + xRenderColor *color) +{ + CARD32 r, g, b, a; + miIndexedPtr pIndexed; + + switch (format->type) { + case PictTypeDirect: + r = (pixel >> format->direct.red) & format->direct.redMask; + g = (pixel >> format->direct.green) & format->direct.greenMask; + b = (pixel >> format->direct.blue) & format->direct.blueMask; + a = (pixel >> format->direct.alpha) & format->direct.alphaMask; + color->red = miFillColor (r, Ones (format->direct.redMask)); + color->green = miFillColor (g, Ones (format->direct.greenMask)); + color->blue = miFillColor (b, Ones (format->direct.blueMask)); + color->alpha = miFillColor (a, Ones (format->direct.alphaMask)); + break; + case PictTypeIndexed: + pIndexed = (miIndexedPtr) (format->index.devPrivate); + pixel = pIndexed->rgba[pixel & (MI_MAX_INDEXED-1)]; + r = (pixel >> 16) & 0xff; + g = (pixel >> 8) & 0xff; + b = (pixel ) & 0xff; + color->red = miFillColor (r, 8); + color->green = miFillColor (g, 8); + color->blue = miFillColor (b, 8); + color->alpha = 0xffff; + break; + } +} + +Bool +miPictureInit (ScreenPtr pScreen, PictFormatPtr formats, int nformats) +{ + PictureScreenPtr ps; + + if (!PictureInit (pScreen, formats, nformats)) + return FALSE; + ps = GetPictureScreen(pScreen); + ps->CreatePicture = miCreatePicture; + ps->DestroyPicture = miDestroyPicture; + ps->ChangePictureClip = miChangePictureClip; + ps->DestroyPictureClip = miDestroyPictureClip; + ps->ChangePicture = miChangePicture; + ps->ValidatePicture = miValidatePicture; + ps->InitIndexed = miInitIndexed; + ps->CloseIndexed = miCloseIndexed; + ps->UpdateIndexed = miUpdateIndexed; + ps->ChangePictureTransform = miChangePictureTransform; + ps->ChangePictureFilter = miChangePictureFilter; + ps->RealizeGlyph = miRealizeGlyph; + ps->UnrealizeGlyph = miUnrealizeGlyph; + + /* MI rendering routines */ + ps->Composite = 0; /* requires DDX support */ + ps->Glyphs = miGlyphs; + ps->CompositeRects = miCompositeRects; + ps->Trapezoids = 0; + ps->Triangles = 0; + ps->TriStrip = miTriStrip; + ps->TriFan = miTriFan; + + ps->RasterizeTrapezoid = 0; /* requires DDX support */ + ps->AddTraps = 0; /* requires DDX support */ + ps->AddTriangles = 0; /* requires DDX support */ + + return TRUE; +} diff --git a/xorg-server/render/mipict.h b/xorg-server/render/mipict.h index eb6b6645d..d1495891e 100644 --- a/xorg-server/render/mipict.h +++ b/xorg-server/render/mipict.h @@ -146,32 +146,12 @@ extern _X_EXPORT void miTrapezoidBounds (int ntrap, xTrapezoid *traps, BoxPtr box); extern _X_EXPORT void -miTrapezoids (CARD8 op, - PicturePtr pSrc, - PicturePtr pDst, - PictFormatPtr maskFormat, - INT16 xSrc, - INT16 ySrc, - int ntrap, - xTrapezoid *traps); - -extern _X_EXPORT void miPointFixedBounds (int npoint, xPointFixed *points, BoxPtr bounds); extern _X_EXPORT void miTriangleBounds (int ntri, xTriangle *tris, BoxPtr bounds); extern _X_EXPORT void -miTriangles (CARD8 op, - PicturePtr pSrc, - PicturePtr pDst, - PictFormatPtr maskFormat, - INT16 xSrc, - INT16 ySrc, - int ntri, - xTriangle *tris); - -extern _X_EXPORT void miTriStrip (CARD8 op, PicturePtr pSrc, PicturePtr pDst, @@ -191,13 +171,6 @@ miTriFan (CARD8 op, int npoint, xPointFixed *points); -extern _X_EXPORT PicturePtr -miCreateAlphaPicture (ScreenPtr pScreen, - PicturePtr pDst, - PictFormatPtr pPictFormat, - CARD16 width, - CARD16 height); - extern _X_EXPORT Bool miInitIndexed (ScreenPtr pScreen, PictFormatPtr pFormat); diff --git a/xorg-server/render/mitrap.c b/xorg-server/render/mitrap.c index 8bdc8a8d0..445f23630 100644 --- a/xorg-server/render/mitrap.c +++ b/xorg-server/render/mitrap.c @@ -34,55 +34,6 @@ #include "picturestr.h" #include "mipict.h" -PicturePtr -miCreateAlphaPicture (ScreenPtr pScreen, - PicturePtr pDst, - PictFormatPtr pPictFormat, - CARD16 width, - CARD16 height) -{ - PixmapPtr pPixmap; - PicturePtr pPicture; - GCPtr pGC; - int error; - xRectangle rect; - - if (width > 32767 || height > 32767) - return 0; - - if (!pPictFormat) - { - if (pDst->polyEdge == PolyEdgeSharp) - pPictFormat = PictureMatchFormat (pScreen, 1, PICT_a1); - else - pPictFormat = PictureMatchFormat (pScreen, 8, PICT_a8); - if (!pPictFormat) - return 0; - } - - pPixmap = (*pScreen->CreatePixmap) (pScreen, width, height, - pPictFormat->depth, 0); - if (!pPixmap) - return 0; - pGC = GetScratchGC (pPixmap->drawable.depth, pScreen); - if (!pGC) - { - (*pScreen->DestroyPixmap) (pPixmap); - return 0; - } - ValidateGC (&pPixmap->drawable, pGC); - rect.x = 0; - rect.y = 0; - rect.width = width; - rect.height = height; - (*pGC->ops->PolyFillRect)(&pPixmap->drawable, pGC, 1, &rect); - FreeScratchGC (pGC); - pPicture = CreatePicture (0, &pPixmap->drawable, pPictFormat, - 0, 0, serverClient, &error); - (*pScreen->DestroyPixmap) (pPixmap); - return pPicture; -} - static xFixed miLineFixedX (xLineFixed *l, xFixed y, Bool ceil) { @@ -126,64 +77,3 @@ miTrapezoidBounds (int ntrap, xTrapezoid *traps, BoxPtr box) box->x2 = x2; } } - -void -miTrapezoids (CARD8 op, - PicturePtr pSrc, - PicturePtr pDst, - PictFormatPtr maskFormat, - INT16 xSrc, - INT16 ySrc, - int ntrap, - xTrapezoid *traps) -{ - ScreenPtr pScreen = pDst->pDrawable->pScreen; - PictureScreenPtr ps = GetPictureScreen(pScreen); - - /* - * Check for solid alpha add - */ - if (op == PictOpAdd && miIsSolidAlpha (pSrc)) - { - for (; ntrap; ntrap--, traps++) - (*ps->RasterizeTrapezoid) (pDst, traps, 0, 0); - } - else if (maskFormat) - { - PicturePtr pPicture; - BoxRec bounds; - INT16 xDst, yDst; - INT16 xRel, yRel; - - xDst = traps[0].left.p1.x >> 16; - yDst = traps[0].left.p1.y >> 16; - - miTrapezoidBounds (ntrap, traps, &bounds); - if (bounds.y1 >= bounds.y2 || bounds.x1 >= bounds.x2) - return; - pPicture = miCreateAlphaPicture (pScreen, pDst, maskFormat, - bounds.x2 - bounds.x1, - bounds.y2 - bounds.y1); - if (!pPicture) - return; - for (; ntrap; ntrap--, traps++) - (*ps->RasterizeTrapezoid) (pPicture, traps, - -bounds.x1, -bounds.y1); - xRel = bounds.x1 + xSrc - xDst; - yRel = bounds.y1 + ySrc - yDst; - CompositePicture (op, pSrc, pPicture, pDst, - xRel, yRel, 0, 0, bounds.x1, bounds.y1, - bounds.x2 - bounds.x1, - bounds.y2 - bounds.y1); - FreePicture (pPicture, 0); - } - else - { - if (pDst->polyEdge == PolyEdgeSharp) - maskFormat = PictureMatchFormat (pScreen, 1, PICT_a1); - else - maskFormat = PictureMatchFormat (pScreen, 8, PICT_a8); - for (; ntrap; ntrap--, traps++) - miTrapezoids (op, pSrc, pDst, maskFormat, xSrc, ySrc, 1, traps); - } -} diff --git a/xorg-server/render/mitri.c b/xorg-server/render/mitri.c index 3e11cffd9..b258c2156 100644 --- a/xorg-server/render/mitri.c +++ b/xorg-server/render/mitri.c @@ -1,191 +1,132 @@ -/*
- *
- * Copyright © 2002 Keith Packard, member of The XFree86 Project, Inc.
- *
- * Permission to use, copy, modify, distribute, and sell this software and its
- * documentation for any purpose is hereby granted without fee, provided that
- * the above copyright notice appear in all copies and that both that
- * copyright notice and this permission notice appear in supporting
- * documentation, and that the name of Keith Packard not be used in
- * advertising or publicity pertaining to distribution of the software without
- * specific, written prior permission. Keith Packard makes no
- * representations about the suitability of this software for any purpose. It
- * is provided "as is" without express or implied warranty.
- *
- * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
- * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
- * CONSEQUENTIAL DAMAGES OR ANY 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 THIS SOFTWARE.
- */
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#include "scrnintstr.h"
-#include "gcstruct.h"
-#include "pixmapstr.h"
-#include "windowstr.h"
-#include "mi.h"
-#include "picturestr.h"
-#include "mipict.h"
-
-void
-miPointFixedBounds (int npoint, xPointFixed *points, BoxPtr bounds)
-{
- bounds->x1 = xFixedToInt (points->x);
- bounds->x2 = xFixedToInt (xFixedCeil (points->x));
- bounds->y1 = xFixedToInt (points->y);
- bounds->y2 = xFixedToInt (xFixedCeil (points->y));
- points++;
- npoint--;
- while (npoint-- > 0)
- {
- INT16 x1 = xFixedToInt (points->x);
- INT16 x2 = xFixedToInt (xFixedCeil (points->x));
- INT16 y1 = xFixedToInt (points->y);
- INT16 y2 = xFixedToInt (xFixedCeil (points->y));
-
- if (x1 < bounds->x1)
- bounds->x1 = x1;
- else if (x2 > bounds->x2)
- bounds->x2 = x2;
- if (y1 < bounds->y1)
- bounds->y1 = y1;
- else if (y2 > bounds->y2)
- bounds->y2 = y2;
- points++;
- }
-}
-
-void
-miTriangleBounds (int ntri, xTriangle *tris, BoxPtr bounds)
-{
- miPointFixedBounds (ntri * 3, (xPointFixed *) tris, bounds);
-}
-
-void
-miTriangles (CARD8 op,
- PicturePtr pSrc,
- PicturePtr pDst,
- PictFormatPtr maskFormat,
- INT16 xSrc,
- INT16 ySrc,
- int ntri,
- xTriangle *tris)
-{
- ScreenPtr pScreen = pDst->pDrawable->pScreen;
- PictureScreenPtr ps = GetPictureScreen(pScreen);
-
- /*
- * Check for solid alpha add
- */
- if (op == PictOpAdd && miIsSolidAlpha (pSrc))
- {
- (*ps->AddTriangles) (pDst, 0, 0, ntri, tris);
- }
- else if (maskFormat)
- {
- BoxRec bounds;
- PicturePtr pPicture;
- INT16 xDst, yDst;
- INT16 xRel, yRel;
-
- xDst = tris[0].p1.x >> 16;
- yDst = tris[0].p1.y >> 16;
-
- miTriangleBounds (ntri, tris, &bounds);
- if (bounds.x2 <= bounds.x1 || bounds.y2 <= bounds.y1)
- return;
- pPicture = miCreateAlphaPicture (pScreen, pDst, maskFormat,
- bounds.x2 - bounds.x1,
- bounds.y2 - bounds.y1);
- if (!pPicture)
- return;
- (*ps->AddTriangles) (pPicture, -bounds.x1, -bounds.y1, ntri, tris);
-
- xRel = bounds.x1 + xSrc - xDst;
- yRel = bounds.y1 + ySrc - yDst;
- CompositePicture (op, pSrc, pPicture, pDst,
- xRel, yRel, 0, 0, bounds.x1, bounds.y1,
- bounds.x2 - bounds.x1, bounds.y2 - bounds.y1);
- FreePicture (pPicture, 0);
- }
- else
- {
- if (pDst->polyEdge == PolyEdgeSharp)
- maskFormat = PictureMatchFormat (pScreen, 1, PICT_a1);
- else
- maskFormat = PictureMatchFormat (pScreen, 8, PICT_a8);
-
- for (; ntri; ntri--, tris++)
- miTriangles (op, pSrc, pDst, maskFormat, xSrc, ySrc, 1, tris);
- }
-}
-
-void
-miTriStrip (CARD8 op,
- PicturePtr pSrc,
- PicturePtr pDst,
- PictFormatPtr maskFormat,
- INT16 xSrc,
- INT16 ySrc,
- int npoint,
- xPointFixed *points)
-{
- ScreenPtr pScreen = pDst->pDrawable->pScreen;
- PictureScreenPtr ps = GetPictureScreen(pScreen);
- xTriangle *tris, *tri;
- int ntri;
-
- if (npoint < 3)
- return;
- ntri = npoint - 2;
- tris = malloc(ntri * sizeof (xTriangle));
- if (!tris)
- return;
- for (tri = tris; npoint >= 3; npoint--, points++, tri++)
- {
- tri->p1 = points[0];
- tri->p2 = points[1];
- tri->p3 = points[2];
- }
- (*ps->Triangles) (op, pSrc, pDst, maskFormat, xSrc, ySrc, ntri, tris);
- free(tris);
-}
-
-void
-miTriFan (CARD8 op,
- PicturePtr pSrc,
- PicturePtr pDst,
- PictFormatPtr maskFormat,
- INT16 xSrc,
- INT16 ySrc,
- int npoint,
- xPointFixed *points)
-{
- ScreenPtr pScreen = pDst->pDrawable->pScreen;
- PictureScreenPtr ps = GetPictureScreen(pScreen);
- xTriangle *tris, *tri;
- xPointFixed *first;
- int ntri;
-
- if (npoint < 3)
- return;
- ntri = npoint - 2;
- tris = malloc(ntri * sizeof (xTriangle));
- if (!tris)
- return;
- first = points++;
- for (tri = tris; npoint >= 3; npoint--, points++, tri++)
- {
- tri->p1 = *first;
- tri->p2 = points[0];
- tri->p3 = points[1];
- }
- (*ps->Triangles) (op, pSrc, pDst, maskFormat, xSrc, ySrc, ntri, tris);
- free(tris);
-}
+/* + * + * Copyright © 2002 Keith Packard, member of The XFree86 Project, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY 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 THIS SOFTWARE. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include "scrnintstr.h" +#include "gcstruct.h" +#include "pixmapstr.h" +#include "windowstr.h" +#include "mi.h" +#include "picturestr.h" +#include "mipict.h" + +void +miPointFixedBounds (int npoint, xPointFixed *points, BoxPtr bounds) +{ + bounds->x1 = xFixedToInt (points->x); + bounds->x2 = xFixedToInt (xFixedCeil (points->x)); + bounds->y1 = xFixedToInt (points->y); + bounds->y2 = xFixedToInt (xFixedCeil (points->y)); + points++; + npoint--; + while (npoint-- > 0) + { + INT16 x1 = xFixedToInt (points->x); + INT16 x2 = xFixedToInt (xFixedCeil (points->x)); + INT16 y1 = xFixedToInt (points->y); + INT16 y2 = xFixedToInt (xFixedCeil (points->y)); + + if (x1 < bounds->x1) + bounds->x1 = x1; + else if (x2 > bounds->x2) + bounds->x2 = x2; + if (y1 < bounds->y1) + bounds->y1 = y1; + else if (y2 > bounds->y2) + bounds->y2 = y2; + points++; + } +} + +void +miTriangleBounds (int ntri, xTriangle *tris, BoxPtr bounds) +{ + miPointFixedBounds (ntri * 3, (xPointFixed *) tris, bounds); +} + +void +miTriStrip (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int npoint, + xPointFixed *points) +{ + ScreenPtr pScreen = pDst->pDrawable->pScreen; + PictureScreenPtr ps = GetPictureScreen(pScreen); + xTriangle *tris, *tri; + int ntri; + + if (npoint < 3) + return; + ntri = npoint - 2; + tris = malloc(ntri * sizeof (xTriangle)); + if (!tris) + return; + for (tri = tris; npoint >= 3; npoint--, points++, tri++) + { + tri->p1 = points[0]; + tri->p2 = points[1]; + tri->p3 = points[2]; + } + (*ps->Triangles) (op, pSrc, pDst, maskFormat, xSrc, ySrc, ntri, tris); + free(tris); +} + +void +miTriFan (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int npoint, + xPointFixed *points) +{ + ScreenPtr pScreen = pDst->pDrawable->pScreen; + PictureScreenPtr ps = GetPictureScreen(pScreen); + xTriangle *tris, *tri; + xPointFixed *first; + int ntri; + + if (npoint < 3) + return; + ntri = npoint - 2; + tris = malloc(ntri * sizeof (xTriangle)); + if (!tris) + return; + first = points++; + for (tri = tris; npoint >= 3; npoint--, points++, tri++) + { + tri->p1 = *first; + tri->p2 = points[0]; + tri->p3 = points[1]; + } + (*ps->Triangles) (op, pSrc, pDst, maskFormat, xSrc, ySrc, ntri, tris); + free(tris); +} diff --git a/xorg-server/test/input.c b/xorg-server/test/input.c index e0e9e6af7..c13b4f213 100644 --- a/xorg-server/test/input.c +++ b/xorg-server/test/input.c @@ -149,29 +149,32 @@ static void dix_check_grab_values(void) static void dix_event_to_core(int type) { DeviceEvent ev; - xEvent core; + xEvent *core; int time; int x, y; int rc; int state; int detail; + int count; const int ROOT_WINDOW_ID = 0x100; /* EventToCore memsets the event to 0 */ #define test_event() \ g_assert(rc == Success); \ - g_assert(core.u.u.type == type); \ - g_assert(core.u.u.detail == detail); \ - g_assert(core.u.keyButtonPointer.time == time); \ - g_assert(core.u.keyButtonPointer.rootX == x); \ - g_assert(core.u.keyButtonPointer.rootY == y); \ - g_assert(core.u.keyButtonPointer.state == state); \ - g_assert(core.u.keyButtonPointer.eventX == 0); \ - g_assert(core.u.keyButtonPointer.eventY == 0); \ - g_assert(core.u.keyButtonPointer.root == ROOT_WINDOW_ID); \ - g_assert(core.u.keyButtonPointer.event == 0); \ - g_assert(core.u.keyButtonPointer.child == 0); \ - g_assert(core.u.keyButtonPointer.sameScreen == FALSE); + g_assert(core); \ + g_assert(count == 1); \ + g_assert(core->u.u.type == type); \ + g_assert(core->u.u.detail == detail); \ + g_assert(core->u.keyButtonPointer.time == time); \ + g_assert(core->u.keyButtonPointer.rootX == x); \ + g_assert(core->u.keyButtonPointer.rootY == y); \ + g_assert(core->u.keyButtonPointer.state == state); \ + g_assert(core->u.keyButtonPointer.eventX == 0); \ + g_assert(core->u.keyButtonPointer.eventY == 0); \ + g_assert(core->u.keyButtonPointer.root == ROOT_WINDOW_ID); \ + g_assert(core->u.keyButtonPointer.event == 0); \ + g_assert(core->u.keyButtonPointer.child == 0); \ + g_assert(core->u.keyButtonPointer.sameScreen == FALSE); x = 0; y = 0; @@ -192,30 +195,33 @@ static void dix_event_to_core(int type) ev.type = type; ev.detail.key = 0; - rc = EventToCore((InternalEvent*)&ev, &core); + rc = EventToCore((InternalEvent*)&ev, &core, &count); test_event(); x = 1; y = 2; ev.root_x = x; ev.root_y = y; - rc = EventToCore((InternalEvent*)&ev, &core); + rc = EventToCore((InternalEvent*)&ev, &core, &count); test_event(); x = 0x7FFF; y = 0x7FFF; ev.root_x = x; ev.root_y = y; - rc = EventToCore((InternalEvent*)&ev, &core); + rc = EventToCore((InternalEvent*)&ev, &core, &count); test_event(); x = 0x8000; /* too high */ y = 0x8000; /* too high */ ev.root_x = x; ev.root_y = y; - rc = EventToCore((InternalEvent*)&ev, &core); - g_assert(core.u.keyButtonPointer.rootX != x); - g_assert(core.u.keyButtonPointer.rootY != y); + rc = EventToCore((InternalEvent*)&ev, &core, &count); + g_assert(rc == Success); + g_assert(core); + g_assert(count == 1); + g_assert(core->u.keyButtonPointer.rootX != x); + g_assert(core->u.keyButtonPointer.rootY != y); x = 0x7FFF; y = 0x7FFF; @@ -223,36 +229,39 @@ static void dix_event_to_core(int type) ev.root_y = y; time = 0; ev.time = time; - rc = EventToCore((InternalEvent*)&ev, &core); + rc = EventToCore((InternalEvent*)&ev, &core, &count); test_event(); detail = 1; ev.detail.key = detail; - rc = EventToCore((InternalEvent*)&ev, &core); + rc = EventToCore((InternalEvent*)&ev, &core, &count); test_event(); detail = 0xFF; /* highest value */ ev.detail.key = detail; - rc = EventToCore((InternalEvent*)&ev, &core); + rc = EventToCore((InternalEvent*)&ev, &core, &count); test_event(); detail = 0xFFF; /* too big */ ev.detail.key = detail; - rc = EventToCore((InternalEvent*)&ev, &core); + rc = EventToCore((InternalEvent*)&ev, &core, &count); g_assert(rc == BadMatch); detail = 0xFF; /* too big */ ev.detail.key = detail; state = 0xFFFF; /* highest value */ ev.corestate = state; - rc = EventToCore((InternalEvent*)&ev, &core); + rc = EventToCore((InternalEvent*)&ev, &core, &count); test_event(); state = 0x10000; /* too big */ ev.corestate = state; - rc = EventToCore((InternalEvent*)&ev, &core); - g_assert(core.u.keyButtonPointer.state != state); - g_assert(core.u.keyButtonPointer.state == (state & 0xFFFF)); + rc = EventToCore((InternalEvent*)&ev, &core, &count); + g_assert(rc == Success); + g_assert(core); + g_assert(count == 1); + g_assert(core->u.keyButtonPointer.state != state); + g_assert(core->u.keyButtonPointer.state == (state & 0xFFFF)); #undef test_event } @@ -260,14 +269,15 @@ static void dix_event_to_core(int type) static void dix_event_to_core_fail(int evtype, int expected_rc) { DeviceEvent ev; - xEvent core; + xEvent *core; int rc; + int count; ev.header = 0xFF; ev.length = sizeof(DeviceEvent); ev.type = evtype; - rc = EventToCore((InternalEvent*)&ev, &core); + rc = EventToCore((InternalEvent*)&ev, &core, &count); g_assert(rc == expected_rc); } diff --git a/xorg-server/test/xi2/protocol-xiquerypointer.c b/xorg-server/test/xi2/protocol-xiquerypointer.c index 810c61575..a42d59515 100644 --- a/xorg-server/test/xi2/protocol-xiquerypointer.c +++ b/xorg-server/test/xi2/protocol-xiquerypointer.c @@ -185,7 +185,7 @@ static void test_XIQueryPointer(void) request_XIQueryPointer(&client_request, &request, BadDevice); test_data.dev = devices.mouse; - devices.mouse->u.master = NULL; /* Float, kind-of */ + devices.mouse->master = NULL; /* Float, kind-of */ request.deviceid = devices.mouse->id; request_XIQueryPointer(&client_request, &request, Success); diff --git a/xorg-server/test/xi2/protocol-xiwarppointer.c b/xorg-server/test/xi2/protocol-xiwarppointer.c index 4f8860ea0..75b7617a0 100644 --- a/xorg-server/test/xi2/protocol-xiwarppointer.c +++ b/xorg-server/test/xi2/protocol-xiwarppointer.c @@ -145,7 +145,7 @@ static void test_XIWarpPointer(void) request.deviceid = devices.kbd->id; request_XIWarpPointer(&client_request, &request, BadDevice); - devices.mouse->u.master = NULL; /* Float, kind-of */ + devices.mouse->master = NULL; /* Float, kind-of */ request.deviceid = devices.mouse->id; request_XIWarpPointer(&client_request, &request, Success); diff --git a/xorg-server/xkb/XKBGAlloc.c b/xorg-server/xkb/XKBGAlloc.c index d5e49349e..65f92fdba 100644 --- a/xorg-server/xkb/XKBGAlloc.c +++ b/xorg-server/xkb/XKBGAlloc.c @@ -1,979 +1,974 @@ -/************************************************************
-Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc.
-
-Permission 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 that both that copyright
-notice and this permission notice appear in supporting
-documentation, and that the name of Silicon Graphics not be
-used in advertising or publicity pertaining to distribution
-of the software without specific prior written permission.
-Silicon Graphics makes no representation about the suitability
-of this software for any purpose. It is provided "as is"
-without any express or implied warranty.
-
-SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
-SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
-AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
-GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
-DAMAGES OR ANY 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 THIS SOFTWARE.
-
-********************************************************/
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-
-#include <stdio.h>
-#include <X11/X.h>
-#include <X11/Xproto.h>
-#include "misc.h"
-#include "inputstr.h"
-#include <xkbsrv.h>
-#include "xkbgeom.h"
-
-/***====================================================================***/
-
-static void
-_XkbFreeGeomLeafElems( Bool freeAll,
- int first,
- int count,
- unsigned short * num_inout,
- unsigned short * sz_inout,
- char ** elems,
- unsigned int elem_sz)
-{
- if ((freeAll)||(*elems==NULL)) {
- *num_inout= *sz_inout= 0;
- free(*elems);
- *elems = NULL;
- return;
- }
-
- if ((first>=(*num_inout))||(first<0)||(count<1))
- return;
-
- if (first+count>=(*num_inout)) {
- /* truncating the array is easy */
- (*num_inout)= first;
- }
- else {
- char * ptr;
- int extra;
- ptr= *elems;
- extra= ((*num_inout)-(first+count))*elem_sz;
- if (extra>0)
- memmove(&ptr[first*elem_sz],&ptr[(first+count)*elem_sz],extra);
- (*num_inout)-= count;
- }
- return;
-}
-
-typedef void (*ContentsClearFunc)(
- char * /* priv */
-);
-
-static void
-_XkbFreeGeomNonLeafElems( Bool freeAll,
- int first,
- int count,
- unsigned short * num_inout,
- unsigned short * sz_inout,
- char ** elems,
- unsigned int elem_sz,
- ContentsClearFunc freeFunc)
-{
-register int i;
-register char *ptr;
-
- if (freeAll) {
- first= 0;
- count= (*num_inout);
- }
- else if ((first>=(*num_inout))||(first<0)||(count<1))
- return;
- else if (first+count>(*num_inout))
- count= (*num_inout)-first;
- if (*elems==NULL)
- return;
-
- if (freeFunc) {
- ptr= *elems;
- ptr+= first*elem_sz;
- for (i=0;i<count;i++) {
- (*freeFunc)(ptr);
- ptr+= elem_sz;
- }
- }
- if (freeAll) {
- (*num_inout)= (*sz_inout)= 0;
- free(*elems);
- *elems = NULL;
- }
- else if (first+count>=(*num_inout))
- *num_inout= first;
- else {
- i= ((*num_inout)-(first+count))*elem_sz;
- ptr= *elems;
- memmove(&ptr[first*elem_sz],&ptr[(first+count)*elem_sz],i);
- (*num_inout)-= count;
- }
- return;
-}
-
-/***====================================================================***/
-
-static void
-_XkbClearProperty(char *prop_in)
-{
-XkbPropertyPtr prop= (XkbPropertyPtr)prop_in;
-
- free(prop->name);
- prop->name = NULL;
- free(prop->value);
- prop->value = NULL;
- return;
-}
-
-void
-XkbFreeGeomProperties( XkbGeometryPtr geom,
- int first,
- int count,
- Bool freeAll)
-{
- _XkbFreeGeomNonLeafElems(freeAll,first,count,
- &geom->num_properties,&geom->sz_properties,
- (char **)&geom->properties,
- sizeof(XkbPropertyRec),_XkbClearProperty);
- return;
-}
-
-/***====================================================================***/
-
-void
-XkbFreeGeomKeyAliases( XkbGeometryPtr geom,
- int first,
- int count,
- Bool freeAll)
-{
- _XkbFreeGeomLeafElems(freeAll,first,count,
- &geom->num_key_aliases,&geom->sz_key_aliases,
- (char **)&geom->key_aliases,
- sizeof(XkbKeyAliasRec));
- return;
-}
-
-/***====================================================================***/
-
-static void
-_XkbClearColor(char *color_in)
-{
-XkbColorPtr color= (XkbColorPtr)color_in;
-
- free(color->spec);
- return;
-}
-
-void
-XkbFreeGeomColors(XkbGeometryPtr geom,int first,int count,Bool freeAll)
-{
- _XkbFreeGeomNonLeafElems(freeAll,first,count,
- &geom->num_colors,&geom->sz_colors,
- (char **)&geom->colors,
- sizeof(XkbColorRec),_XkbClearColor);
- return;
-}
-
-/***====================================================================***/
-
-void
-XkbFreeGeomPoints(XkbOutlinePtr outline,int first,int count,Bool freeAll)
-{
- _XkbFreeGeomLeafElems(freeAll,first,count,
- &outline->num_points,&outline->sz_points,
- (char **)&outline->points,
- sizeof(XkbPointRec));
- return;
-}
-
-/***====================================================================***/
-
-static void
-_XkbClearOutline(char *outline_in)
-{
-XkbOutlinePtr outline= (XkbOutlinePtr)outline_in;
-
- if (outline->points!=NULL)
- XkbFreeGeomPoints(outline,0,outline->num_points,TRUE);
- return;
-}
-
-void
-XkbFreeGeomOutlines(XkbShapePtr shape,int first,int count,Bool freeAll)
-{
- _XkbFreeGeomNonLeafElems(freeAll,first,count,
- &shape->num_outlines,&shape->sz_outlines,
- (char **)&shape->outlines,
- sizeof(XkbOutlineRec),_XkbClearOutline);
-
- return;
-}
-
-/***====================================================================***/
-
-static void
-_XkbClearShape(char *shape_in)
-{
-XkbShapePtr shape= (XkbShapePtr)shape_in;
-
- if (shape->outlines)
- XkbFreeGeomOutlines(shape,0,shape->num_outlines,TRUE);
- return;
-}
-
-void
-XkbFreeGeomShapes(XkbGeometryPtr geom,int first,int count,Bool freeAll)
-{
- _XkbFreeGeomNonLeafElems(freeAll,first,count,
- &geom->num_shapes,&geom->sz_shapes,
- (char **)&geom->shapes,
- sizeof(XkbShapeRec),_XkbClearShape);
- return;
-}
-
-/***====================================================================***/
-
-void
-XkbFreeGeomOverlayKeys(XkbOverlayRowPtr row,int first,int count,Bool freeAll)
-{
- _XkbFreeGeomLeafElems(freeAll,first,count,
- &row->num_keys,&row->sz_keys,
- (char **)&row->keys,
- sizeof(XkbOverlayKeyRec));
- return;
-}
-
-/***====================================================================***/
-
-static void
-_XkbClearOverlayRow(char *row_in)
-{
-XkbOverlayRowPtr row= (XkbOverlayRowPtr)row_in;
-
- if (row->keys!=NULL)
- XkbFreeGeomOverlayKeys(row,0,row->num_keys,TRUE);
- return;
-}
-
-void
-XkbFreeGeomOverlayRows(XkbOverlayPtr overlay,int first,int count,Bool freeAll)
-{
- _XkbFreeGeomNonLeafElems(freeAll,first,count,
- &overlay->num_rows,&overlay->sz_rows,
- (char **)&overlay->rows,
- sizeof(XkbOverlayRowRec),_XkbClearOverlayRow);
- return;
-}
-
-/***====================================================================***/
-
-static void
-_XkbClearOverlay(char *overlay_in)
-{
-XkbOverlayPtr overlay= (XkbOverlayPtr)overlay_in;
-
- if (overlay->rows!=NULL)
- XkbFreeGeomOverlayRows(overlay,0,overlay->num_rows,TRUE);
- return;
-}
-
-void
-XkbFreeGeomOverlays(XkbSectionPtr section,int first,int count,Bool freeAll)
-{
- _XkbFreeGeomNonLeafElems(freeAll,first,count,
- §ion->num_overlays,§ion->sz_overlays,
- (char **)§ion->overlays,
- sizeof(XkbOverlayRec),_XkbClearOverlay);
- return;
-}
-
-/***====================================================================***/
-
-void
-XkbFreeGeomKeys(XkbRowPtr row,int first,int count,Bool freeAll)
-{
- _XkbFreeGeomLeafElems(freeAll,first,count,
- &row->num_keys,&row->sz_keys,
- (char **)&row->keys,
- sizeof(XkbKeyRec));
- return;
-}
-
-/***====================================================================***/
-
-static void
-_XkbClearRow(char *row_in)
-{
-XkbRowPtr row= (XkbRowPtr)row_in;
-
- if (row->keys!=NULL)
- XkbFreeGeomKeys(row,0,row->num_keys,TRUE);
- return;
-}
-
-void
-XkbFreeGeomRows(XkbSectionPtr section,int first,int count,Bool freeAll)
-{
- _XkbFreeGeomNonLeafElems(freeAll,first,count,
- §ion->num_rows,§ion->sz_rows,
- (char **)§ion->rows,
- sizeof(XkbRowRec),_XkbClearRow);
-}
-
-/***====================================================================***/
-
-static void
-_XkbClearSection(char *section_in)
-{
-XkbSectionPtr section= (XkbSectionPtr)section_in;
-
- if (section->rows!=NULL)
- XkbFreeGeomRows(section,0,section->num_rows,TRUE);
- if (section->doodads!=NULL) {
- XkbFreeGeomDoodads(section->doodads,section->num_doodads,TRUE);
- section->doodads= NULL;
- }
- return;
-}
-
-void
-XkbFreeGeomSections(XkbGeometryPtr geom,int first,int count,Bool freeAll)
-{
- _XkbFreeGeomNonLeafElems(freeAll,first,count,
- &geom->num_sections,&geom->sz_sections,
- (char **)&geom->sections,
- sizeof(XkbSectionRec),_XkbClearSection);
- return;
-}
-
-/***====================================================================***/
-
-static void
-_XkbClearDoodad(char *doodad_in)
-{
-XkbDoodadPtr doodad= (XkbDoodadPtr)doodad_in;
-
- switch (doodad->any.type) {
- case XkbTextDoodad:
- {
- free(doodad->text.text);
- doodad->text.text = NULL;
- free(doodad->text.font);
- doodad->text.font = NULL;
- }
- break;
- case XkbLogoDoodad:
- {
- free(doodad->logo.logo_name);
- doodad->logo.logo_name = NULL;
- }
- break;
- }
- return;
-}
-
-void
-XkbFreeGeomDoodads(XkbDoodadPtr doodads,int nDoodads,Bool freeAll)
-{
-register int i;
-register XkbDoodadPtr doodad;
-
- if (doodads) {
- for (i=0,doodad= doodads;i<nDoodads;i++,doodad++) {
- _XkbClearDoodad((char *)doodad);
- }
- if (freeAll)
- free(doodads);
- }
- return;
-}
-
-void
-XkbFreeGeometry(XkbGeometryPtr geom,unsigned which,Bool freeMap)
-{
- if (geom==NULL)
- return;
- if (freeMap)
- which= XkbGeomAllMask;
- if ((which&XkbGeomPropertiesMask)&&(geom->properties!=NULL))
- XkbFreeGeomProperties(geom,0,geom->num_properties,TRUE);
- if ((which&XkbGeomColorsMask)&&(geom->colors!=NULL))
- XkbFreeGeomColors(geom,0,geom->num_colors,TRUE);
- if ((which&XkbGeomShapesMask)&&(geom->shapes!=NULL))
- XkbFreeGeomShapes(geom,0,geom->num_shapes,TRUE);
- if ((which&XkbGeomSectionsMask)&&(geom->sections!=NULL))
- XkbFreeGeomSections(geom,0,geom->num_sections,TRUE);
- if ((which&XkbGeomDoodadsMask)&&(geom->doodads!= NULL)) {
- XkbFreeGeomDoodads(geom->doodads,geom->num_doodads,TRUE);
- geom->doodads= NULL;
- geom->num_doodads= geom->sz_doodads= 0;
- }
- if ((which&XkbGeomKeyAliasesMask)&&(geom->key_aliases!=NULL))
- XkbFreeGeomKeyAliases(geom,0,geom->num_key_aliases,TRUE);
- if (freeMap) {
- free(geom->label_font);
- geom->label_font = NULL;
- free(geom);
- }
- return;
-}
-
-/***====================================================================***/
-
-static Status
-_XkbGeomAlloc( void ** old,
- unsigned short * num,
- unsigned short * total,
- int num_new,
- size_t sz_elem)
-{
- if (num_new<1)
- return Success;
- if ((*old)==NULL)
- *num= *total= 0;
-
- if ((*num)+num_new<=(*total))
- return Success;
-
- *total= (*num)+num_new;
- if ((*old)!=NULL)
- (*old)= realloc((*old),(*total)*sz_elem);
- else (*old)= calloc((*total),sz_elem);
- if ((*old)==NULL) {
- *total= *num= 0;
- return BadAlloc;
- }
-
- if (*num>0) {
- char *tmp= (char *)(*old);
- memset(&tmp[sz_elem*(*num)], 0, (num_new*sz_elem));
- }
- return Success;
-}
-
-#define _XkbAllocProps(g,n) _XkbGeomAlloc((void *)&(g)->properties,\
- &(g)->num_properties,&(g)->sz_properties,\
- (n),sizeof(XkbPropertyRec))
-#define _XkbAllocColors(g,n) _XkbGeomAlloc((void *)&(g)->colors,\
- &(g)->num_colors,&(g)->sz_colors,\
- (n),sizeof(XkbColorRec))
-#define _XkbAllocShapes(g,n) _XkbGeomAlloc((void *)&(g)->shapes,\
- &(g)->num_shapes,&(g)->sz_shapes,\
- (n),sizeof(XkbShapeRec))
-#define _XkbAllocSections(g,n) _XkbGeomAlloc((void *)&(g)->sections,\
- &(g)->num_sections,&(g)->sz_sections,\
- (n),sizeof(XkbSectionRec))
-#define _XkbAllocDoodads(g,n) _XkbGeomAlloc((void *)&(g)->doodads,\
- &(g)->num_doodads,&(g)->sz_doodads,\
- (n),sizeof(XkbDoodadRec))
-#define _XkbAllocKeyAliases(g,n) _XkbGeomAlloc((void *)&(g)->key_aliases,\
- &(g)->num_key_aliases,&(g)->sz_key_aliases,\
- (n),sizeof(XkbKeyAliasRec))
-
-#define _XkbAllocOutlines(s,n) _XkbGeomAlloc((void *)&(s)->outlines,\
- &(s)->num_outlines,&(s)->sz_outlines,\
- (n),sizeof(XkbOutlineRec))
-#define _XkbAllocRows(s,n) _XkbGeomAlloc((void *)&(s)->rows,\
- &(s)->num_rows,&(s)->sz_rows,\
- (n),sizeof(XkbRowRec))
-#define _XkbAllocPoints(o,n) _XkbGeomAlloc((void *)&(o)->points,\
- &(o)->num_points,&(o)->sz_points,\
- (n),sizeof(XkbPointRec))
-#define _XkbAllocKeys(r,n) _XkbGeomAlloc((void *)&(r)->keys,\
- &(r)->num_keys,&(r)->sz_keys,\
- (n),sizeof(XkbKeyRec))
-#define _XkbAllocOverlays(s,n) _XkbGeomAlloc((void *)&(s)->overlays,\
- &(s)->num_overlays,&(s)->sz_overlays,\
- (n),sizeof(XkbOverlayRec))
-#define _XkbAllocOverlayRows(o,n) _XkbGeomAlloc((void *)&(o)->rows,\
- &(o)->num_rows,&(o)->sz_rows,\
- (n),sizeof(XkbOverlayRowRec))
-#define _XkbAllocOverlayKeys(r,n) _XkbGeomAlloc((void *)&(r)->keys,\
- &(r)->num_keys,&(r)->sz_keys,\
- (n),sizeof(XkbOverlayKeyRec))
-
-Status
-XkbAllocGeomProps(XkbGeometryPtr geom,int nProps)
-{
- return _XkbAllocProps(geom,nProps);
-}
-
-Status
-XkbAllocGeomColors(XkbGeometryPtr geom,int nColors)
-{
- return _XkbAllocColors(geom,nColors);
-}
-
-Status
-XkbAllocGeomKeyAliases(XkbGeometryPtr geom,int nKeyAliases)
-{
- return _XkbAllocKeyAliases(geom,nKeyAliases);
-}
-
-Status
-XkbAllocGeomShapes(XkbGeometryPtr geom,int nShapes)
-{
- return _XkbAllocShapes(geom,nShapes);
-}
-
-Status
-XkbAllocGeomSections(XkbGeometryPtr geom,int nSections)
-{
- return _XkbAllocSections(geom,nSections);
-}
-
-Status
-XkbAllocGeomOverlays(XkbSectionPtr section,int nOverlays)
-{
- return _XkbAllocOverlays(section,nOverlays);
-}
-
-Status
-XkbAllocGeomOverlayRows(XkbOverlayPtr overlay,int nRows)
-{
- return _XkbAllocOverlayRows(overlay,nRows);
-}
-
-Status
-XkbAllocGeomOverlayKeys(XkbOverlayRowPtr row,int nKeys)
-{
- return _XkbAllocOverlayKeys(row,nKeys);
-}
-
-Status
-XkbAllocGeomDoodads(XkbGeometryPtr geom,int nDoodads)
-{
- return _XkbAllocDoodads(geom,nDoodads);
-}
-
-Status
-XkbAllocGeomSectionDoodads(XkbSectionPtr section,int nDoodads)
-{
- return _XkbAllocDoodads(section,nDoodads);
-}
-
-Status
-XkbAllocGeomOutlines(XkbShapePtr shape,int nOL)
-{
- return _XkbAllocOutlines(shape,nOL);
-}
-
-Status
-XkbAllocGeomRows(XkbSectionPtr section,int nRows)
-{
- return _XkbAllocRows(section,nRows);
-}
-
-Status
-XkbAllocGeomPoints(XkbOutlinePtr ol,int nPts)
-{
- return _XkbAllocPoints(ol,nPts);
-}
-
-Status
-XkbAllocGeomKeys(XkbRowPtr row,int nKeys)
-{
- return _XkbAllocKeys(row,nKeys);
-}
-
-Status
-XkbAllocGeometry(XkbDescPtr xkb,XkbGeometrySizesPtr sizes)
-{
-XkbGeometryPtr geom;
-Status rtrn;
-
- if (xkb->geom==NULL) {
- xkb->geom= calloc(1, sizeof(XkbGeometryRec));
- if (!xkb->geom)
- return BadAlloc;
- }
- geom= xkb->geom;
- if ((sizes->which&XkbGeomPropertiesMask)&&
- ((rtrn=_XkbAllocProps(geom,sizes->num_properties))!=Success)) {
- goto BAIL;
- }
- if ((sizes->which&XkbGeomColorsMask)&&
- ((rtrn=_XkbAllocColors(geom,sizes->num_colors))!=Success)) {
- goto BAIL;
- }
- if ((sizes->which&XkbGeomShapesMask)&&
- ((rtrn=_XkbAllocShapes(geom,sizes->num_shapes))!=Success)) {
- goto BAIL;
- }
- if ((sizes->which&XkbGeomSectionsMask)&&
- ((rtrn=_XkbAllocSections(geom,sizes->num_sections))!=Success)) {
- goto BAIL;
- }
- if ((sizes->which&XkbGeomDoodadsMask)&&
- ((rtrn=_XkbAllocDoodads(geom,sizes->num_doodads))!=Success)) {
- goto BAIL;
- }
- if ((sizes->which&XkbGeomKeyAliasesMask)&&
- ((rtrn=_XkbAllocKeyAliases(geom,sizes->num_key_aliases))!=Success)) {
- goto BAIL;
- }
- return Success;
-BAIL:
- XkbFreeGeometry(geom,XkbGeomAllMask,TRUE);
- xkb->geom= NULL;
- return rtrn;
-}
-
-/***====================================================================***/
-
-XkbPropertyPtr
-XkbAddGeomProperty(XkbGeometryPtr geom,char *name,char *value)
-{
-register int i;
-register XkbPropertyPtr prop;
-
- if ((!geom)||(!name)||(!value))
- return NULL;
- for (i=0,prop=geom->properties;i<geom->num_properties;i++,prop++) {
- if ((prop->name)&&(strcmp(name,prop->name)==0)) {
- free(prop->value);
- prop->value= malloc(strlen(value)+1);
- if (prop->value)
- strcpy(prop->value,value);
- return prop;
- }
- }
- if ((geom->num_properties>=geom->sz_properties)&&
- (_XkbAllocProps(geom,1)!=Success)) {
- return NULL;
- }
- prop= &geom->properties[geom->num_properties];
- prop->name= malloc(strlen(name)+1);
- if (!name)
- return NULL;
- strcpy(prop->name,name);
- prop->value= malloc(strlen(value)+1);
- if (!value) {
- free(prop->name);
- prop->name= NULL;
- return NULL;
- }
- strcpy(prop->value,value);
- geom->num_properties++;
- return prop;
-}
-
-XkbKeyAliasPtr
-XkbAddGeomKeyAlias(XkbGeometryPtr geom,char *aliasStr,char *realStr)
-{
-register int i;
-register XkbKeyAliasPtr alias;
-
- if ((!geom)||(!aliasStr)||(!realStr)||(!aliasStr[0])||(!realStr[0]))
- return NULL;
- for (i=0,alias=geom->key_aliases;i<geom->num_key_aliases;i++,alias++) {
- if (strncmp(alias->alias,aliasStr,XkbKeyNameLength)==0) {
- memset(alias->real, 0, XkbKeyNameLength);
- strncpy(alias->real,realStr,XkbKeyNameLength);
- return alias;
- }
- }
- if ((geom->num_key_aliases>=geom->sz_key_aliases)&&
- (_XkbAllocKeyAliases(geom,1)!=Success)) {
- return NULL;
- }
- alias= &geom->key_aliases[geom->num_key_aliases];
- memset(alias, 0, sizeof(XkbKeyAliasRec));
- strncpy(alias->alias,aliasStr,XkbKeyNameLength);
- strncpy(alias->real,realStr,XkbKeyNameLength);
- geom->num_key_aliases++;
- return alias;
-}
-
-XkbColorPtr
-XkbAddGeomColor(XkbGeometryPtr geom,char *spec,unsigned int pixel)
-{
-register int i;
-register XkbColorPtr color;
-
- if ((!geom)||(!spec))
- return NULL;
- for (i=0,color=geom->colors;i<geom->num_colors;i++,color++) {
- if ((color->spec)&&(strcmp(color->spec,spec)==0)) {
- color->pixel= pixel;
- return color;
- }
- }
- if ((geom->num_colors>=geom->sz_colors)&&
- (_XkbAllocColors(geom,1)!=Success)) {
- return NULL;
- }
- color= &geom->colors[geom->num_colors];
- color->pixel= pixel;
- color->spec= malloc(strlen(spec)+1);
- if (!color->spec)
- return NULL;
- strcpy(color->spec,spec);
- geom->num_colors++;
- return color;
-}
-
-XkbOutlinePtr
-XkbAddGeomOutline(XkbShapePtr shape,int sz_points)
-{
-XkbOutlinePtr outline;
-
- if ((!shape)||(sz_points<0))
- return NULL;
- if ((shape->num_outlines>=shape->sz_outlines)&&
- (_XkbAllocOutlines(shape,1)!=Success)) {
- return NULL;
- }
- outline= &shape->outlines[shape->num_outlines];
- memset(outline, 0, sizeof(XkbOutlineRec));
- if ((sz_points>0)&&(_XkbAllocPoints(outline,sz_points)!=Success))
- return NULL;
- shape->num_outlines++;
- return outline;
-}
-
-XkbShapePtr
-XkbAddGeomShape(XkbGeometryPtr geom,Atom name,int sz_outlines)
-{
-XkbShapePtr shape;
-register int i;
-
- if ((!geom)||(!name)||(sz_outlines<0))
- return NULL;
- if (geom->num_shapes>0) {
- for (shape=geom->shapes,i=0;i<geom->num_shapes;i++,shape++) {
- if (name==shape->name)
- return shape;
- }
- }
- if ((geom->num_shapes>=geom->sz_shapes)&&
- (_XkbAllocShapes(geom,1)!=Success))
- return NULL;
- shape= &geom->shapes[geom->num_shapes];
- memset(shape, 0, sizeof(XkbShapeRec));
- if ((sz_outlines>0)&&(_XkbAllocOutlines(shape,sz_outlines)!=Success))
- return NULL;
- shape->name= name;
- shape->primary= shape->approx= NULL;
- geom->num_shapes++;
- return shape;
-}
-
-XkbKeyPtr
-XkbAddGeomKey(XkbRowPtr row)
-{
-XkbKeyPtr key;
- if (!row)
- return NULL;
- if ((row->num_keys>=row->sz_keys)&&(_XkbAllocKeys(row,1)!=Success))
- return NULL;
- key= &row->keys[row->num_keys++];
- memset(key, 0, sizeof(XkbKeyRec));
- return key;
-}
-
-XkbRowPtr
-XkbAddGeomRow(XkbSectionPtr section,int sz_keys)
-{
-XkbRowPtr row;
-
- if ((!section)||(sz_keys<0))
- return NULL;
- if ((section->num_rows>=section->sz_rows)&&
- (_XkbAllocRows(section,1)!=Success))
- return NULL;
- row= §ion->rows[section->num_rows];
- memset(row, 0, sizeof(XkbRowRec));
- if ((sz_keys>0)&&(_XkbAllocKeys(row,sz_keys)!=Success))
- return NULL;
- section->num_rows++;
- return row;
-}
-
-XkbSectionPtr
-XkbAddGeomSection( XkbGeometryPtr geom,
- Atom name,
- int sz_rows,
- int sz_doodads,
- int sz_over)
-{
-register int i;
-XkbSectionPtr section;
-
- if ((!geom)||(name==None)||(sz_rows<0))
- return NULL;
- for (i=0,section=geom->sections;i<geom->num_sections;i++,section++) {
- if (section->name!=name)
- continue;
- if (((sz_rows>0)&&(_XkbAllocRows(section,sz_rows)!=Success))||
- ((sz_doodads>0)&&(_XkbAllocDoodads(section,sz_doodads)!=Success))||
- ((sz_over>0)&&(_XkbAllocOverlays(section,sz_over)!=Success)))
- return NULL;
- return section;
- }
- if ((geom->num_sections>=geom->sz_sections)&&
- (_XkbAllocSections(geom,1)!=Success))
- return NULL;
- section= &geom->sections[geom->num_sections];
- if ((sz_rows>0)&&(_XkbAllocRows(section,sz_rows)!=Success))
- return NULL;
- if ((sz_doodads>0)&&(_XkbAllocDoodads(section,sz_doodads)!=Success)) {
- if (section->rows) {
- free(section->rows);
- section->rows= NULL;
- section->sz_rows= section->num_rows= 0;
- }
- return NULL;
- }
- section->name= name;
- geom->num_sections++;
- return section;
-}
-
-XkbDoodadPtr
-XkbAddGeomDoodad(XkbGeometryPtr geom,XkbSectionPtr section,Atom name)
-{
-XkbDoodadPtr old,doodad;
-register int i,nDoodads;
-
- if ((!geom)||(name==None))
- return NULL;
- if ((section!=NULL)&&(section->num_doodads>0)) {
- old= section->doodads;
- nDoodads= section->num_doodads;
- }
- else {
- old= geom->doodads;
- nDoodads= geom->num_doodads;
- }
- for (i=0,doodad=old;i<nDoodads;i++,doodad++) {
- if (doodad->any.name==name)
- return doodad;
- }
- if (section) {
- if ((section->num_doodads>=geom->sz_doodads)&&
- (_XkbAllocDoodads(section,1)!=Success)) {
- return NULL;
- }
- doodad= §ion->doodads[section->num_doodads++];
- }
- else {
- if ((geom->num_doodads>=geom->sz_doodads)&&
- (_XkbAllocDoodads(geom,1)!=Success))
- return NULL;
- doodad= &geom->doodads[geom->num_doodads++];
- }
- memset(doodad, 0, sizeof(XkbDoodadRec));
- doodad->any.name= name;
- return doodad;
-}
-
-XkbOverlayKeyPtr
-XkbAddGeomOverlayKey( XkbOverlayPtr overlay,
- XkbOverlayRowPtr row,
- char * over,
- char * under)
-{
-register int i;
-XkbOverlayKeyPtr key;
-XkbSectionPtr section;
-XkbRowPtr row_under;
-Bool found;
-
- if ((!overlay)||(!row)||(!over)||(!under))
- return NULL;
- section= overlay->section_under;
- if (row->row_under>=section->num_rows)
- return NULL;
- row_under= §ion->rows[row->row_under];
- for (i=0,found=FALSE;i<row_under->num_keys;i++) {
- if (strncmp(under,row_under->keys[i].name.name,XkbKeyNameLength)==0) {
- found= TRUE;
- break;
- }
- }
- if (!found)
- return NULL;
- if ((row->num_keys>=row->sz_keys)&&(_XkbAllocOverlayKeys(row,1)!=Success))
- return NULL;
- key= &row->keys[row->num_keys];
- strncpy(key->under.name,under,XkbKeyNameLength);
- strncpy(key->over.name,over,XkbKeyNameLength);
- row->num_keys++;
- return key;
-}
-
-XkbOverlayRowPtr
-XkbAddGeomOverlayRow(XkbOverlayPtr overlay,int row_under,int sz_keys)
-{
-register int i;
-XkbOverlayRowPtr row;
-
- if ((!overlay)||(sz_keys<0))
- return NULL;
- if (row_under>=overlay->section_under->num_rows)
- return NULL;
- for (i=0;i<overlay->num_rows;i++) {
- if (overlay->rows[i].row_under==row_under) {
- row= &overlay->rows[i];
- if ((row->sz_keys<sz_keys)&&
- (_XkbAllocOverlayKeys(row,sz_keys)!=Success)) {
- return NULL;
- }
- return &overlay->rows[i];
- }
- }
- if ((overlay->num_rows>=overlay->sz_rows)&&
- (_XkbAllocOverlayRows(overlay,1)!=Success))
- return NULL;
- row= &overlay->rows[overlay->num_rows];
- memset(row, 0, sizeof(XkbOverlayRowRec));
- if ((sz_keys>0)&&(_XkbAllocOverlayKeys(row,sz_keys)!=Success))
- return NULL;
- row->row_under= row_under;
- overlay->num_rows++;
- return row;
-}
-
-XkbOverlayPtr
-XkbAddGeomOverlay(XkbSectionPtr section,Atom name,int sz_rows)
-{
-register int i;
-XkbOverlayPtr overlay;
-
- if ((!section)||(name==None)||(sz_rows==0))
- return NULL;
-
- for (i=0,overlay=section->overlays;i<section->num_overlays;i++,overlay++) {
- if (overlay->name==name) {
- if ((sz_rows>0)&&(_XkbAllocOverlayRows(overlay,sz_rows)!=Success))
- return NULL;
- return overlay;
- }
- }
- if ((section->num_overlays>=section->sz_overlays)&&
- (_XkbAllocOverlays(section,1)!=Success))
- return NULL;
- overlay= §ion->overlays[section->num_overlays];
- if ((sz_rows>0)&&(_XkbAllocOverlayRows(overlay,sz_rows)!=Success))
- return NULL;
- overlay->name= name;
- overlay->section_under= section;
- section->num_overlays++;
- return overlay;
-}
+/************************************************************ +Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc. + +Permission 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 that both that copyright +notice and this permission notice appear in supporting +documentation, and that the name of Silicon Graphics not be +used in advertising or publicity pertaining to distribution +of the software without specific prior written permission. +Silicon Graphics makes no representation about the suitability +of this software for any purpose. It is provided "as is" +without any express or implied warranty. + +SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS +SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON +GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL +DAMAGES OR ANY 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 THIS SOFTWARE. + +********************************************************/ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + + +#include <stdio.h> +#include <X11/X.h> +#include <X11/Xproto.h> +#include "misc.h" +#include "inputstr.h" +#include <xkbsrv.h> +#include "xkbgeom.h" + +/***====================================================================***/ + +static void +_XkbFreeGeomLeafElems( Bool freeAll, + int first, + int count, + unsigned short * num_inout, + unsigned short * sz_inout, + char ** elems, + unsigned int elem_sz) +{ + if ((freeAll)||(*elems==NULL)) { + *num_inout= *sz_inout= 0; + free(*elems); + *elems = NULL; + return; + } + + if ((first>=(*num_inout))||(first<0)||(count<1)) + return; + + if (first+count>=(*num_inout)) { + /* truncating the array is easy */ + (*num_inout)= first; + } + else { + char * ptr; + int extra; + ptr= *elems; + extra= ((*num_inout)-(first+count))*elem_sz; + if (extra>0) + memmove(&ptr[first*elem_sz],&ptr[(first+count)*elem_sz],extra); + (*num_inout)-= count; + } + return; +} + +typedef void (*ContentsClearFunc)( + char * /* priv */ +); + +static void +_XkbFreeGeomNonLeafElems( Bool freeAll, + int first, + int count, + unsigned short * num_inout, + unsigned short * sz_inout, + char ** elems, + unsigned int elem_sz, + ContentsClearFunc freeFunc) +{ +register int i; +register char *ptr; + + if (freeAll) { + first= 0; + count= (*num_inout); + } + else if ((first>=(*num_inout))||(first<0)||(count<1)) + return; + else if (first+count>(*num_inout)) + count= (*num_inout)-first; + if (*elems==NULL) + return; + + if (freeFunc) { + ptr= *elems; + ptr+= first*elem_sz; + for (i=0;i<count;i++) { + (*freeFunc)(ptr); + ptr+= elem_sz; + } + } + if (freeAll) { + (*num_inout)= (*sz_inout)= 0; + free(*elems); + *elems = NULL; + } + else if (first+count>=(*num_inout)) + *num_inout= first; + else { + i= ((*num_inout)-(first+count))*elem_sz; + ptr= *elems; + memmove(&ptr[first*elem_sz],&ptr[(first+count)*elem_sz],i); + (*num_inout)-= count; + } + return; +} + +/***====================================================================***/ + +static void +_XkbClearProperty(char *prop_in) +{ +XkbPropertyPtr prop= (XkbPropertyPtr)prop_in; + + free(prop->name); + prop->name = NULL; + free(prop->value); + prop->value = NULL; + return; +} + +void +XkbFreeGeomProperties( XkbGeometryPtr geom, + int first, + int count, + Bool freeAll) +{ + _XkbFreeGeomNonLeafElems(freeAll,first,count, + &geom->num_properties,&geom->sz_properties, + (char **)&geom->properties, + sizeof(XkbPropertyRec),_XkbClearProperty); + return; +} + +/***====================================================================***/ + +void +XkbFreeGeomKeyAliases( XkbGeometryPtr geom, + int first, + int count, + Bool freeAll) +{ + _XkbFreeGeomLeafElems(freeAll,first,count, + &geom->num_key_aliases,&geom->sz_key_aliases, + (char **)&geom->key_aliases, + sizeof(XkbKeyAliasRec)); + return; +} + +/***====================================================================***/ + +static void +_XkbClearColor(char *color_in) +{ +XkbColorPtr color= (XkbColorPtr)color_in; + + free(color->spec); + return; +} + +void +XkbFreeGeomColors(XkbGeometryPtr geom,int first,int count,Bool freeAll) +{ + _XkbFreeGeomNonLeafElems(freeAll,first,count, + &geom->num_colors,&geom->sz_colors, + (char **)&geom->colors, + sizeof(XkbColorRec),_XkbClearColor); + return; +} + +/***====================================================================***/ + +void +XkbFreeGeomPoints(XkbOutlinePtr outline,int first,int count,Bool freeAll) +{ + _XkbFreeGeomLeafElems(freeAll,first,count, + &outline->num_points,&outline->sz_points, + (char **)&outline->points, + sizeof(XkbPointRec)); + return; +} + +/***====================================================================***/ + +static void +_XkbClearOutline(char *outline_in) +{ +XkbOutlinePtr outline= (XkbOutlinePtr)outline_in; + + if (outline->points!=NULL) + XkbFreeGeomPoints(outline,0,outline->num_points,TRUE); + return; +} + +void +XkbFreeGeomOutlines(XkbShapePtr shape,int first,int count,Bool freeAll) +{ + _XkbFreeGeomNonLeafElems(freeAll,first,count, + &shape->num_outlines,&shape->sz_outlines, + (char **)&shape->outlines, + sizeof(XkbOutlineRec),_XkbClearOutline); + + return; +} + +/***====================================================================***/ + +static void +_XkbClearShape(char *shape_in) +{ +XkbShapePtr shape= (XkbShapePtr)shape_in; + + if (shape->outlines) + XkbFreeGeomOutlines(shape,0,shape->num_outlines,TRUE); + return; +} + +void +XkbFreeGeomShapes(XkbGeometryPtr geom,int first,int count,Bool freeAll) +{ + _XkbFreeGeomNonLeafElems(freeAll,first,count, + &geom->num_shapes,&geom->sz_shapes, + (char **)&geom->shapes, + sizeof(XkbShapeRec),_XkbClearShape); + return; +} + +/***====================================================================***/ + +void +XkbFreeGeomOverlayKeys(XkbOverlayRowPtr row,int first,int count,Bool freeAll) +{ + _XkbFreeGeomLeafElems(freeAll,first,count, + &row->num_keys,&row->sz_keys, + (char **)&row->keys, + sizeof(XkbOverlayKeyRec)); + return; +} + +/***====================================================================***/ + +static void +_XkbClearOverlayRow(char *row_in) +{ +XkbOverlayRowPtr row= (XkbOverlayRowPtr)row_in; + + if (row->keys!=NULL) + XkbFreeGeomOverlayKeys(row,0,row->num_keys,TRUE); + return; +} + +void +XkbFreeGeomOverlayRows(XkbOverlayPtr overlay,int first,int count,Bool freeAll) +{ + _XkbFreeGeomNonLeafElems(freeAll,first,count, + &overlay->num_rows,&overlay->sz_rows, + (char **)&overlay->rows, + sizeof(XkbOverlayRowRec),_XkbClearOverlayRow); + return; +} + +/***====================================================================***/ + +static void +_XkbClearOverlay(char *overlay_in) +{ +XkbOverlayPtr overlay= (XkbOverlayPtr)overlay_in; + + if (overlay->rows!=NULL) + XkbFreeGeomOverlayRows(overlay,0,overlay->num_rows,TRUE); + return; +} + +void +XkbFreeGeomOverlays(XkbSectionPtr section,int first,int count,Bool freeAll) +{ + _XkbFreeGeomNonLeafElems(freeAll,first,count, + §ion->num_overlays,§ion->sz_overlays, + (char **)§ion->overlays, + sizeof(XkbOverlayRec),_XkbClearOverlay); + return; +} + +/***====================================================================***/ + +void +XkbFreeGeomKeys(XkbRowPtr row,int first,int count,Bool freeAll) +{ + _XkbFreeGeomLeafElems(freeAll,first,count, + &row->num_keys,&row->sz_keys, + (char **)&row->keys, + sizeof(XkbKeyRec)); + return; +} + +/***====================================================================***/ + +static void +_XkbClearRow(char *row_in) +{ +XkbRowPtr row= (XkbRowPtr)row_in; + + if (row->keys!=NULL) + XkbFreeGeomKeys(row,0,row->num_keys,TRUE); + return; +} + +void +XkbFreeGeomRows(XkbSectionPtr section,int first,int count,Bool freeAll) +{ + _XkbFreeGeomNonLeafElems(freeAll,first,count, + §ion->num_rows,§ion->sz_rows, + (char **)§ion->rows, + sizeof(XkbRowRec),_XkbClearRow); +} + +/***====================================================================***/ + +static void +_XkbClearSection(char *section_in) +{ +XkbSectionPtr section= (XkbSectionPtr)section_in; + + if (section->rows!=NULL) + XkbFreeGeomRows(section,0,section->num_rows,TRUE); + if (section->doodads!=NULL) { + XkbFreeGeomDoodads(section->doodads,section->num_doodads,TRUE); + section->doodads= NULL; + } + return; +} + +void +XkbFreeGeomSections(XkbGeometryPtr geom,int first,int count,Bool freeAll) +{ + _XkbFreeGeomNonLeafElems(freeAll,first,count, + &geom->num_sections,&geom->sz_sections, + (char **)&geom->sections, + sizeof(XkbSectionRec),_XkbClearSection); + return; +} + +/***====================================================================***/ + +static void +_XkbClearDoodad(char *doodad_in) +{ +XkbDoodadPtr doodad= (XkbDoodadPtr)doodad_in; + + switch (doodad->any.type) { + case XkbTextDoodad: + { + free(doodad->text.text); + doodad->text.text = NULL; + free(doodad->text.font); + doodad->text.font = NULL; + } + break; + case XkbLogoDoodad: + { + free(doodad->logo.logo_name); + doodad->logo.logo_name = NULL; + } + break; + } + return; +} + +void +XkbFreeGeomDoodads(XkbDoodadPtr doodads,int nDoodads,Bool freeAll) +{ +register int i; +register XkbDoodadPtr doodad; + + if (doodads) { + for (i=0,doodad= doodads;i<nDoodads;i++,doodad++) { + _XkbClearDoodad((char *)doodad); + } + if (freeAll) + free(doodads); + } + return; +} + +void +XkbFreeGeometry(XkbGeometryPtr geom,unsigned which,Bool freeMap) +{ + if (geom==NULL) + return; + if (freeMap) + which= XkbGeomAllMask; + if ((which&XkbGeomPropertiesMask)&&(geom->properties!=NULL)) + XkbFreeGeomProperties(geom,0,geom->num_properties,TRUE); + if ((which&XkbGeomColorsMask)&&(geom->colors!=NULL)) + XkbFreeGeomColors(geom,0,geom->num_colors,TRUE); + if ((which&XkbGeomShapesMask)&&(geom->shapes!=NULL)) + XkbFreeGeomShapes(geom,0,geom->num_shapes,TRUE); + if ((which&XkbGeomSectionsMask)&&(geom->sections!=NULL)) + XkbFreeGeomSections(geom,0,geom->num_sections,TRUE); + if ((which&XkbGeomDoodadsMask)&&(geom->doodads!= NULL)) { + XkbFreeGeomDoodads(geom->doodads,geom->num_doodads,TRUE); + geom->doodads= NULL; + geom->num_doodads= geom->sz_doodads= 0; + } + if ((which&XkbGeomKeyAliasesMask)&&(geom->key_aliases!=NULL)) + XkbFreeGeomKeyAliases(geom,0,geom->num_key_aliases,TRUE); + if (freeMap) { + free(geom->label_font); + geom->label_font = NULL; + free(geom); + } + return; +} + +/***====================================================================***/ + +static Status +_XkbGeomAlloc( void ** old, + unsigned short * num, + unsigned short * total, + int num_new, + size_t sz_elem) +{ + if (num_new<1) + return Success; + if ((*old)==NULL) + *num= *total= 0; + + if ((*num)+num_new<=(*total)) + return Success; + + *total= (*num)+num_new; + if ((*old)!=NULL) + (*old)= realloc((*old),(*total)*sz_elem); + else (*old)= calloc((*total),sz_elem); + if ((*old)==NULL) { + *total= *num= 0; + return BadAlloc; + } + + if (*num>0) { + char *tmp= (char *)(*old); + memset(&tmp[sz_elem*(*num)], 0, (num_new*sz_elem)); + } + return Success; +} + +#define _XkbAllocProps(g,n) _XkbGeomAlloc((void *)&(g)->properties,\ + &(g)->num_properties,&(g)->sz_properties,\ + (n),sizeof(XkbPropertyRec)) +#define _XkbAllocColors(g,n) _XkbGeomAlloc((void *)&(g)->colors,\ + &(g)->num_colors,&(g)->sz_colors,\ + (n),sizeof(XkbColorRec)) +#define _XkbAllocShapes(g,n) _XkbGeomAlloc((void *)&(g)->shapes,\ + &(g)->num_shapes,&(g)->sz_shapes,\ + (n),sizeof(XkbShapeRec)) +#define _XkbAllocSections(g,n) _XkbGeomAlloc((void *)&(g)->sections,\ + &(g)->num_sections,&(g)->sz_sections,\ + (n),sizeof(XkbSectionRec)) +#define _XkbAllocDoodads(g,n) _XkbGeomAlloc((void *)&(g)->doodads,\ + &(g)->num_doodads,&(g)->sz_doodads,\ + (n),sizeof(XkbDoodadRec)) +#define _XkbAllocKeyAliases(g,n) _XkbGeomAlloc((void *)&(g)->key_aliases,\ + &(g)->num_key_aliases,&(g)->sz_key_aliases,\ + (n),sizeof(XkbKeyAliasRec)) + +#define _XkbAllocOutlines(s,n) _XkbGeomAlloc((void *)&(s)->outlines,\ + &(s)->num_outlines,&(s)->sz_outlines,\ + (n),sizeof(XkbOutlineRec)) +#define _XkbAllocRows(s,n) _XkbGeomAlloc((void *)&(s)->rows,\ + &(s)->num_rows,&(s)->sz_rows,\ + (n),sizeof(XkbRowRec)) +#define _XkbAllocPoints(o,n) _XkbGeomAlloc((void *)&(o)->points,\ + &(o)->num_points,&(o)->sz_points,\ + (n),sizeof(XkbPointRec)) +#define _XkbAllocKeys(r,n) _XkbGeomAlloc((void *)&(r)->keys,\ + &(r)->num_keys,&(r)->sz_keys,\ + (n),sizeof(XkbKeyRec)) +#define _XkbAllocOverlays(s,n) _XkbGeomAlloc((void *)&(s)->overlays,\ + &(s)->num_overlays,&(s)->sz_overlays,\ + (n),sizeof(XkbOverlayRec)) +#define _XkbAllocOverlayRows(o,n) _XkbGeomAlloc((void *)&(o)->rows,\ + &(o)->num_rows,&(o)->sz_rows,\ + (n),sizeof(XkbOverlayRowRec)) +#define _XkbAllocOverlayKeys(r,n) _XkbGeomAlloc((void *)&(r)->keys,\ + &(r)->num_keys,&(r)->sz_keys,\ + (n),sizeof(XkbOverlayKeyRec)) + +Status +XkbAllocGeomProps(XkbGeometryPtr geom,int nProps) +{ + return _XkbAllocProps(geom,nProps); +} + +Status +XkbAllocGeomColors(XkbGeometryPtr geom,int nColors) +{ + return _XkbAllocColors(geom,nColors); +} + +Status +XkbAllocGeomKeyAliases(XkbGeometryPtr geom,int nKeyAliases) +{ + return _XkbAllocKeyAliases(geom,nKeyAliases); +} + +Status +XkbAllocGeomShapes(XkbGeometryPtr geom,int nShapes) +{ + return _XkbAllocShapes(geom,nShapes); +} + +Status +XkbAllocGeomSections(XkbGeometryPtr geom,int nSections) +{ + return _XkbAllocSections(geom,nSections); +} + +Status +XkbAllocGeomOverlays(XkbSectionPtr section,int nOverlays) +{ + return _XkbAllocOverlays(section,nOverlays); +} + +Status +XkbAllocGeomOverlayRows(XkbOverlayPtr overlay,int nRows) +{ + return _XkbAllocOverlayRows(overlay,nRows); +} + +Status +XkbAllocGeomOverlayKeys(XkbOverlayRowPtr row,int nKeys) +{ + return _XkbAllocOverlayKeys(row,nKeys); +} + +Status +XkbAllocGeomDoodads(XkbGeometryPtr geom,int nDoodads) +{ + return _XkbAllocDoodads(geom,nDoodads); +} + +Status +XkbAllocGeomSectionDoodads(XkbSectionPtr section,int nDoodads) +{ + return _XkbAllocDoodads(section,nDoodads); +} + +Status +XkbAllocGeomOutlines(XkbShapePtr shape,int nOL) +{ + return _XkbAllocOutlines(shape,nOL); +} + +Status +XkbAllocGeomRows(XkbSectionPtr section,int nRows) +{ + return _XkbAllocRows(section,nRows); +} + +Status +XkbAllocGeomPoints(XkbOutlinePtr ol,int nPts) +{ + return _XkbAllocPoints(ol,nPts); +} + +Status +XkbAllocGeomKeys(XkbRowPtr row,int nKeys) +{ + return _XkbAllocKeys(row,nKeys); +} + +Status +XkbAllocGeometry(XkbDescPtr xkb,XkbGeometrySizesPtr sizes) +{ +XkbGeometryPtr geom; +Status rtrn; + + if (xkb->geom==NULL) { + xkb->geom= calloc(1, sizeof(XkbGeometryRec)); + if (!xkb->geom) + return BadAlloc; + } + geom= xkb->geom; + if ((sizes->which&XkbGeomPropertiesMask)&& + ((rtrn=_XkbAllocProps(geom,sizes->num_properties))!=Success)) { + goto BAIL; + } + if ((sizes->which&XkbGeomColorsMask)&& + ((rtrn=_XkbAllocColors(geom,sizes->num_colors))!=Success)) { + goto BAIL; + } + if ((sizes->which&XkbGeomShapesMask)&& + ((rtrn=_XkbAllocShapes(geom,sizes->num_shapes))!=Success)) { + goto BAIL; + } + if ((sizes->which&XkbGeomSectionsMask)&& + ((rtrn=_XkbAllocSections(geom,sizes->num_sections))!=Success)) { + goto BAIL; + } + if ((sizes->which&XkbGeomDoodadsMask)&& + ((rtrn=_XkbAllocDoodads(geom,sizes->num_doodads))!=Success)) { + goto BAIL; + } + if ((sizes->which&XkbGeomKeyAliasesMask)&& + ((rtrn=_XkbAllocKeyAliases(geom,sizes->num_key_aliases))!=Success)) { + goto BAIL; + } + return Success; +BAIL: + XkbFreeGeometry(geom,XkbGeomAllMask,TRUE); + xkb->geom= NULL; + return rtrn; +} + +/***====================================================================***/ + +XkbPropertyPtr +XkbAddGeomProperty(XkbGeometryPtr geom,char *name,char *value) +{ +register int i; +register XkbPropertyPtr prop; + + if ((!geom)||(!name)||(!value)) + return NULL; + for (i=0,prop=geom->properties;i<geom->num_properties;i++,prop++) { + if ((prop->name)&&(strcmp(name,prop->name)==0)) { + free(prop->value); + prop->value= strdup(value); + return prop; + } + } + if ((geom->num_properties>=geom->sz_properties)&& + (_XkbAllocProps(geom,1)!=Success)) { + return NULL; + } + prop= &geom->properties[geom->num_properties]; + prop->name= strdup(name); + if (!prop->name) + return NULL; + prop->value= strdup(value); + if (!prop->value) { + free(prop->name); + prop->name= NULL; + return NULL; + } + geom->num_properties++; + return prop; +} + +XkbKeyAliasPtr +XkbAddGeomKeyAlias(XkbGeometryPtr geom,char *aliasStr,char *realStr) +{ +register int i; +register XkbKeyAliasPtr alias; + + if ((!geom)||(!aliasStr)||(!realStr)||(!aliasStr[0])||(!realStr[0])) + return NULL; + for (i=0,alias=geom->key_aliases;i<geom->num_key_aliases;i++,alias++) { + if (strncmp(alias->alias,aliasStr,XkbKeyNameLength)==0) { + memset(alias->real, 0, XkbKeyNameLength); + strncpy(alias->real,realStr,XkbKeyNameLength); + return alias; + } + } + if ((geom->num_key_aliases>=geom->sz_key_aliases)&& + (_XkbAllocKeyAliases(geom,1)!=Success)) { + return NULL; + } + alias= &geom->key_aliases[geom->num_key_aliases]; + memset(alias, 0, sizeof(XkbKeyAliasRec)); + strncpy(alias->alias,aliasStr,XkbKeyNameLength); + strncpy(alias->real,realStr,XkbKeyNameLength); + geom->num_key_aliases++; + return alias; +} + +XkbColorPtr +XkbAddGeomColor(XkbGeometryPtr geom,char *spec,unsigned int pixel) +{ +register int i; +register XkbColorPtr color; + + if ((!geom)||(!spec)) + return NULL; + for (i=0,color=geom->colors;i<geom->num_colors;i++,color++) { + if ((color->spec)&&(strcmp(color->spec,spec)==0)) { + color->pixel= pixel; + return color; + } + } + if ((geom->num_colors>=geom->sz_colors)&& + (_XkbAllocColors(geom,1)!=Success)) { + return NULL; + } + color= &geom->colors[geom->num_colors]; + color->pixel= pixel; + color->spec= strdup(spec); + if (!color->spec) + return NULL; + geom->num_colors++; + return color; +} + +XkbOutlinePtr +XkbAddGeomOutline(XkbShapePtr shape,int sz_points) +{ +XkbOutlinePtr outline; + + if ((!shape)||(sz_points<0)) + return NULL; + if ((shape->num_outlines>=shape->sz_outlines)&& + (_XkbAllocOutlines(shape,1)!=Success)) { + return NULL; + } + outline= &shape->outlines[shape->num_outlines]; + memset(outline, 0, sizeof(XkbOutlineRec)); + if ((sz_points>0)&&(_XkbAllocPoints(outline,sz_points)!=Success)) + return NULL; + shape->num_outlines++; + return outline; +} + +XkbShapePtr +XkbAddGeomShape(XkbGeometryPtr geom,Atom name,int sz_outlines) +{ +XkbShapePtr shape; +register int i; + + if ((!geom)||(!name)||(sz_outlines<0)) + return NULL; + if (geom->num_shapes>0) { + for (shape=geom->shapes,i=0;i<geom->num_shapes;i++,shape++) { + if (name==shape->name) + return shape; + } + } + if ((geom->num_shapes>=geom->sz_shapes)&& + (_XkbAllocShapes(geom,1)!=Success)) + return NULL; + shape= &geom->shapes[geom->num_shapes]; + memset(shape, 0, sizeof(XkbShapeRec)); + if ((sz_outlines>0)&&(_XkbAllocOutlines(shape,sz_outlines)!=Success)) + return NULL; + shape->name= name; + shape->primary= shape->approx= NULL; + geom->num_shapes++; + return shape; +} + +XkbKeyPtr +XkbAddGeomKey(XkbRowPtr row) +{ +XkbKeyPtr key; + if (!row) + return NULL; + if ((row->num_keys>=row->sz_keys)&&(_XkbAllocKeys(row,1)!=Success)) + return NULL; + key= &row->keys[row->num_keys++]; + memset(key, 0, sizeof(XkbKeyRec)); + return key; +} + +XkbRowPtr +XkbAddGeomRow(XkbSectionPtr section,int sz_keys) +{ +XkbRowPtr row; + + if ((!section)||(sz_keys<0)) + return NULL; + if ((section->num_rows>=section->sz_rows)&& + (_XkbAllocRows(section,1)!=Success)) + return NULL; + row= §ion->rows[section->num_rows]; + memset(row, 0, sizeof(XkbRowRec)); + if ((sz_keys>0)&&(_XkbAllocKeys(row,sz_keys)!=Success)) + return NULL; + section->num_rows++; + return row; +} + +XkbSectionPtr +XkbAddGeomSection( XkbGeometryPtr geom, + Atom name, + int sz_rows, + int sz_doodads, + int sz_over) +{ +register int i; +XkbSectionPtr section; + + if ((!geom)||(name==None)||(sz_rows<0)) + return NULL; + for (i=0,section=geom->sections;i<geom->num_sections;i++,section++) { + if (section->name!=name) + continue; + if (((sz_rows>0)&&(_XkbAllocRows(section,sz_rows)!=Success))|| + ((sz_doodads>0)&&(_XkbAllocDoodads(section,sz_doodads)!=Success))|| + ((sz_over>0)&&(_XkbAllocOverlays(section,sz_over)!=Success))) + return NULL; + return section; + } + if ((geom->num_sections>=geom->sz_sections)&& + (_XkbAllocSections(geom,1)!=Success)) + return NULL; + section= &geom->sections[geom->num_sections]; + if ((sz_rows>0)&&(_XkbAllocRows(section,sz_rows)!=Success)) + return NULL; + if ((sz_doodads>0)&&(_XkbAllocDoodads(section,sz_doodads)!=Success)) { + if (section->rows) { + free(section->rows); + section->rows= NULL; + section->sz_rows= section->num_rows= 0; + } + return NULL; + } + section->name= name; + geom->num_sections++; + return section; +} + +XkbDoodadPtr +XkbAddGeomDoodad(XkbGeometryPtr geom,XkbSectionPtr section,Atom name) +{ +XkbDoodadPtr old,doodad; +register int i,nDoodads; + + if ((!geom)||(name==None)) + return NULL; + if ((section!=NULL)&&(section->num_doodads>0)) { + old= section->doodads; + nDoodads= section->num_doodads; + } + else { + old= geom->doodads; + nDoodads= geom->num_doodads; + } + for (i=0,doodad=old;i<nDoodads;i++,doodad++) { + if (doodad->any.name==name) + return doodad; + } + if (section) { + if ((section->num_doodads>=geom->sz_doodads)&& + (_XkbAllocDoodads(section,1)!=Success)) { + return NULL; + } + doodad= §ion->doodads[section->num_doodads++]; + } + else { + if ((geom->num_doodads>=geom->sz_doodads)&& + (_XkbAllocDoodads(geom,1)!=Success)) + return NULL; + doodad= &geom->doodads[geom->num_doodads++]; + } + memset(doodad, 0, sizeof(XkbDoodadRec)); + doodad->any.name= name; + return doodad; +} + +XkbOverlayKeyPtr +XkbAddGeomOverlayKey( XkbOverlayPtr overlay, + XkbOverlayRowPtr row, + char * over, + char * under) +{ +register int i; +XkbOverlayKeyPtr key; +XkbSectionPtr section; +XkbRowPtr row_under; +Bool found; + + if ((!overlay)||(!row)||(!over)||(!under)) + return NULL; + section= overlay->section_under; + if (row->row_under>=section->num_rows) + return NULL; + row_under= §ion->rows[row->row_under]; + for (i=0,found=FALSE;i<row_under->num_keys;i++) { + if (strncmp(under,row_under->keys[i].name.name,XkbKeyNameLength)==0) { + found= TRUE; + break; + } + } + if (!found) + return NULL; + if ((row->num_keys>=row->sz_keys)&&(_XkbAllocOverlayKeys(row,1)!=Success)) + return NULL; + key= &row->keys[row->num_keys]; + strncpy(key->under.name,under,XkbKeyNameLength); + strncpy(key->over.name,over,XkbKeyNameLength); + row->num_keys++; + return key; +} + +XkbOverlayRowPtr +XkbAddGeomOverlayRow(XkbOverlayPtr overlay,int row_under,int sz_keys) +{ +register int i; +XkbOverlayRowPtr row; + + if ((!overlay)||(sz_keys<0)) + return NULL; + if (row_under>=overlay->section_under->num_rows) + return NULL; + for (i=0;i<overlay->num_rows;i++) { + if (overlay->rows[i].row_under==row_under) { + row= &overlay->rows[i]; + if ((row->sz_keys<sz_keys)&& + (_XkbAllocOverlayKeys(row,sz_keys)!=Success)) { + return NULL; + } + return &overlay->rows[i]; + } + } + if ((overlay->num_rows>=overlay->sz_rows)&& + (_XkbAllocOverlayRows(overlay,1)!=Success)) + return NULL; + row= &overlay->rows[overlay->num_rows]; + memset(row, 0, sizeof(XkbOverlayRowRec)); + if ((sz_keys>0)&&(_XkbAllocOverlayKeys(row,sz_keys)!=Success)) + return NULL; + row->row_under= row_under; + overlay->num_rows++; + return row; +} + +XkbOverlayPtr +XkbAddGeomOverlay(XkbSectionPtr section,Atom name,int sz_rows) +{ +register int i; +XkbOverlayPtr overlay; + + if ((!section)||(name==None)||(sz_rows==0)) + return NULL; + + for (i=0,overlay=section->overlays;i<section->num_overlays;i++,overlay++) { + if (overlay->name==name) { + if ((sz_rows>0)&&(_XkbAllocOverlayRows(overlay,sz_rows)!=Success)) + return NULL; + return overlay; + } + } + if ((section->num_overlays>=section->sz_overlays)&& + (_XkbAllocOverlays(section,1)!=Success)) + return NULL; + overlay= §ion->overlays[section->num_overlays]; + if ((sz_rows>0)&&(_XkbAllocOverlayRows(overlay,sz_rows)!=Success)) + return NULL; + overlay->name= name; + overlay->section_under= section; + section->num_overlays++; + return overlay; +} diff --git a/xorg-server/xkb/ddxLoad.c b/xorg-server/xkb/ddxLoad.c index be946d89e..dc3c844c9 100644 --- a/xorg-server/xkb/ddxLoad.c +++ b/xorg-server/xkb/ddxLoad.c @@ -1,503 +1,504 @@ -/************************************************************
-Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc.
-
-Permission 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 that both that copyright
-notice and this permission notice appear in supporting
-documentation, and that the name of Silicon Graphics not be
-used in advertising or publicity pertaining to distribution
-of the software without specific prior written permission.
-Silicon Graphics makes no representation about the suitability
-of this software for any purpose. It is provided "as is"
-without any express or implied warranty.
-
-SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
-SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
-AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
-GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
-DAMAGES OR ANY 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 THIS SOFTWARE.
-
-********************************************************/
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#include <xkb-config.h>
-
-#include <stdio.h>
-#include <ctype.h>
-#include <X11/X.h>
-#include <X11/Xos.h>
-#include <X11/Xproto.h>
-#include <X11/keysym.h>
-#include <X11/extensions/XKM.h>
-#include "inputstr.h"
-#include "scrnintstr.h"
-#include "windowstr.h"
-#define XKBSRV_NEED_FILE_FUNCS
-#include <xkbsrv.h>
-#include <X11/extensions/XI.h>
-#include "xkb.h"
-
- /*
- * If XKM_OUTPUT_DIR specifies a path without a leading slash, it is
- * relative to the top-level XKB configuration directory.
- * Making the server write to a subdirectory of that directory
- * requires some work in the general case (install procedure
- * has to create links to /var or somesuch on many machines),
- * so we just compile into /usr/tmp for now.
- */
-#ifndef XKM_OUTPUT_DIR
-#define XKM_OUTPUT_DIR "compiled/"
-#endif
-
-#define PRE_ERROR_MSG "\"The XKEYBOARD keymap compiler (xkbcomp) reports:\""
-#define ERROR_PREFIX "\"> \""
-#define POST_ERROR_MSG1 "\"Errors from xkbcomp are not fatal to the X server\""
-#define POST_ERROR_MSG2 "\"End of messages from xkbcomp\""
-
-#if defined(WIN32)
-#define PATHSEPARATOR "\\"
-#else
-#define PATHSEPARATOR "/"
-#endif
-
-#ifdef WIN32
-
-#include <X11/Xwindows.h>
-const char*
-Win32TempDir()
-{
- static char buffer[PATH_MAX];
- if (GetTempPath(sizeof(buffer), buffer))
- {
- int len;
- buffer[sizeof(buffer)-1] = 0;
- len = strlen(buffer);
- if (len > 0)
- if (buffer[len-1] == '\\')
- buffer[len-1] = 0;
- return buffer;
- }
- if (getenv("TEMP") != NULL)
- return getenv("TEMP");
- else if (getenv("TMP") != NULL)
- return getenv("TEMP");
- else
- return "/tmp";
-}
-
-int
-Win32System(const char *cmdline)
-{
- STARTUPINFO si;
- PROCESS_INFORMATION pi;
- DWORD dwExitCode;
- char *cmd = strdup(cmdline);
-
- ZeroMemory( &si, sizeof(si) );
- si.cb = sizeof(si);
- ZeroMemory( &pi, sizeof(pi) );
-
- if (!CreateProcess(NULL, cmd, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi))
- {
- LPVOID buffer;
- if (!FormatMessage(
- FORMAT_MESSAGE_ALLOCATE_BUFFER |
- FORMAT_MESSAGE_FROM_SYSTEM |
- FORMAT_MESSAGE_IGNORE_INSERTS,
- NULL,
- GetLastError(),
- MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
- (LPTSTR) &buffer,
- 0,
- NULL ))
- {
- ErrorF("[xkb] Starting '%s' failed!\n", cmdline);
- }
- else
- {
- ErrorF("[xkb] Starting '%s' failed: %s", cmdline, (char *)buffer);
- LocalFree(buffer);
- }
-
- free(cmd);
- return -1;
- }
- /* Wait until child process exits. */
- WaitForSingleObject( pi.hProcess, INFINITE );
-
- GetExitCodeProcess( pi.hProcess, &dwExitCode);
-
- /* Close process and thread handles. */
- CloseHandle( pi.hProcess );
- CloseHandle( pi.hThread );
- free(cmd);
-
- return dwExitCode;
-}
-#undef System
-#define System(x) Win32System(x)
-#endif
-
-static void
-OutputDirectory(
- char* outdir,
- size_t size)
-{
-#ifndef WIN32
- /* Can we write an xkm and then open it too? */
- if (access(XKM_OUTPUT_DIR, W_OK | X_OK) == 0 && (strlen(XKM_OUTPUT_DIR) < size))
- {
- (void) strcpy (outdir, XKM_OUTPUT_DIR);
- } else
-#else
- if (strlen(Win32TempDir()) + 1 < size)
- {
- (void) strcpy(outdir, Win32TempDir());
- (void) strcat(outdir, "\\");
- } else
-#endif
- if (strlen("/tmp/") < size)
- {
- (void) strcpy (outdir, "/tmp/");
- }
-}
-
-static Bool
-XkbDDXCompileKeymapByNames( XkbDescPtr xkb,
- XkbComponentNamesPtr names,
- unsigned want,
- unsigned need,
- char * nameRtrn,
- int nameRtrnLen)
-{
- FILE * out;
- char *buf = NULL, keymap[PATH_MAX], xkm_output_dir[PATH_MAX];
-
- const char *emptystring = "";
- char *xkbbasedirflag = NULL;
- const char *xkbbindir = emptystring;
- const char *xkbbindirsep = emptystring;
-
-#ifdef WIN32
- /* WIN32 has no popen. The input must be stored in a file which is
- used as input for xkbcomp. xkbcomp does not read from stdin. */
- char tmpname[PATH_MAX];
- const char *xkmfile = tmpname;
-#else
- const char *xkmfile = "-";
-#endif
-
- snprintf(keymap, sizeof(keymap), "server-%s", display);
-
- OutputDirectory(xkm_output_dir, sizeof(xkm_output_dir));
-
-#ifdef WIN32
- strcpy(tmpname, Win32TempDir());
- strcat(tmpname, "\\xkb_XXXXXX");
- (void) mktemp(tmpname);
-#endif
-
- if (XkbBaseDirectory != NULL) {
- if (asprintf(&xkbbasedirflag, "\"-R%s\"", XkbBaseDirectory) == -1)
- xkbbasedirflag = NULL;
- }
-
- if (XkbBinDirectory != NULL) {
- int ld = strlen(XkbBinDirectory);
- int lps = strlen(PATHSEPARATOR);
-
- xkbbindir = XkbBinDirectory;
-
- if ((ld >= lps) &&
- (strcmp(xkbbindir + ld - lps, PATHSEPARATOR) != 0)) {
- xkbbindirsep = PATHSEPARATOR;
- }
- }
-
- if (asprintf(&buf,
- "\"%s%sxkbcomp\" -w %d %s -xkm \"%s\" "
- "-em1 %s -emp %s -eml %s \"%s%s.xkm\"",
- xkbbindir, xkbbindirsep,
- ((xkbDebugFlags < 2) ? 1 :
- ((xkbDebugFlags > 10) ? 10 : (int) xkbDebugFlags)),
- xkbbasedirflag ? xkbbasedirflag : "", xkmfile,
- PRE_ERROR_MSG, ERROR_PREFIX, POST_ERROR_MSG1,
- xkm_output_dir, keymap) == -1)
- buf = NULL;
-
- free(xkbbasedirflag);
-
- if (!buf) {
- LogMessage(X_ERROR, "XKB: Could not invoke xkbcomp: not enough memory\n");
- return FALSE;
- }
-
-#ifndef WIN32
- out= Popen(buf,"w");
-#else
- out= fopen(tmpname, "w");
-#endif
-
- if (out!=NULL) {
-#ifdef DEBUG
- if (xkbDebugFlags) {
- ErrorF("[xkb] XkbDDXCompileKeymapByNames compiling keymap:\n");
- XkbWriteXKBKeymapForNames(stderr,names,xkb,want,need);
- }
-#endif
- XkbWriteXKBKeymapForNames(out,names,xkb,want,need);
-#ifndef WIN32
- if (Pclose(out)==0)
-#else
- if (fclose(out)==0 && System(buf) >= 0)
-#endif
- {
- if (xkbDebugFlags)
- DebugF("[xkb] xkb executes: %s\n",buf);
- if (nameRtrn) {
- strncpy(nameRtrn,keymap,nameRtrnLen);
- nameRtrn[nameRtrnLen-1]= '\0';
- }
- free(buf);
- return TRUE;
- }
- else
- LogMessage(X_ERROR, "Error compiling keymap (%s)\n", keymap);
-#ifdef WIN32
- /* remove the temporary file */
- unlink(tmpname);
-#endif
- }
- else {
-#ifndef WIN32
- LogMessage(X_ERROR, "XKB: Could not invoke xkbcomp\n");
-#else
- LogMessage(X_ERROR, "Could not open file %s\n", tmpname);
-#endif
- }
- if (nameRtrn)
- nameRtrn[0]= '\0';
- free(buf);
- return FALSE;
-}
-
-static FILE *
-XkbDDXOpenConfigFile(char *mapName,char *fileNameRtrn,int fileNameRtrnLen)
-{
-char buf[PATH_MAX],xkm_output_dir[PATH_MAX];
-FILE * file;
-
- buf[0]= '\0';
- if (mapName!=NULL) {
- OutputDirectory(xkm_output_dir, sizeof(xkm_output_dir));
- if ((XkbBaseDirectory!=NULL)&&(xkm_output_dir[0]!='/')
-#ifdef WIN32
- &&(!isalpha(xkm_output_dir[0]) || xkm_output_dir[1]!=':')
-#endif
- ) {
- if (strlen(XkbBaseDirectory)+strlen(xkm_output_dir)
- +strlen(mapName)+6 <= PATH_MAX)
- {
- sprintf(buf,"%s/%s%s.xkm",XkbBaseDirectory,
- xkm_output_dir,mapName);
- }
- }
- else if (strlen(xkm_output_dir)+strlen(mapName)+5 <= PATH_MAX)
- sprintf(buf,"%s%s.xkm",xkm_output_dir,mapName);
- if (buf[0] != '\0')
- file= fopen(buf,"rb");
- else file= NULL;
- }
- else file= NULL;
- if ((fileNameRtrn!=NULL)&&(fileNameRtrnLen>0)) {
- strncpy(fileNameRtrn,buf,fileNameRtrnLen);
- buf[fileNameRtrnLen-1]= '\0';
- }
- return file;
-}
-
-unsigned
-XkbDDXLoadKeymapByNames( DeviceIntPtr keybd,
- XkbComponentNamesPtr names,
- unsigned want,
- unsigned need,
- XkbDescPtr * xkbRtrn,
- char * nameRtrn,
- int nameRtrnLen)
-{
-XkbDescPtr xkb;
-FILE * file;
-char fileName[PATH_MAX];
-unsigned missing;
-
- *xkbRtrn = NULL;
- if ((keybd==NULL)||(keybd->key==NULL)||(keybd->key->xkbInfo==NULL))
- xkb= NULL;
- else xkb= keybd->key->xkbInfo->desc;
- if ((names->keycodes==NULL)&&(names->types==NULL)&&
- (names->compat==NULL)&&(names->symbols==NULL)&&
- (names->geometry==NULL)) {
- LogMessage(X_ERROR, "XKB: No components provided for device %s\n",
- keybd->name ? keybd->name : "(unnamed keyboard)");
- return 0;
- }
- else if (!XkbDDXCompileKeymapByNames(xkb,names,want,need,
- nameRtrn,nameRtrnLen)){
- LogMessage(X_ERROR, "XKB: Couldn't compile keymap\n");
- return 0;
- }
- file= XkbDDXOpenConfigFile(nameRtrn,fileName,PATH_MAX);
- if (file==NULL) {
- LogMessage(X_ERROR, "Couldn't open compiled keymap file %s\n",fileName);
- return 0;
- }
- missing= XkmReadFile(file,need,want,xkbRtrn);
- if (*xkbRtrn==NULL) {
- LogMessage(X_ERROR, "Error loading keymap %s\n",fileName);
- fclose(file);
- (void) unlink (fileName);
- return 0;
- }
- else {
- DebugF("Loaded XKB keymap %s, defined=0x%x\n",fileName,(*xkbRtrn)->defined);
- }
- fclose(file);
- (void) unlink (fileName);
- return (need|want)&(~missing);
-}
-
-Bool
-XkbDDXNamesFromRules( DeviceIntPtr keybd,
- char * rules_name,
- XkbRF_VarDefsPtr defs,
- XkbComponentNamesPtr names)
-{
-char buf[PATH_MAX];
-FILE * file;
-Bool complete;
-XkbRF_RulesPtr rules;
-
- if (!rules_name)
- return FALSE;
-
- if (strlen(XkbBaseDirectory) + strlen(rules_name) + 8 > PATH_MAX) {
- LogMessage(X_ERROR, "XKB: Rules name is too long\n");
- return FALSE;
- }
- sprintf(buf,"%s/rules/%s", XkbBaseDirectory, rules_name);
-
- file = fopen(buf, "r");
- if (!file) {
- LogMessage(X_ERROR, "XKB: Couldn't open rules file %s\n", buf);
- return FALSE;
- }
-
- rules = XkbRF_Create();
- if (!rules) {
- LogMessage(X_ERROR, "XKB: Couldn't create rules struct\n");
- fclose(file);
- return FALSE;
- }
-
- if (!XkbRF_LoadRules(file, rules)) {
- LogMessage(X_ERROR, "XKB: Couldn't parse rules file %s\n", rules_name);
- fclose(file);
- XkbRF_Free(rules,TRUE);
- return FALSE;
- }
-
- memset(names, 0, sizeof(*names));
- complete = XkbRF_GetComponents(rules,defs,names);
- fclose(file);
- XkbRF_Free(rules, TRUE);
-
- if (!complete)
- LogMessage(X_ERROR, "XKB: Rules returned no components\n");
-
- return complete;
-}
-
-static Bool
-XkbRMLVOtoKcCGST(DeviceIntPtr dev, XkbRMLVOSet *rmlvo, XkbComponentNamesPtr kccgst)
-{
- XkbRF_VarDefsRec mlvo;
-
- mlvo.model = rmlvo->model;
- mlvo.layout = rmlvo->layout;
- mlvo.variant = rmlvo->variant;
- mlvo.options = rmlvo->options;
-
- return XkbDDXNamesFromRules(dev, rmlvo->rules, &mlvo, kccgst);
-}
-
-/**
- * Compile the given RMLVO keymap and return it. Returns the XkbDescPtr on
- * success or NULL on failure. If the components compiled are not a superset
- * or equal to need, the compiliation is treated as failure.
- */
-static XkbDescPtr
-XkbCompileKeymapForDevice(DeviceIntPtr dev, XkbRMLVOSet *rmlvo, int need)
-{
- XkbDescPtr xkb;
- unsigned int provided;
- XkbComponentNamesRec kccgst;
- char name[PATH_MAX];
-
- if (!XkbRMLVOtoKcCGST(dev, rmlvo, &kccgst))
- return NULL;
-
- provided = XkbDDXLoadKeymapByNames(dev, &kccgst, XkmAllIndicesMask, need,
- &xkb, name, PATH_MAX);
- if ((need & provided) != need) {
- if (xkb) {
- XkbFreeKeyboard(xkb, 0, TRUE);
- xkb = NULL;
- }
- }
-
- return xkb;
-}
-
-XkbDescPtr
-XkbCompileKeymap(DeviceIntPtr dev, XkbRMLVOSet *rmlvo)
-{
- XkbDescPtr xkb;
- unsigned int need;
-
- if (!dev || !rmlvo) {
- LogMessage(X_ERROR, "XKB: No device or RMLVO specified\n");
- return NULL;
- }
-
- /* These are the components we really really need */
- need = XkmSymbolsMask | XkmCompatMapMask | XkmTypesMask |
- XkmKeyNamesMask | XkmVirtualModsMask;
-
-
- xkb = XkbCompileKeymapForDevice(dev, rmlvo, need);
-
- if (!xkb) {
- XkbRMLVOSet dflts;
-
- /* we didn't get what we really needed. And that will likely leave
- * us with a keyboard that doesn't work. Use the defaults instead */
- LogMessage(X_ERROR, "XKB: Failed to load keymap. Loading default "
- "keymap instead.\n");
-
- XkbGetRulesDflts(&dflts);
-
- xkb = XkbCompileKeymapForDevice(dev, &dflts, 0);
-
- XkbFreeRMLVOSet(&dflts, FALSE);
- }
-
- return xkb;
-}
+/************************************************************ +Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc. + +Permission 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 that both that copyright +notice and this permission notice appear in supporting +documentation, and that the name of Silicon Graphics not be +used in advertising or publicity pertaining to distribution +of the software without specific prior written permission. +Silicon Graphics makes no representation about the suitability +of this software for any purpose. It is provided "as is" +without any express or implied warranty. + +SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS +SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON +GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL +DAMAGES OR ANY 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 THIS SOFTWARE. + +********************************************************/ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include <xkb-config.h> + +#include <stdio.h> +#include <ctype.h> +#include <X11/X.h> +#include <X11/Xos.h> +#include <X11/Xproto.h> +#include <X11/keysym.h> +#include <X11/extensions/XKM.h> +#include "inputstr.h" +#include "scrnintstr.h" +#include "windowstr.h" +#define XKBSRV_NEED_FILE_FUNCS +#include <xkbsrv.h> +#include <X11/extensions/XI.h> +#include "xkb.h" + + /* + * If XKM_OUTPUT_DIR specifies a path without a leading slash, it is + * relative to the top-level XKB configuration directory. + * Making the server write to a subdirectory of that directory + * requires some work in the general case (install procedure + * has to create links to /var or somesuch on many machines), + * so we just compile into /usr/tmp for now. + */ +#ifndef XKM_OUTPUT_DIR +#define XKM_OUTPUT_DIR "compiled/" +#endif + +#define PRE_ERROR_MSG "\"The XKEYBOARD keymap compiler (xkbcomp) reports:\"" +#define ERROR_PREFIX "\"> \"" +#define POST_ERROR_MSG1 "\"Errors from xkbcomp are not fatal to the X server\"" +#define POST_ERROR_MSG2 "\"End of messages from xkbcomp\"" + +#if defined(WIN32) +#define PATHSEPARATOR "\\" +#else +#define PATHSEPARATOR "/" +#endif + +#ifdef WIN32 + +#include <X11/Xwindows.h> +const char* +Win32TempDir() +{ + static char buffer[PATH_MAX]; + if (GetTempPath(sizeof(buffer), buffer)) + { + int len; + buffer[sizeof(buffer)-1] = 0; + len = strlen(buffer); + if (len > 0) + if (buffer[len-1] == '\\') + buffer[len-1] = 0; + return buffer; + } + if (getenv("TEMP") != NULL) + return getenv("TEMP"); + else if (getenv("TMP") != NULL) + return getenv("TEMP"); + else + return "/tmp"; +} + +int +Win32System(const char *cmdline) +{ + STARTUPINFO si; + PROCESS_INFORMATION pi; + DWORD dwExitCode; + char *cmd = strdup(cmdline); + + ZeroMemory( &si, sizeof(si) ); + si.cb = sizeof(si); + ZeroMemory( &pi, sizeof(pi) ); + + if (!CreateProcess(NULL, cmd, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) + { + LPVOID buffer; + if (!FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + GetLastError(), + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPTSTR) &buffer, + 0, + NULL )) + { + ErrorF("[xkb] Starting '%s' failed!\n", cmdline); + } + else + { + ErrorF("[xkb] Starting '%s' failed: %s", cmdline, (char *)buffer); + LocalFree(buffer); + } + + free(cmd); + return -1; + } + /* Wait until child process exits. */ + WaitForSingleObject( pi.hProcess, INFINITE ); + + GetExitCodeProcess( pi.hProcess, &dwExitCode); + + /* Close process and thread handles. */ + CloseHandle( pi.hProcess ); + CloseHandle( pi.hThread ); + free(cmd); + + return dwExitCode; +} +#undef System +#define System(x) Win32System(x) +#endif + +static void +OutputDirectory( + char* outdir, + size_t size) +{ +#ifndef WIN32 + /* Can we write an xkm and then open it too? */ + if (access(XKM_OUTPUT_DIR, W_OK | X_OK) == 0 && (strlen(XKM_OUTPUT_DIR) < size)) + { + (void) strcpy (outdir, XKM_OUTPUT_DIR); + } else +#else + if (strlen(Win32TempDir()) + 1 < size) + { + (void) strcpy(outdir, Win32TempDir()); + (void) strcat(outdir, "\\"); + } else +#endif + if (strlen("/tmp/") < size) + { + (void) strcpy (outdir, "/tmp/"); + } +} + +static Bool +XkbDDXCompileKeymapByNames( XkbDescPtr xkb, + XkbComponentNamesPtr names, + unsigned want, + unsigned need, + char * nameRtrn, + int nameRtrnLen) +{ + FILE * out; + char *buf = NULL, keymap[PATH_MAX], xkm_output_dir[PATH_MAX]; + + const char *emptystring = ""; + char *xkbbasedirflag = NULL; + const char *xkbbindir = emptystring; + const char *xkbbindirsep = emptystring; + +#ifdef WIN32 + /* WIN32 has no popen. The input must be stored in a file which is + used as input for xkbcomp. xkbcomp does not read from stdin. */ + char tmpname[PATH_MAX]; + const char *xkmfile = tmpname; +#else + const char *xkmfile = "-"; +#endif + + snprintf(keymap, sizeof(keymap), "server-%s", display); + + OutputDirectory(xkm_output_dir, sizeof(xkm_output_dir)); + +#ifdef WIN32 + strcpy(tmpname, Win32TempDir()); + strcat(tmpname, "\\xkb_XXXXXX"); + (void) mktemp(tmpname); +#endif + + if (XkbBaseDirectory != NULL) { + if (asprintf(&xkbbasedirflag, "\"-R%s\"", XkbBaseDirectory) == -1) + xkbbasedirflag = NULL; + } + + if (XkbBinDirectory != NULL) { + int ld = strlen(XkbBinDirectory); + int lps = strlen(PATHSEPARATOR); + + xkbbindir = XkbBinDirectory; + + if ((ld >= lps) && + (strcmp(xkbbindir + ld - lps, PATHSEPARATOR) != 0)) { + xkbbindirsep = PATHSEPARATOR; + } + } + + if (asprintf(&buf, + "\"%s%sxkbcomp\" -w %d %s -xkm \"%s\" " + "-em1 %s -emp %s -eml %s \"%s%s.xkm\"", + xkbbindir, xkbbindirsep, + ((xkbDebugFlags < 2) ? 1 : + ((xkbDebugFlags > 10) ? 10 : (int) xkbDebugFlags)), + xkbbasedirflag ? xkbbasedirflag : "", xkmfile, + PRE_ERROR_MSG, ERROR_PREFIX, POST_ERROR_MSG1, + xkm_output_dir, keymap) == -1) + buf = NULL; + + free(xkbbasedirflag); + + if (!buf) { + LogMessage(X_ERROR, "XKB: Could not invoke xkbcomp: not enough memory\n"); + return FALSE; + } + +#ifndef WIN32 + out= Popen(buf,"w"); +#else + out= fopen(tmpname, "w"); +#endif + + if (out!=NULL) { +#ifdef DEBUG + if (xkbDebugFlags) { + ErrorF("[xkb] XkbDDXCompileKeymapByNames compiling keymap:\n"); + XkbWriteXKBKeymapForNames(stderr,names,xkb,want,need); + } +#endif + XkbWriteXKBKeymapForNames(out,names,xkb,want,need); +#ifndef WIN32 + if (Pclose(out)==0) +#else + if (fclose(out)==0 && System(buf) >= 0) +#endif + { + if (xkbDebugFlags) + DebugF("[xkb] xkb executes: %s\n",buf); + if (nameRtrn) { + strncpy(nameRtrn,keymap,nameRtrnLen); + nameRtrn[nameRtrnLen-1]= '\0'; + } + free(buf); + return TRUE; + } + else + LogMessage(X_ERROR, "Error compiling keymap (%s)\n", keymap); +#ifdef WIN32 + /* remove the temporary file */ + unlink(tmpname); +#endif + } + else { +#ifndef WIN32 + LogMessage(X_ERROR, "XKB: Could not invoke xkbcomp\n"); +#else + LogMessage(X_ERROR, "Could not open file %s\n", tmpname); +#endif + } + if (nameRtrn) + nameRtrn[0]= '\0'; + free(buf); + return FALSE; +} + +static FILE * +XkbDDXOpenConfigFile(char *mapName,char *fileNameRtrn,int fileNameRtrnLen) +{ +char buf[PATH_MAX],xkm_output_dir[PATH_MAX]; +FILE * file; + + buf[0]= '\0'; + if (mapName!=NULL) { + OutputDirectory(xkm_output_dir, sizeof(xkm_output_dir)); + if ((XkbBaseDirectory!=NULL)&&(xkm_output_dir[0]!='/') +#ifdef WIN32 + &&(!isalpha(xkm_output_dir[0]) || xkm_output_dir[1]!=':') +#endif + ) { + if (snprintf(buf, PATH_MAX, "%s/%s%s.xkm", XkbBaseDirectory, + xkm_output_dir, mapName) >= PATH_MAX) + buf[0] = '\0'; + } + else + { + if (snprintf(buf, PATH_MAX, "%s%s.xkm", xkm_output_dir, mapName) + >= PATH_MAX) + buf[0] = '\0'; + } + if (buf[0] != '\0') + file= fopen(buf,"rb"); + else file= NULL; + } + else file= NULL; + if ((fileNameRtrn!=NULL)&&(fileNameRtrnLen>0)) { + strncpy(fileNameRtrn,buf,fileNameRtrnLen); + buf[fileNameRtrnLen-1]= '\0'; + } + return file; +} + +unsigned +XkbDDXLoadKeymapByNames( DeviceIntPtr keybd, + XkbComponentNamesPtr names, + unsigned want, + unsigned need, + XkbDescPtr * xkbRtrn, + char * nameRtrn, + int nameRtrnLen) +{ +XkbDescPtr xkb; +FILE * file; +char fileName[PATH_MAX]; +unsigned missing; + + *xkbRtrn = NULL; + if ((keybd==NULL)||(keybd->key==NULL)||(keybd->key->xkbInfo==NULL)) + xkb= NULL; + else xkb= keybd->key->xkbInfo->desc; + if ((names->keycodes==NULL)&&(names->types==NULL)&& + (names->compat==NULL)&&(names->symbols==NULL)&& + (names->geometry==NULL)) { + LogMessage(X_ERROR, "XKB: No components provided for device %s\n", + keybd->name ? keybd->name : "(unnamed keyboard)"); + return 0; + } + else if (!XkbDDXCompileKeymapByNames(xkb,names,want,need, + nameRtrn,nameRtrnLen)){ + LogMessage(X_ERROR, "XKB: Couldn't compile keymap\n"); + return 0; + } + file= XkbDDXOpenConfigFile(nameRtrn,fileName,PATH_MAX); + if (file==NULL) { + LogMessage(X_ERROR, "Couldn't open compiled keymap file %s\n",fileName); + return 0; + } + missing= XkmReadFile(file,need,want,xkbRtrn); + if (*xkbRtrn==NULL) { + LogMessage(X_ERROR, "Error loading keymap %s\n",fileName); + fclose(file); + (void) unlink (fileName); + return 0; + } + else { + DebugF("Loaded XKB keymap %s, defined=0x%x\n",fileName,(*xkbRtrn)->defined); + } + fclose(file); + (void) unlink (fileName); + return (need|want)&(~missing); +} + +Bool +XkbDDXNamesFromRules( DeviceIntPtr keybd, + char * rules_name, + XkbRF_VarDefsPtr defs, + XkbComponentNamesPtr names) +{ +char buf[PATH_MAX]; +FILE * file; +Bool complete; +XkbRF_RulesPtr rules; + + if (!rules_name) + return FALSE; + + if (snprintf(buf, PATH_MAX, "%s/rules/%s", XkbBaseDirectory, rules_name) + >= PATH_MAX) { + LogMessage(X_ERROR, "XKB: Rules name is too long\n"); + return FALSE; + } + + file = fopen(buf, "r"); + if (!file) { + LogMessage(X_ERROR, "XKB: Couldn't open rules file %s\n", buf); + return FALSE; + } + + rules = XkbRF_Create(); + if (!rules) { + LogMessage(X_ERROR, "XKB: Couldn't create rules struct\n"); + fclose(file); + return FALSE; + } + + if (!XkbRF_LoadRules(file, rules)) { + LogMessage(X_ERROR, "XKB: Couldn't parse rules file %s\n", rules_name); + fclose(file); + XkbRF_Free(rules,TRUE); + return FALSE; + } + + memset(names, 0, sizeof(*names)); + complete = XkbRF_GetComponents(rules,defs,names); + fclose(file); + XkbRF_Free(rules, TRUE); + + if (!complete) + LogMessage(X_ERROR, "XKB: Rules returned no components\n"); + + return complete; +} + +static Bool +XkbRMLVOtoKcCGST(DeviceIntPtr dev, XkbRMLVOSet *rmlvo, XkbComponentNamesPtr kccgst) +{ + XkbRF_VarDefsRec mlvo; + + mlvo.model = rmlvo->model; + mlvo.layout = rmlvo->layout; + mlvo.variant = rmlvo->variant; + mlvo.options = rmlvo->options; + + return XkbDDXNamesFromRules(dev, rmlvo->rules, &mlvo, kccgst); +} + +/** + * Compile the given RMLVO keymap and return it. Returns the XkbDescPtr on + * success or NULL on failure. If the components compiled are not a superset + * or equal to need, the compiliation is treated as failure. + */ +static XkbDescPtr +XkbCompileKeymapForDevice(DeviceIntPtr dev, XkbRMLVOSet *rmlvo, int need) +{ + XkbDescPtr xkb; + unsigned int provided; + XkbComponentNamesRec kccgst; + char name[PATH_MAX]; + + if (!XkbRMLVOtoKcCGST(dev, rmlvo, &kccgst)) + return NULL; + + provided = XkbDDXLoadKeymapByNames(dev, &kccgst, XkmAllIndicesMask, need, + &xkb, name, PATH_MAX); + if ((need & provided) != need) { + if (xkb) { + XkbFreeKeyboard(xkb, 0, TRUE); + xkb = NULL; + } + } + + return xkb; +} + +XkbDescPtr +XkbCompileKeymap(DeviceIntPtr dev, XkbRMLVOSet *rmlvo) +{ + XkbDescPtr xkb; + unsigned int need; + + if (!dev || !rmlvo) { + LogMessage(X_ERROR, "XKB: No device or RMLVO specified\n"); + return NULL; + } + + /* These are the components we really really need */ + need = XkmSymbolsMask | XkmCompatMapMask | XkmTypesMask | + XkmKeyNamesMask | XkmVirtualModsMask; + + + xkb = XkbCompileKeymapForDevice(dev, rmlvo, need); + + if (!xkb) { + XkbRMLVOSet dflts; + + /* we didn't get what we really needed. And that will likely leave + * us with a keyboard that doesn't work. Use the defaults instead */ + LogMessage(X_ERROR, "XKB: Failed to load keymap. Loading default " + "keymap instead.\n"); + + XkbGetRulesDflts(&dflts); + + xkb = XkbCompileKeymapForDevice(dev, &dflts, 0); + + XkbFreeRMLVOSet(&dflts, FALSE); + } + + return xkb; +} diff --git a/xorg-server/xkb/maprules.c b/xorg-server/xkb/maprules.c index 2a118ae6a..f94089982 100644 --- a/xorg-server/xkb/maprules.c +++ b/xorg-server/xkb/maprules.c @@ -1,1019 +1,1018 @@ -/************************************************************
- Copyright (c) 1996 by Silicon Graphics Computer Systems, Inc.
-
- Permission 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 that both that copyright
- notice and this permission notice appear in supporting
- documentation, and that the name of Silicon Graphics not be
- used in advertising or publicity pertaining to distribution
- of the software without specific prior written permission.
- Silicon Graphics makes no representation about the suitability
- of this software for any purpose. It is provided "as is"
- without any express or implied warranty.
-
- SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
- SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
- AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
- GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
- DAMAGES OR ANY 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 THIS SOFTWARE.
-
- ********************************************************/
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#include <stdio.h>
-#include <ctype.h>
-#include <stdlib.h>
-
-#define X_INCLUDE_STRING_H
-#define XOS_USE_NO_LOCKING
-#include <X11/Xos_r.h>
-
-#include <X11/Xproto.h>
-#include <X11/X.h>
-#include <X11/Xos.h>
-#include <X11/Xfuncs.h>
-#include <X11/Xatom.h>
-#include <X11/keysym.h>
-#include "misc.h"
-#include "inputstr.h"
-#include "dix.h"
-#include "os.h"
-#include "xkbstr.h"
-#define XKBSRV_NEED_FILE_FUNCS
-#include <xkbsrv.h>
-
-/***====================================================================***/
-
-
-
-#define DFLT_LINE_SIZE 128
-
-typedef struct {
- int line_num;
- int sz_line;
- int num_line;
- char buf[DFLT_LINE_SIZE];
- char * line;
-} InputLine;
-
-static void
-InitInputLine(InputLine *line)
-{
- line->line_num= 1;
- line->num_line= 0;
- line->sz_line= DFLT_LINE_SIZE;
- line->line= line->buf;
- return;
-}
-
-static void
-FreeInputLine(InputLine *line)
-{
- if (line->line!=line->buf)
- free(line->line);
- line->line_num= 1;
- line->num_line= 0;
- line->sz_line= DFLT_LINE_SIZE;
- line->line= line->buf;
- return;
-}
-
-static int
-InputLineAddChar(InputLine *line,int ch)
-{
- if (line->num_line>=line->sz_line) {
- if (line->line==line->buf) {
- line->line= malloc(line->sz_line*2);
- memcpy(line->line,line->buf,line->sz_line);
- }
- else {
- line->line= realloc((char *)line->line,line->sz_line*2);
- }
- line->sz_line*= 2;
- }
- line->line[line->num_line++]= ch;
- return ch;
-}
-
-#define ADD_CHAR(l,c) ((l)->num_line<(l)->sz_line?\
- (int)((l)->line[(l)->num_line++]= (c)):\
- InputLineAddChar(l,c))
-
-static Bool
-GetInputLine(FILE *file,InputLine *line,Bool checkbang)
-{
-int ch;
-Bool endOfFile,spacePending,slashPending,inComment;
-
- endOfFile= FALSE;
- while ((!endOfFile)&&(line->num_line==0)) {
- spacePending= slashPending= inComment= FALSE;
- while (((ch=getc(file))!='\n')&&(ch!=EOF)) {
- if (ch=='\\') {
- if ((ch=getc(file))==EOF)
- break;
- if (ch=='\n') {
- inComment= FALSE;
- ch= ' ';
- line->line_num++;
- }
- }
- if (inComment)
- continue;
- if (ch=='/') {
- if (slashPending) {
- inComment= TRUE;
- slashPending= FALSE;
- }
- else {
- slashPending= TRUE;
- }
- continue;
- }
- else if (slashPending) {
- if (spacePending) {
- ADD_CHAR(line,' ');
- spacePending= FALSE;
- }
- ADD_CHAR(line,'/');
- slashPending= FALSE;
- }
- if (isspace(ch)) {
- while (isspace(ch)&&(ch!='\n')&&(ch!=EOF)) {
- ch= getc(file);
- }
- if (ch==EOF)
- break;
- if ((ch!='\n')&&(line->num_line>0))
- spacePending= TRUE;
- ungetc(ch,file);
- }
- else {
- if (spacePending) {
- ADD_CHAR(line,' ');
- spacePending= FALSE;
- }
- if (checkbang && ch=='!') {
- if (line->num_line!=0) {
- DebugF("The '!' legal only at start of line\n");
- DebugF("Line containing '!' ignored\n");
- line->num_line= 0;
- inComment= 0;
- break;
- }
-
- }
- ADD_CHAR(line,ch);
- }
- }
- if (ch==EOF)
- endOfFile= TRUE;
-/* else line->num_line++;*/
- }
- if ((line->num_line==0)&&(endOfFile))
- return FALSE;
- ADD_CHAR(line,'\0');
- return TRUE;
-}
-
-/***====================================================================***/
-
-#define MODEL 0
-#define LAYOUT 1
-#define VARIANT 2
-#define OPTION 3
-#define KEYCODES 4
-#define SYMBOLS 5
-#define TYPES 6
-#define COMPAT 7
-#define GEOMETRY 8
-#define MAX_WORDS 9
-
-#define PART_MASK 0x000F
-#define COMPONENT_MASK 0x03F0
-
-static char * cname[MAX_WORDS] = {
- "model", "layout", "variant", "option",
- "keycodes", "symbols", "types", "compat", "geometry"
-};
-
-typedef struct _RemapSpec {
- int number;
- int num_remap;
- struct {
- int word;
- int index;
- } remap[MAX_WORDS];
-} RemapSpec;
-
-typedef struct _FileSpec {
- char * name[MAX_WORDS];
- struct _FileSpec * pending;
-} FileSpec;
-
-typedef struct {
- char * model;
- char * layout[XkbNumKbdGroups+1];
- char * variant[XkbNumKbdGroups+1];
- char * options;
-} XkbRF_MultiDefsRec, *XkbRF_MultiDefsPtr;
-
-#define NDX_BUFF_SIZE 4
-
-/***====================================================================***/
-
-static char*
-get_index(char *str, int *ndx)
-{
- char ndx_buf[NDX_BUFF_SIZE];
- char *end;
-
- if (*str != '[') {
- *ndx = 0;
- return str;
- }
- str++;
- end = strchr(str, ']');
- if (end == NULL) {
- *ndx = -1;
- return str - 1;
- }
- if ( (end - str) >= NDX_BUFF_SIZE) {
- *ndx = -1;
- return end + 1;
- }
- strncpy(ndx_buf, str, end - str);
- ndx_buf[end - str] = '\0';
- *ndx = atoi(ndx_buf);
- return end + 1;
-}
-
-static void
-SetUpRemap(InputLine *line,RemapSpec *remap)
-{
-char * tok,*str;
-unsigned present, l_ndx_present, v_ndx_present;
-register int i;
-int len, ndx;
-_Xstrtokparams strtok_buf;
-Bool found;
-
-
- l_ndx_present = v_ndx_present = present= 0;
- str= &line->line[1];
- len = remap->number;
- memset((char *)remap, 0, sizeof(RemapSpec));
- remap->number = len;
- while ((tok=_XStrtok(str," ",strtok_buf))!=NULL) {
- found= FALSE;
- str= NULL;
- if (strcmp(tok,"=")==0)
- continue;
- for (i=0;i<MAX_WORDS;i++) {
- len = strlen(cname[i]);
- if (strncmp(cname[i],tok,len)==0) {
- if(strlen(tok) > len) {
- char *end = get_index(tok+len, &ndx);
- if ((i != LAYOUT && i != VARIANT) ||
- *end != '\0' || ndx == -1)
- break;
- if (ndx < 1 || ndx > XkbNumKbdGroups) {
- DebugF("Illegal %s index: %d\n", cname[i], ndx);
- DebugF("Index must be in range 1..%d\n",
- XkbNumKbdGroups);
- break;
- }
- } else {
- ndx = 0;
- }
- found= TRUE;
- if (present&(1<<i)) {
- if ((i == LAYOUT && l_ndx_present&(1<<ndx)) ||
- (i == VARIANT && v_ndx_present&(1<<ndx)) ) {
- DebugF("Component \"%s\" listed twice\n",tok);
- DebugF("Second definition ignored\n");
- break;
- }
- }
- present |= (1<<i);
- if (i == LAYOUT)
- l_ndx_present |= 1 << ndx;
- if (i == VARIANT)
- v_ndx_present |= 1 << ndx;
- remap->remap[remap->num_remap].word= i;
- remap->remap[remap->num_remap++].index= ndx;
- break;
- }
- }
- if (!found) {
- fprintf(stderr,"Unknown component \"%s\" ignored\n",tok);
- }
- }
- if ((present&PART_MASK)==0) {
- unsigned mask= PART_MASK;
- ErrorF("Mapping needs at least one of ");
- for (i=0; (i<MAX_WORDS); i++) {
- if ((1L<<i)&mask) {
- mask&= ~(1L<<i);
- if (mask) DebugF("\"%s,\" ",cname[i]);
- else DebugF("or \"%s\"\n",cname[i]);
- }
- }
- DebugF("Illegal mapping ignored\n");
- remap->num_remap= 0;
- return;
- }
- if ((present&COMPONENT_MASK)==0) {
- DebugF("Mapping needs at least one component\n");
- DebugF("Illegal mapping ignored\n");
- remap->num_remap= 0;
- return;
- }
- remap->number++;
- return;
-}
-
-static Bool
-MatchOneOf(char *wanted,char *vals_defined)
-{
-char *str,*next;
-int want_len= strlen(wanted);
-
- for (str=vals_defined,next=NULL;str!=NULL;str=next) {
- int len;
- next= strchr(str,',');
- if (next) {
- len= next-str;
- next++;
- }
- else {
- len= strlen(str);
- }
- if ((len==want_len)&&(strncmp(wanted,str,len)==0))
- return TRUE;
- }
- return FALSE;
-}
-
-/***====================================================================***/
-
-static Bool
-CheckLine( InputLine * line,
- RemapSpec * remap,
- XkbRF_RulePtr rule,
- XkbRF_GroupPtr group)
-{
-char * str,*tok;
-register int nread, i;
-FileSpec tmp;
-_Xstrtokparams strtok_buf;
-Bool append = FALSE;
-
- if (line->line[0]=='!') {
- if (line->line[1] == '$' ||
- (line->line[1] == ' ' && line->line[2] == '$')) {
- char *gname = strchr(line->line, '$');
- char *words = strchr(gname, ' ');
- if(!words)
- return FALSE;
- *words++ = '\0';
- for (; *words; words++) {
- if (*words != '=' && *words != ' ')
- break;
- }
- if (*words == '\0')
- return FALSE;
- group->name = _XkbDupString(gname);
- group->words = _XkbDupString(words);
- for (i = 1, words = group->words; *words; words++) {
- if ( *words == ' ') {
- *words++ = '\0';
- i++;
- }
- }
- group->number = i;
- return TRUE;
- } else {
- SetUpRemap(line,remap);
- return FALSE;
- }
- }
-
- if (remap->num_remap==0) {
- DebugF("Must have a mapping before first line of data\n");
- DebugF("Illegal line of data ignored\n");
- return FALSE;
- }
- memset((char *)&tmp, 0, sizeof(FileSpec));
- str= line->line;
- for (nread= 0;(tok=_XStrtok(str," ",strtok_buf))!=NULL;nread++) {
- str= NULL;
- if (strcmp(tok,"=")==0) {
- nread--;
- continue;
- }
- if (nread>remap->num_remap) {
- DebugF("Too many words on a line\n");
- DebugF("Extra word \"%s\" ignored\n",tok);
- continue;
- }
- tmp.name[remap->remap[nread].word]= tok;
- if (*tok == '+' || *tok == '|')
- append = TRUE;
- }
- if (nread<remap->num_remap) {
- DebugF("Too few words on a line: %s\n", line->line);
- DebugF("line ignored\n");
- return FALSE;
- }
-
- rule->flags= 0;
- rule->number = remap->number;
- if (tmp.name[OPTION])
- rule->flags|= XkbRF_Option;
- else if (append)
- rule->flags|= XkbRF_Append;
- else
- rule->flags|= XkbRF_Normal;
- rule->model= _XkbDupString(tmp.name[MODEL]);
- rule->layout= _XkbDupString(tmp.name[LAYOUT]);
- rule->variant= _XkbDupString(tmp.name[VARIANT]);
- rule->option= _XkbDupString(tmp.name[OPTION]);
-
- rule->keycodes= _XkbDupString(tmp.name[KEYCODES]);
- rule->symbols= _XkbDupString(tmp.name[SYMBOLS]);
- rule->types= _XkbDupString(tmp.name[TYPES]);
- rule->compat= _XkbDupString(tmp.name[COMPAT]);
- rule->geometry= _XkbDupString(tmp.name[GEOMETRY]);
-
- rule->layout_num = rule->variant_num = 0;
- for (i = 0; i < nread; i++) {
- if (remap->remap[i].index) {
- if (remap->remap[i].word == LAYOUT)
- rule->layout_num = remap->remap[i].index;
- if (remap->remap[i].word == VARIANT)
- rule->variant_num = remap->remap[i].index;
- }
- }
- return TRUE;
-}
-
-static char *
-_Concat(char *str1,char *str2)
-{
-int len;
-
- if ((!str1)||(!str2))
- return str1;
- len= strlen(str1)+strlen(str2)+1;
- str1= realloc(str1,len * sizeof(char));
- if (str1)
- strcat(str1,str2);
- return str1;
-}
-
-static void
-squeeze_spaces(char *p1)
-{
- char *p2;
- for (p2 = p1; *p2; p2++) {
- *p1 = *p2;
- if (*p1 != ' ') p1++;
- }
- *p1 = '\0';
-}
-
-static Bool
-MakeMultiDefs(XkbRF_MultiDefsPtr mdefs, XkbRF_VarDefsPtr defs)
-{
-
- memset((char *)mdefs, 0, sizeof(XkbRF_MultiDefsRec));
- mdefs->model = defs->model;
- mdefs->options = _XkbDupString(defs->options);
- if (mdefs->options) squeeze_spaces(mdefs->options);
-
- if (defs->layout) {
- if (!strchr(defs->layout, ',')) {
- mdefs->layout[0] = defs->layout;
- } else {
- char *p;
- int i;
- mdefs->layout[1] = _XkbDupString(defs->layout);
- if (mdefs->layout[1] == NULL)
- return FALSE;
- squeeze_spaces(mdefs->layout[1]);
- p = mdefs->layout[1];
- for (i = 2; i <= XkbNumKbdGroups; i++) {
- if ((p = strchr(p, ','))) {
- *p++ = '\0';
- mdefs->layout[i] = p;
- } else {
- break;
- }
- }
- if (p && (p = strchr(p, ',')))
- *p = '\0';
- }
- }
-
- if (defs->variant) {
- if (!strchr(defs->variant, ',')) {
- mdefs->variant[0] = defs->variant;
- } else {
- char *p;
- int i;
- mdefs->variant[1] = _XkbDupString(defs->variant);
- if (mdefs->variant[1] == NULL)
- return FALSE;
- squeeze_spaces(mdefs->variant[1]);
- p = mdefs->variant[1];
- for (i = 2; i <= XkbNumKbdGroups; i++) {
- if ((p = strchr(p, ','))) {
- *p++ = '\0';
- mdefs->variant[i] = p;
- } else {
- break;
- }
- }
- if (p && (p = strchr(p, ',')))
- *p = '\0';
- }
- }
- return TRUE;
-}
-
-static void
-FreeMultiDefs(XkbRF_MultiDefsPtr defs)
-{
- free(defs->options);
- free(defs->layout[1]);
- free(defs->variant[1]);
-}
-
-static void
-Apply(char *src, char **dst)
-{
- if (src) {
- if (*src == '+' || *src == '!') {
- *dst= _Concat(*dst, src);
- } else {
- if (*dst == NULL)
- *dst= _XkbDupString(src);
- }
- }
-}
-
-static void
-XkbRF_ApplyRule( XkbRF_RulePtr rule,
- XkbComponentNamesPtr names)
-{
- rule->flags&= ~XkbRF_PendingMatch; /* clear the flag because it's applied */
-
- Apply(rule->keycodes, &names->keycodes);
- Apply(rule->symbols, &names->symbols);
- Apply(rule->types, &names->types);
- Apply(rule->compat, &names->compat);
- Apply(rule->geometry, &names->geometry);
-}
-
-static Bool
-CheckGroup( XkbRF_RulesPtr rules,
- char * group_name,
- char * name)
-{
- int i;
- char *p;
- XkbRF_GroupPtr group;
-
- for (i = 0, group = rules->groups; i < rules->num_groups; i++, group++) {
- if (! strcmp(group->name, group_name)) {
- break;
- }
- }
- if (i == rules->num_groups)
- return FALSE;
- for (i = 0, p = group->words; i < group->number; i++, p += strlen(p)+1) {
- if (! strcmp(p, name)) {
- return TRUE;
- }
- }
- return FALSE;
-}
-
-static int
-XkbRF_CheckApplyRule( XkbRF_RulePtr rule,
- XkbRF_MultiDefsPtr mdefs,
- XkbComponentNamesPtr names,
- XkbRF_RulesPtr rules)
-{
- Bool pending = FALSE;
-
- if (rule->model != NULL) {
- if(mdefs->model == NULL)
- return 0;
- if (strcmp(rule->model, "*") == 0) {
- pending = TRUE;
- } else {
- if (rule->model[0] == '$') {
- if (!CheckGroup(rules, rule->model, mdefs->model))
- return 0;
- } else {
- if (strcmp(rule->model, mdefs->model) != 0)
- return 0;
- }
- }
- }
- if (rule->option != NULL) {
- if (mdefs->options == NULL)
- return 0;
- if ((!MatchOneOf(rule->option,mdefs->options)))
- return 0;
- }
-
- if (rule->layout != NULL) {
- if(mdefs->layout[rule->layout_num] == NULL ||
- *mdefs->layout[rule->layout_num] == '\0')
- return 0;
- if (strcmp(rule->layout, "*") == 0) {
- pending = TRUE;
- } else {
- if (rule->layout[0] == '$') {
- if (!CheckGroup(rules, rule->layout,
- mdefs->layout[rule->layout_num]))
- return 0;
- } else {
- if (strcmp(rule->layout, mdefs->layout[rule->layout_num]) != 0)
- return 0;
- }
- }
- }
- if (rule->variant != NULL) {
- if (mdefs->variant[rule->variant_num] == NULL ||
- *mdefs->variant[rule->variant_num] == '\0')
- return 0;
- if (strcmp(rule->variant, "*") == 0) {
- pending = TRUE;
- } else {
- if (rule->variant[0] == '$') {
- if (!CheckGroup(rules, rule->variant,
- mdefs->variant[rule->variant_num]))
- return 0;
- } else {
- if (strcmp(rule->variant,
- mdefs->variant[rule->variant_num]) != 0)
- return 0;
- }
- }
- }
- if (pending) {
- rule->flags|= XkbRF_PendingMatch;
- return rule->number;
- }
- /* exact match, apply it now */
- XkbRF_ApplyRule(rule,names);
- return rule->number;
-}
-
-static void
-XkbRF_ClearPartialMatches(XkbRF_RulesPtr rules)
-{
-register int i;
-XkbRF_RulePtr rule;
-
- for (i=0,rule=rules->rules;i<rules->num_rules;i++,rule++) {
- rule->flags&= ~XkbRF_PendingMatch;
- }
-}
-
-static void
-XkbRF_ApplyPartialMatches(XkbRF_RulesPtr rules,XkbComponentNamesPtr names)
-{
-int i;
-XkbRF_RulePtr rule;
-
- for (rule = rules->rules, i = 0; i < rules->num_rules; i++, rule++) {
- if ((rule->flags&XkbRF_PendingMatch)==0)
- continue;
- XkbRF_ApplyRule(rule,names);
- }
-}
-
-static void
-XkbRF_CheckApplyRules( XkbRF_RulesPtr rules,
- XkbRF_MultiDefsPtr mdefs,
- XkbComponentNamesPtr names,
- int flags)
-{
-int i;
-XkbRF_RulePtr rule;
-int skip;
-
- for (rule = rules->rules, i=0; i < rules->num_rules; rule++, i++) {
- if ((rule->flags & flags) != flags)
- continue;
- skip = XkbRF_CheckApplyRule(rule, mdefs, names, rules);
- if (skip && !(flags & XkbRF_Option)) {
- for ( ;(i < rules->num_rules) && (rule->number == skip);
- rule++, i++);
- rule--; i--;
- }
- }
-}
-
-/***====================================================================***/
-
-static char *
-XkbRF_SubstituteVars(char *name, XkbRF_MultiDefsPtr mdefs)
-{
-char *str, *outstr, *orig, *var;
-int len, ndx;
-
- orig= name;
- str= index(name,'%');
- if (str==NULL)
- return name;
- len= strlen(name);
- while (str!=NULL) {
- char pfx= str[1];
- int extra_len= 0;
- if ((pfx=='+')||(pfx=='|')||(pfx=='_')||(pfx=='-')) {
- extra_len= 1;
- str++;
- }
- else if (pfx=='(') {
- extra_len= 2;
- str++;
- }
- var = str + 1;
- str = get_index(var + 1, &ndx);
- if (ndx == -1) {
- str = index(str,'%');
- continue;
- }
- if ((*var=='l') && mdefs->layout[ndx] && *mdefs->layout[ndx])
- len+= strlen(mdefs->layout[ndx])+extra_len;
- else if ((*var=='m')&&mdefs->model)
- len+= strlen(mdefs->model)+extra_len;
- else if ((*var=='v') && mdefs->variant[ndx] && *mdefs->variant[ndx])
- len+= strlen(mdefs->variant[ndx])+extra_len;
- if ((pfx=='(')&&(*str==')')) {
- str++;
- }
- str= index(&str[0],'%');
- }
- name= malloc(len+1);
- str= orig;
- outstr= name;
- while (*str!='\0') {
- if (str[0]=='%') {
- char pfx,sfx;
- str++;
- pfx= str[0];
- sfx= '\0';
- if ((pfx=='+')||(pfx=='|')||(pfx=='_')||(pfx=='-')) {
- str++;
- }
- else if (pfx=='(') {
- sfx= ')';
- str++;
- }
- else pfx= '\0';
-
- var = str;
- str = get_index(var + 1, &ndx);
- if (ndx == -1) {
- continue;
- }
- if ((*var=='l') && mdefs->layout[ndx] && *mdefs->layout[ndx]) {
- if (pfx) *outstr++= pfx;
- strcpy(outstr,mdefs->layout[ndx]);
- outstr+= strlen(mdefs->layout[ndx]);
- if (sfx) *outstr++= sfx;
- }
- else if ((*var=='m')&&(mdefs->model)) {
- if (pfx) *outstr++= pfx;
- strcpy(outstr,mdefs->model);
- outstr+= strlen(mdefs->model);
- if (sfx) *outstr++= sfx;
- }
- else if ((*var=='v') && mdefs->variant[ndx] && *mdefs->variant[ndx]) {
- if (pfx) *outstr++= pfx;
- strcpy(outstr,mdefs->variant[ndx]);
- outstr+= strlen(mdefs->variant[ndx]);
- if (sfx) *outstr++= sfx;
- }
- if ((pfx=='(')&&(*str==')'))
- str++;
- }
- else {
- *outstr++= *str++;
- }
- }
- *outstr++= '\0';
- if (orig!=name)
- free(orig);
- return name;
-}
-
-/***====================================================================***/
-
-Bool
-XkbRF_GetComponents( XkbRF_RulesPtr rules,
- XkbRF_VarDefsPtr defs,
- XkbComponentNamesPtr names)
-{
- XkbRF_MultiDefsRec mdefs;
-
- MakeMultiDefs(&mdefs, defs);
-
- memset((char *)names, 0, sizeof(XkbComponentNamesRec));
- XkbRF_ClearPartialMatches(rules);
- XkbRF_CheckApplyRules(rules, &mdefs, names, XkbRF_Normal);
- XkbRF_ApplyPartialMatches(rules, names);
- XkbRF_CheckApplyRules(rules, &mdefs, names, XkbRF_Append);
- XkbRF_ApplyPartialMatches(rules, names);
- XkbRF_CheckApplyRules(rules, &mdefs, names, XkbRF_Option);
-
- if (names->keycodes)
- names->keycodes= XkbRF_SubstituteVars(names->keycodes, &mdefs);
- if (names->symbols)
- names->symbols= XkbRF_SubstituteVars(names->symbols, &mdefs);
- if (names->types)
- names->types= XkbRF_SubstituteVars(names->types, &mdefs);
- if (names->compat)
- names->compat= XkbRF_SubstituteVars(names->compat, &mdefs);
- if (names->geometry)
- names->geometry= XkbRF_SubstituteVars(names->geometry, &mdefs);
-
- FreeMultiDefs(&mdefs);
- return (names->keycodes && names->symbols && names->types &&
- names->compat && names->geometry);
-}
-
-static XkbRF_RulePtr
-XkbRF_AddRule(XkbRF_RulesPtr rules)
-{
- if (rules->sz_rules<1) {
- rules->sz_rules= 16;
- rules->num_rules= 0;
- rules->rules= calloc(rules->sz_rules, sizeof(XkbRF_RuleRec));
- }
- else if (rules->num_rules>=rules->sz_rules) {
- rules->sz_rules*= 2;
- rules->rules= realloc(rules->rules,
- rules->sz_rules * sizeof(XkbRF_RuleRec));
- }
- if (!rules->rules) {
- rules->sz_rules= rules->num_rules= 0;
- DebugF("Allocation failure in XkbRF_AddRule\n");
- return NULL;
- }
- memset((char *)&rules->rules[rules->num_rules], 0, sizeof(XkbRF_RuleRec));
- return &rules->rules[rules->num_rules++];
-}
-
-static XkbRF_GroupPtr
-XkbRF_AddGroup(XkbRF_RulesPtr rules)
-{
- if (rules->sz_groups<1) {
- rules->sz_groups= 16;
- rules->num_groups= 0;
- rules->groups= calloc(rules->sz_groups, sizeof(XkbRF_GroupRec));
- }
- else if (rules->num_groups >= rules->sz_groups) {
- rules->sz_groups *= 2;
- rules->groups= realloc(rules->groups,
- rules->sz_groups * sizeof(XkbRF_GroupRec));
- }
- if (!rules->groups) {
- rules->sz_groups= rules->num_groups= 0;
- return NULL;
- }
-
- memset((char *)&rules->groups[rules->num_groups], 0, sizeof(XkbRF_GroupRec));
- return &rules->groups[rules->num_groups++];
-}
-
-Bool
-XkbRF_LoadRules(FILE *file, XkbRF_RulesPtr rules)
-{
-InputLine line;
-RemapSpec remap;
-XkbRF_RuleRec trule,*rule;
-XkbRF_GroupRec tgroup,*group;
-
- if (!(rules && file))
- return FALSE;
- memset((char *)&remap, 0, sizeof(RemapSpec));
- memset((char *)&tgroup, 0, sizeof(XkbRF_GroupRec));
- InitInputLine(&line);
- while (GetInputLine(file,&line,TRUE)) {
- if (CheckLine(&line,&remap,&trule,&tgroup)) {
- if (tgroup.number) {
- if ((group= XkbRF_AddGroup(rules))!=NULL) {
- *group= tgroup;
- memset((char *)&tgroup, 0, sizeof(XkbRF_GroupRec));
- }
- } else {
- if ((rule= XkbRF_AddRule(rules))!=NULL) {
- *rule= trule;
- memset((char *)&trule, 0, sizeof(XkbRF_RuleRec));
- }
- }
- }
- line.num_line= 0;
- }
- FreeInputLine(&line);
- return TRUE;
-}
-
-Bool
-XkbRF_LoadRulesByName(char *base,char *locale,XkbRF_RulesPtr rules)
-{
-FILE * file;
-char buf[PATH_MAX];
-Bool ok;
-
- if ((!base)||(!rules))
- return FALSE;
- if (locale) {
- if (strlen(base)+strlen(locale)+2 > PATH_MAX)
- return FALSE;
- sprintf(buf,"%s-%s", base, locale);
- }
- else {
- if (strlen(base)+1 > PATH_MAX)
- return FALSE;
- strcpy(buf,base);
- }
-
- file= fopen(buf, "r");
- if ((!file)&&(locale)) { /* fallback if locale was specified */
- strcpy(buf,base);
- file= fopen(buf, "r");
- }
- if (!file)
- return FALSE;
- ok= XkbRF_LoadRules(file,rules);
- fclose(file);
- return ok;
-}
-
-/***====================================================================***/
-
-XkbRF_RulesPtr
-XkbRF_Create(void)
-{
- return calloc(1, sizeof( XkbRF_RulesRec));
-}
-
-/***====================================================================***/
-
-void
-XkbRF_Free(XkbRF_RulesPtr rules,Bool freeRules)
-{
-int i;
-XkbRF_RulePtr rule;
-XkbRF_GroupPtr group;
-
- if (!rules)
- return;
- if (rules->rules) {
- for (i=0,rule=rules->rules;i<rules->num_rules;i++,rule++) {
- free(rule->model);
- free(rule->layout);
- free(rule->variant);
- free(rule->option);
- free(rule->keycodes);
- free(rule->symbols);
- free(rule->types);
- free(rule->compat);
- free(rule->geometry);
- memset((char *)rule, 0, sizeof(XkbRF_RuleRec));
- }
- free(rules->rules);
- rules->num_rules= rules->sz_rules= 0;
- rules->rules= NULL;
- }
-
- if (rules->groups) {
- for (i=0, group=rules->groups;i<rules->num_groups;i++,group++) {
- free(group->name);
- free(group->words);
- }
- free(rules->groups);
- rules->num_groups= 0;
- rules->groups= NULL;
- }
- if (freeRules)
- free(rules);
- return;
-}
+/************************************************************ + Copyright (c) 1996 by Silicon Graphics Computer Systems, Inc. + + Permission 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 that both that copyright + notice and this permission notice appear in supporting + documentation, and that the name of Silicon Graphics not be + used in advertising or publicity pertaining to distribution + of the software without specific prior written permission. + Silicon Graphics makes no representation about the suitability + of this software for any purpose. It is provided "as is" + without any express or implied warranty. + + SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS + SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON + GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL + DAMAGES OR ANY 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 THIS SOFTWARE. + + ********************************************************/ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include <stdio.h> +#include <ctype.h> +#include <stdlib.h> + +#define X_INCLUDE_STRING_H +#define XOS_USE_NO_LOCKING +#include <X11/Xos_r.h> + +#include <X11/Xproto.h> +#include <X11/X.h> +#include <X11/Xos.h> +#include <X11/Xfuncs.h> +#include <X11/Xatom.h> +#include <X11/keysym.h> +#include "misc.h" +#include "inputstr.h" +#include "dix.h" +#include "os.h" +#include "xkbstr.h" +#define XKBSRV_NEED_FILE_FUNCS +#include <xkbsrv.h> + +/***====================================================================***/ + + + +#define DFLT_LINE_SIZE 128 + +typedef struct { + int line_num; + int sz_line; + int num_line; + char buf[DFLT_LINE_SIZE]; + char * line; +} InputLine; + +static void +InitInputLine(InputLine *line) +{ + line->line_num= 1; + line->num_line= 0; + line->sz_line= DFLT_LINE_SIZE; + line->line= line->buf; + return; +} + +static void +FreeInputLine(InputLine *line) +{ + if (line->line!=line->buf) + free(line->line); + line->line_num= 1; + line->num_line= 0; + line->sz_line= DFLT_LINE_SIZE; + line->line= line->buf; + return; +} + +static int +InputLineAddChar(InputLine *line,int ch) +{ + if (line->num_line>=line->sz_line) { + if (line->line==line->buf) { + line->line= malloc(line->sz_line*2); + memcpy(line->line,line->buf,line->sz_line); + } + else { + line->line= realloc((char *)line->line,line->sz_line*2); + } + line->sz_line*= 2; + } + line->line[line->num_line++]= ch; + return ch; +} + +#define ADD_CHAR(l,c) ((l)->num_line<(l)->sz_line?\ + (int)((l)->line[(l)->num_line++]= (c)):\ + InputLineAddChar(l,c)) + +static Bool +GetInputLine(FILE *file,InputLine *line,Bool checkbang) +{ +int ch; +Bool endOfFile,spacePending,slashPending,inComment; + + endOfFile= FALSE; + while ((!endOfFile)&&(line->num_line==0)) { + spacePending= slashPending= inComment= FALSE; + while (((ch=getc(file))!='\n')&&(ch!=EOF)) { + if (ch=='\\') { + if ((ch=getc(file))==EOF) + break; + if (ch=='\n') { + inComment= FALSE; + ch= ' '; + line->line_num++; + } + } + if (inComment) + continue; + if (ch=='/') { + if (slashPending) { + inComment= TRUE; + slashPending= FALSE; + } + else { + slashPending= TRUE; + } + continue; + } + else if (slashPending) { + if (spacePending) { + ADD_CHAR(line,' '); + spacePending= FALSE; + } + ADD_CHAR(line,'/'); + slashPending= FALSE; + } + if (isspace(ch)) { + while (isspace(ch)&&(ch!='\n')&&(ch!=EOF)) { + ch= getc(file); + } + if (ch==EOF) + break; + if ((ch!='\n')&&(line->num_line>0)) + spacePending= TRUE; + ungetc(ch,file); + } + else { + if (spacePending) { + ADD_CHAR(line,' '); + spacePending= FALSE; + } + if (checkbang && ch=='!') { + if (line->num_line!=0) { + DebugF("The '!' legal only at start of line\n"); + DebugF("Line containing '!' ignored\n"); + line->num_line= 0; + inComment= 0; + break; + } + + } + ADD_CHAR(line,ch); + } + } + if (ch==EOF) + endOfFile= TRUE; +/* else line->num_line++;*/ + } + if ((line->num_line==0)&&(endOfFile)) + return FALSE; + ADD_CHAR(line,'\0'); + return TRUE; +} + +/***====================================================================***/ + +#define MODEL 0 +#define LAYOUT 1 +#define VARIANT 2 +#define OPTION 3 +#define KEYCODES 4 +#define SYMBOLS 5 +#define TYPES 6 +#define COMPAT 7 +#define GEOMETRY 8 +#define MAX_WORDS 9 + +#define PART_MASK 0x000F +#define COMPONENT_MASK 0x03F0 + +static char * cname[MAX_WORDS] = { + "model", "layout", "variant", "option", + "keycodes", "symbols", "types", "compat", "geometry" +}; + +typedef struct _RemapSpec { + int number; + int num_remap; + struct { + int word; + int index; + } remap[MAX_WORDS]; +} RemapSpec; + +typedef struct _FileSpec { + char * name[MAX_WORDS]; + struct _FileSpec * pending; +} FileSpec; + +typedef struct { + char * model; + char * layout[XkbNumKbdGroups+1]; + char * variant[XkbNumKbdGroups+1]; + char * options; +} XkbRF_MultiDefsRec, *XkbRF_MultiDefsPtr; + +#define NDX_BUFF_SIZE 4 + +/***====================================================================***/ + +static char* +get_index(char *str, int *ndx) +{ + char ndx_buf[NDX_BUFF_SIZE]; + char *end; + + if (*str != '[') { + *ndx = 0; + return str; + } + str++; + end = strchr(str, ']'); + if (end == NULL) { + *ndx = -1; + return str - 1; + } + if ( (end - str) >= NDX_BUFF_SIZE) { + *ndx = -1; + return end + 1; + } + strncpy(ndx_buf, str, end - str); + ndx_buf[end - str] = '\0'; + *ndx = atoi(ndx_buf); + return end + 1; +} + +static void +SetUpRemap(InputLine *line,RemapSpec *remap) +{ +char * tok,*str; +unsigned present, l_ndx_present, v_ndx_present; +register int i; +int len, ndx; +_Xstrtokparams strtok_buf; +Bool found; + + + l_ndx_present = v_ndx_present = present= 0; + str= &line->line[1]; + len = remap->number; + memset((char *)remap, 0, sizeof(RemapSpec)); + remap->number = len; + while ((tok=_XStrtok(str," ",strtok_buf))!=NULL) { + found= FALSE; + str= NULL; + if (strcmp(tok,"=")==0) + continue; + for (i=0;i<MAX_WORDS;i++) { + len = strlen(cname[i]); + if (strncmp(cname[i],tok,len)==0) { + if(strlen(tok) > len) { + char *end = get_index(tok+len, &ndx); + if ((i != LAYOUT && i != VARIANT) || + *end != '\0' || ndx == -1) + break; + if (ndx < 1 || ndx > XkbNumKbdGroups) { + DebugF("Illegal %s index: %d\n", cname[i], ndx); + DebugF("Index must be in range 1..%d\n", + XkbNumKbdGroups); + break; + } + } else { + ndx = 0; + } + found= TRUE; + if (present&(1<<i)) { + if ((i == LAYOUT && l_ndx_present&(1<<ndx)) || + (i == VARIANT && v_ndx_present&(1<<ndx)) ) { + DebugF("Component \"%s\" listed twice\n",tok); + DebugF("Second definition ignored\n"); + break; + } + } + present |= (1<<i); + if (i == LAYOUT) + l_ndx_present |= 1 << ndx; + if (i == VARIANT) + v_ndx_present |= 1 << ndx; + remap->remap[remap->num_remap].word= i; + remap->remap[remap->num_remap++].index= ndx; + break; + } + } + if (!found) { + fprintf(stderr,"Unknown component \"%s\" ignored\n",tok); + } + } + if ((present&PART_MASK)==0) { + unsigned mask= PART_MASK; + ErrorF("Mapping needs at least one of "); + for (i=0; (i<MAX_WORDS); i++) { + if ((1L<<i)&mask) { + mask&= ~(1L<<i); + if (mask) DebugF("\"%s,\" ",cname[i]); + else DebugF("or \"%s\"\n",cname[i]); + } + } + DebugF("Illegal mapping ignored\n"); + remap->num_remap= 0; + return; + } + if ((present&COMPONENT_MASK)==0) { + DebugF("Mapping needs at least one component\n"); + DebugF("Illegal mapping ignored\n"); + remap->num_remap= 0; + return; + } + remap->number++; + return; +} + +static Bool +MatchOneOf(char *wanted,char *vals_defined) +{ +char *str,*next; +int want_len= strlen(wanted); + + for (str=vals_defined,next=NULL;str!=NULL;str=next) { + int len; + next= strchr(str,','); + if (next) { + len= next-str; + next++; + } + else { + len= strlen(str); + } + if ((len==want_len)&&(strncmp(wanted,str,len)==0)) + return TRUE; + } + return FALSE; +} + +/***====================================================================***/ + +static Bool +CheckLine( InputLine * line, + RemapSpec * remap, + XkbRF_RulePtr rule, + XkbRF_GroupPtr group) +{ +char * str,*tok; +register int nread, i; +FileSpec tmp; +_Xstrtokparams strtok_buf; +Bool append = FALSE; + + if (line->line[0]=='!') { + if (line->line[1] == '$' || + (line->line[1] == ' ' && line->line[2] == '$')) { + char *gname = strchr(line->line, '$'); + char *words = strchr(gname, ' '); + if(!words) + return FALSE; + *words++ = '\0'; + for (; *words; words++) { + if (*words != '=' && *words != ' ') + break; + } + if (*words == '\0') + return FALSE; + group->name = Xstrdup(gname); + group->words = Xstrdup(words); + for (i = 1, words = group->words; *words; words++) { + if ( *words == ' ') { + *words++ = '\0'; + i++; + } + } + group->number = i; + return TRUE; + } else { + SetUpRemap(line,remap); + return FALSE; + } + } + + if (remap->num_remap==0) { + DebugF("Must have a mapping before first line of data\n"); + DebugF("Illegal line of data ignored\n"); + return FALSE; + } + memset((char *)&tmp, 0, sizeof(FileSpec)); + str= line->line; + for (nread= 0;(tok=_XStrtok(str," ",strtok_buf))!=NULL;nread++) { + str= NULL; + if (strcmp(tok,"=")==0) { + nread--; + continue; + } + if (nread>remap->num_remap) { + DebugF("Too many words on a line\n"); + DebugF("Extra word \"%s\" ignored\n",tok); + continue; + } + tmp.name[remap->remap[nread].word]= tok; + if (*tok == '+' || *tok == '|') + append = TRUE; + } + if (nread<remap->num_remap) { + DebugF("Too few words on a line: %s\n", line->line); + DebugF("line ignored\n"); + return FALSE; + } + + rule->flags= 0; + rule->number = remap->number; + if (tmp.name[OPTION]) + rule->flags|= XkbRF_Option; + else if (append) + rule->flags|= XkbRF_Append; + else + rule->flags|= XkbRF_Normal; + rule->model= Xstrdup(tmp.name[MODEL]); + rule->layout= Xstrdup(tmp.name[LAYOUT]); + rule->variant= Xstrdup(tmp.name[VARIANT]); + rule->option= Xstrdup(tmp.name[OPTION]); + + rule->keycodes= Xstrdup(tmp.name[KEYCODES]); + rule->symbols= Xstrdup(tmp.name[SYMBOLS]); + rule->types= Xstrdup(tmp.name[TYPES]); + rule->compat= Xstrdup(tmp.name[COMPAT]); + rule->geometry= Xstrdup(tmp.name[GEOMETRY]); + + rule->layout_num = rule->variant_num = 0; + for (i = 0; i < nread; i++) { + if (remap->remap[i].index) { + if (remap->remap[i].word == LAYOUT) + rule->layout_num = remap->remap[i].index; + if (remap->remap[i].word == VARIANT) + rule->variant_num = remap->remap[i].index; + } + } + return TRUE; +} + +static char * +_Concat(char *str1,char *str2) +{ +int len; + + if ((!str1)||(!str2)) + return str1; + len= strlen(str1)+strlen(str2)+1; + str1= realloc(str1,len * sizeof(char)); + if (str1) + strcat(str1,str2); + return str1; +} + +static void +squeeze_spaces(char *p1) +{ + char *p2; + for (p2 = p1; *p2; p2++) { + *p1 = *p2; + if (*p1 != ' ') p1++; + } + *p1 = '\0'; +} + +static Bool +MakeMultiDefs(XkbRF_MultiDefsPtr mdefs, XkbRF_VarDefsPtr defs) +{ + + memset((char *)mdefs, 0, sizeof(XkbRF_MultiDefsRec)); + mdefs->model = defs->model; + mdefs->options = Xstrdup(defs->options); + if (mdefs->options) squeeze_spaces(mdefs->options); + + if (defs->layout) { + if (!strchr(defs->layout, ',')) { + mdefs->layout[0] = defs->layout; + } else { + char *p; + int i; + mdefs->layout[1] = Xstrdup(defs->layout); + if (mdefs->layout[1] == NULL) + return FALSE; + squeeze_spaces(mdefs->layout[1]); + p = mdefs->layout[1]; + for (i = 2; i <= XkbNumKbdGroups; i++) { + if ((p = strchr(p, ','))) { + *p++ = '\0'; + mdefs->layout[i] = p; + } else { + break; + } + } + if (p && (p = strchr(p, ','))) + *p = '\0'; + } + } + + if (defs->variant) { + if (!strchr(defs->variant, ',')) { + mdefs->variant[0] = defs->variant; + } else { + char *p; + int i; + mdefs->variant[1] = Xstrdup(defs->variant); + if (mdefs->variant[1] == NULL) + return FALSE; + squeeze_spaces(mdefs->variant[1]); + p = mdefs->variant[1]; + for (i = 2; i <= XkbNumKbdGroups; i++) { + if ((p = strchr(p, ','))) { + *p++ = '\0'; + mdefs->variant[i] = p; + } else { + break; + } + } + if (p && (p = strchr(p, ','))) + *p = '\0'; + } + } + return TRUE; +} + +static void +FreeMultiDefs(XkbRF_MultiDefsPtr defs) +{ + free(defs->options); + free(defs->layout[1]); + free(defs->variant[1]); +} + +static void +Apply(char *src, char **dst) +{ + if (src) { + if (*src == '+' || *src == '!') { + *dst= _Concat(*dst, src); + } else { + if (*dst == NULL) + *dst= Xstrdup(src); + } + } +} + +static void +XkbRF_ApplyRule( XkbRF_RulePtr rule, + XkbComponentNamesPtr names) +{ + rule->flags&= ~XkbRF_PendingMatch; /* clear the flag because it's applied */ + + Apply(rule->keycodes, &names->keycodes); + Apply(rule->symbols, &names->symbols); + Apply(rule->types, &names->types); + Apply(rule->compat, &names->compat); + Apply(rule->geometry, &names->geometry); +} + +static Bool +CheckGroup( XkbRF_RulesPtr rules, + char * group_name, + char * name) +{ + int i; + char *p; + XkbRF_GroupPtr group; + + for (i = 0, group = rules->groups; i < rules->num_groups; i++, group++) { + if (! strcmp(group->name, group_name)) { + break; + } + } + if (i == rules->num_groups) + return FALSE; + for (i = 0, p = group->words; i < group->number; i++, p += strlen(p)+1) { + if (! strcmp(p, name)) { + return TRUE; + } + } + return FALSE; +} + +static int +XkbRF_CheckApplyRule( XkbRF_RulePtr rule, + XkbRF_MultiDefsPtr mdefs, + XkbComponentNamesPtr names, + XkbRF_RulesPtr rules) +{ + Bool pending = FALSE; + + if (rule->model != NULL) { + if(mdefs->model == NULL) + return 0; + if (strcmp(rule->model, "*") == 0) { + pending = TRUE; + } else { + if (rule->model[0] == '$') { + if (!CheckGroup(rules, rule->model, mdefs->model)) + return 0; + } else { + if (strcmp(rule->model, mdefs->model) != 0) + return 0; + } + } + } + if (rule->option != NULL) { + if (mdefs->options == NULL) + return 0; + if ((!MatchOneOf(rule->option,mdefs->options))) + return 0; + } + + if (rule->layout != NULL) { + if(mdefs->layout[rule->layout_num] == NULL || + *mdefs->layout[rule->layout_num] == '\0') + return 0; + if (strcmp(rule->layout, "*") == 0) { + pending = TRUE; + } else { + if (rule->layout[0] == '$') { + if (!CheckGroup(rules, rule->layout, + mdefs->layout[rule->layout_num])) + return 0; + } else { + if (strcmp(rule->layout, mdefs->layout[rule->layout_num]) != 0) + return 0; + } + } + } + if (rule->variant != NULL) { + if (mdefs->variant[rule->variant_num] == NULL || + *mdefs->variant[rule->variant_num] == '\0') + return 0; + if (strcmp(rule->variant, "*") == 0) { + pending = TRUE; + } else { + if (rule->variant[0] == '$') { + if (!CheckGroup(rules, rule->variant, + mdefs->variant[rule->variant_num])) + return 0; + } else { + if (strcmp(rule->variant, + mdefs->variant[rule->variant_num]) != 0) + return 0; + } + } + } + if (pending) { + rule->flags|= XkbRF_PendingMatch; + return rule->number; + } + /* exact match, apply it now */ + XkbRF_ApplyRule(rule,names); + return rule->number; +} + +static void +XkbRF_ClearPartialMatches(XkbRF_RulesPtr rules) +{ +register int i; +XkbRF_RulePtr rule; + + for (i=0,rule=rules->rules;i<rules->num_rules;i++,rule++) { + rule->flags&= ~XkbRF_PendingMatch; + } +} + +static void +XkbRF_ApplyPartialMatches(XkbRF_RulesPtr rules,XkbComponentNamesPtr names) +{ +int i; +XkbRF_RulePtr rule; + + for (rule = rules->rules, i = 0; i < rules->num_rules; i++, rule++) { + if ((rule->flags&XkbRF_PendingMatch)==0) + continue; + XkbRF_ApplyRule(rule,names); + } +} + +static void +XkbRF_CheckApplyRules( XkbRF_RulesPtr rules, + XkbRF_MultiDefsPtr mdefs, + XkbComponentNamesPtr names, + int flags) +{ +int i; +XkbRF_RulePtr rule; +int skip; + + for (rule = rules->rules, i=0; i < rules->num_rules; rule++, i++) { + if ((rule->flags & flags) != flags) + continue; + skip = XkbRF_CheckApplyRule(rule, mdefs, names, rules); + if (skip && !(flags & XkbRF_Option)) { + for ( ;(i < rules->num_rules) && (rule->number == skip); + rule++, i++); + rule--; i--; + } + } +} + +/***====================================================================***/ + +static char * +XkbRF_SubstituteVars(char *name, XkbRF_MultiDefsPtr mdefs) +{ +char *str, *outstr, *orig, *var; +int len, ndx; + + orig= name; + str= index(name,'%'); + if (str==NULL) + return name; + len= strlen(name); + while (str!=NULL) { + char pfx= str[1]; + int extra_len= 0; + if ((pfx=='+')||(pfx=='|')||(pfx=='_')||(pfx=='-')) { + extra_len= 1; + str++; + } + else if (pfx=='(') { + extra_len= 2; + str++; + } + var = str + 1; + str = get_index(var + 1, &ndx); + if (ndx == -1) { + str = index(str,'%'); + continue; + } + if ((*var=='l') && mdefs->layout[ndx] && *mdefs->layout[ndx]) + len+= strlen(mdefs->layout[ndx])+extra_len; + else if ((*var=='m')&&mdefs->model) + len+= strlen(mdefs->model)+extra_len; + else if ((*var=='v') && mdefs->variant[ndx] && *mdefs->variant[ndx]) + len+= strlen(mdefs->variant[ndx])+extra_len; + if ((pfx=='(')&&(*str==')')) { + str++; + } + str= index(&str[0],'%'); + } + name= malloc(len+1); + str= orig; + outstr= name; + while (*str!='\0') { + if (str[0]=='%') { + char pfx,sfx; + str++; + pfx= str[0]; + sfx= '\0'; + if ((pfx=='+')||(pfx=='|')||(pfx=='_')||(pfx=='-')) { + str++; + } + else if (pfx=='(') { + sfx= ')'; + str++; + } + else pfx= '\0'; + + var = str; + str = get_index(var + 1, &ndx); + if (ndx == -1) { + continue; + } + if ((*var=='l') && mdefs->layout[ndx] && *mdefs->layout[ndx]) { + if (pfx) *outstr++= pfx; + strcpy(outstr,mdefs->layout[ndx]); + outstr+= strlen(mdefs->layout[ndx]); + if (sfx) *outstr++= sfx; + } + else if ((*var=='m')&&(mdefs->model)) { + if (pfx) *outstr++= pfx; + strcpy(outstr,mdefs->model); + outstr+= strlen(mdefs->model); + if (sfx) *outstr++= sfx; + } + else if ((*var=='v') && mdefs->variant[ndx] && *mdefs->variant[ndx]) { + if (pfx) *outstr++= pfx; + strcpy(outstr,mdefs->variant[ndx]); + outstr+= strlen(mdefs->variant[ndx]); + if (sfx) *outstr++= sfx; + } + if ((pfx=='(')&&(*str==')')) + str++; + } + else { + *outstr++= *str++; + } + } + *outstr++= '\0'; + if (orig!=name) + free(orig); + return name; +} + +/***====================================================================***/ + +Bool +XkbRF_GetComponents( XkbRF_RulesPtr rules, + XkbRF_VarDefsPtr defs, + XkbComponentNamesPtr names) +{ + XkbRF_MultiDefsRec mdefs; + + MakeMultiDefs(&mdefs, defs); + + memset((char *)names, 0, sizeof(XkbComponentNamesRec)); + XkbRF_ClearPartialMatches(rules); + XkbRF_CheckApplyRules(rules, &mdefs, names, XkbRF_Normal); + XkbRF_ApplyPartialMatches(rules, names); + XkbRF_CheckApplyRules(rules, &mdefs, names, XkbRF_Append); + XkbRF_ApplyPartialMatches(rules, names); + XkbRF_CheckApplyRules(rules, &mdefs, names, XkbRF_Option); + + if (names->keycodes) + names->keycodes= XkbRF_SubstituteVars(names->keycodes, &mdefs); + if (names->symbols) + names->symbols= XkbRF_SubstituteVars(names->symbols, &mdefs); + if (names->types) + names->types= XkbRF_SubstituteVars(names->types, &mdefs); + if (names->compat) + names->compat= XkbRF_SubstituteVars(names->compat, &mdefs); + if (names->geometry) + names->geometry= XkbRF_SubstituteVars(names->geometry, &mdefs); + + FreeMultiDefs(&mdefs); + return (names->keycodes && names->symbols && names->types && + names->compat && names->geometry); +} + +static XkbRF_RulePtr +XkbRF_AddRule(XkbRF_RulesPtr rules) +{ + if (rules->sz_rules<1) { + rules->sz_rules= 16; + rules->num_rules= 0; + rules->rules= calloc(rules->sz_rules, sizeof(XkbRF_RuleRec)); + } + else if (rules->num_rules>=rules->sz_rules) { + rules->sz_rules*= 2; + rules->rules= realloc(rules->rules, + rules->sz_rules * sizeof(XkbRF_RuleRec)); + } + if (!rules->rules) { + rules->sz_rules= rules->num_rules= 0; + DebugF("Allocation failure in XkbRF_AddRule\n"); + return NULL; + } + memset((char *)&rules->rules[rules->num_rules], 0, sizeof(XkbRF_RuleRec)); + return &rules->rules[rules->num_rules++]; +} + +static XkbRF_GroupPtr +XkbRF_AddGroup(XkbRF_RulesPtr rules) +{ + if (rules->sz_groups<1) { + rules->sz_groups= 16; + rules->num_groups= 0; + rules->groups= calloc(rules->sz_groups, sizeof(XkbRF_GroupRec)); + } + else if (rules->num_groups >= rules->sz_groups) { + rules->sz_groups *= 2; + rules->groups= realloc(rules->groups, + rules->sz_groups * sizeof(XkbRF_GroupRec)); + } + if (!rules->groups) { + rules->sz_groups= rules->num_groups= 0; + return NULL; + } + + memset((char *)&rules->groups[rules->num_groups], 0, sizeof(XkbRF_GroupRec)); + return &rules->groups[rules->num_groups++]; +} + +Bool +XkbRF_LoadRules(FILE *file, XkbRF_RulesPtr rules) +{ +InputLine line; +RemapSpec remap; +XkbRF_RuleRec trule,*rule; +XkbRF_GroupRec tgroup,*group; + + if (!(rules && file)) + return FALSE; + memset((char *)&remap, 0, sizeof(RemapSpec)); + memset((char *)&tgroup, 0, sizeof(XkbRF_GroupRec)); + InitInputLine(&line); + while (GetInputLine(file,&line,TRUE)) { + if (CheckLine(&line,&remap,&trule,&tgroup)) { + if (tgroup.number) { + if ((group= XkbRF_AddGroup(rules))!=NULL) { + *group= tgroup; + memset((char *)&tgroup, 0, sizeof(XkbRF_GroupRec)); + } + } else { + if ((rule= XkbRF_AddRule(rules))!=NULL) { + *rule= trule; + memset((char *)&trule, 0, sizeof(XkbRF_RuleRec)); + } + } + } + line.num_line= 0; + } + FreeInputLine(&line); + return TRUE; +} + +Bool +XkbRF_LoadRulesByName(char *base,char *locale,XkbRF_RulesPtr rules) +{ +FILE * file; +char buf[PATH_MAX]; +Bool ok; + + if ((!base)||(!rules)) + return FALSE; + if (locale) { + if (snprintf(buf, PATH_MAX, "%s-%s", base, locale) >= PATH_MAX) + return FALSE; + } + else { + if (strlen(base)+1 > PATH_MAX) + return FALSE; + strcpy(buf,base); + } + + file= fopen(buf, "r"); + if ((!file)&&(locale)) { /* fallback if locale was specified */ + strcpy(buf,base); + file= fopen(buf, "r"); + } + if (!file) + return FALSE; + ok= XkbRF_LoadRules(file,rules); + fclose(file); + return ok; +} + +/***====================================================================***/ + +XkbRF_RulesPtr +XkbRF_Create(void) +{ + return calloc(1, sizeof( XkbRF_RulesRec)); +} + +/***====================================================================***/ + +void +XkbRF_Free(XkbRF_RulesPtr rules,Bool freeRules) +{ +int i; +XkbRF_RulePtr rule; +XkbRF_GroupPtr group; + + if (!rules) + return; + if (rules->rules) { + for (i=0,rule=rules->rules;i<rules->num_rules;i++,rule++) { + free(rule->model); + free(rule->layout); + free(rule->variant); + free(rule->option); + free(rule->keycodes); + free(rule->symbols); + free(rule->types); + free(rule->compat); + free(rule->geometry); + memset((char *)rule, 0, sizeof(XkbRF_RuleRec)); + } + free(rules->rules); + rules->num_rules= rules->sz_rules= 0; + rules->rules= NULL; + } + + if (rules->groups) { + for (i=0, group=rules->groups;i<rules->num_groups;i++,group++) { + free(group->name); + free(group->words); + } + free(rules->groups); + rules->num_groups= 0; + rules->groups= NULL; + } + if (freeRules) + free(rules); + return; +} diff --git a/xorg-server/xkb/xkb.c b/xorg-server/xkb/xkb.c index 385c38d7d..d701ea13c 100644 --- a/xorg-server/xkb/xkb.c +++ b/xorg-server/xkb/xkb.c @@ -1,6740 +1,6738 @@ -/************************************************************
-Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc.
-
-Permission 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 that both that copyright
-notice and this permission notice appear in supporting
-documentation, and that the name of Silicon Graphics not be
-used in advertising or publicity pertaining to distribution
-of the software without specific prior written permission.
-Silicon Graphics makes no representation about the suitability
-of this software for any purpose. It is provided "as is"
-without any express or implied warranty.
-
-SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
-SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
-AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
-GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
-DAMAGES OR ANY 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 THIS SOFTWARE.
-
-********************************************************/
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#include <stdio.h>
-#include <X11/X.h>
-#include <X11/Xproto.h>
-#include "misc.h"
-#include "inputstr.h"
-#define XKBSRV_NEED_FILE_FUNCS
-#include <xkbsrv.h>
-#include "extnsionst.h"
-#include "xace.h"
-#include "xkb.h"
-#include "protocol-versions.h"
-
-#include <X11/extensions/XI.h>
-#include <X11/extensions/XKMformat.h>
-
-int XkbEventBase;
-static int XkbErrorBase;
-int XkbReqCode;
-int XkbKeyboardErrorCode;
-CARD32 xkbDebugFlags = 0;
-static CARD32 xkbDebugCtrls = 0;
-
-static RESTYPE RT_XKBCLIENT;
-
-/***====================================================================***/
-
-#define CHK_DEVICE(dev, id, client, access_mode, lf) {\
- int why;\
- int rc = lf(&(dev), id, client, access_mode, &why);\
- if (rc != Success) {\
- client->errorValue = _XkbErrCode2(why, id);\
- return rc;\
- }\
-}
-
-#define CHK_KBD_DEVICE(dev, id, client, mode) \
- CHK_DEVICE(dev, id, client, mode, _XkbLookupKeyboard)
-#define CHK_LED_DEVICE(dev, id, client, mode) \
- CHK_DEVICE(dev, id, client, mode, _XkbLookupLedDevice)
-#define CHK_BELL_DEVICE(dev, id, client, mode) \
- CHK_DEVICE(dev, id, client, mode, _XkbLookupBellDevice)
-#define CHK_ANY_DEVICE(dev, id, client, mode) \
- CHK_DEVICE(dev, id, client, mode, _XkbLookupAnyDevice)
-
-#define CHK_ATOM_ONLY2(a,ev,er) {\
- if (((a)==None)||(!ValidAtom((a)))) {\
- (ev)= (XID)(a);\
- return er;\
- }\
-}
-#define CHK_ATOM_ONLY(a) \
- CHK_ATOM_ONLY2(a,client->errorValue,BadAtom)
-
-#define CHK_ATOM_OR_NONE3(a,ev,er,ret) {\
- if (((a)!=None)&&(!ValidAtom((a)))) {\
- (ev)= (XID)(a);\
- (er)= BadAtom;\
- return ret;\
- }\
-}
-#define CHK_ATOM_OR_NONE2(a,ev,er) {\
- if (((a)!=None)&&(!ValidAtom((a)))) {\
- (ev)= (XID)(a);\
- return er;\
- }\
-}
-#define CHK_ATOM_OR_NONE(a) \
- CHK_ATOM_OR_NONE2(a,client->errorValue,BadAtom)
-
-#define CHK_MASK_LEGAL3(err,mask,legal,ev,er,ret) {\
- if ((mask)&(~(legal))) { \
- (ev)= _XkbErrCode2((err),((mask)&(~(legal))));\
- (er)= BadValue;\
- return ret;\
- }\
-}
-#define CHK_MASK_LEGAL2(err,mask,legal,ev,er) {\
- if ((mask)&(~(legal))) { \
- (ev)= _XkbErrCode2((err),((mask)&(~(legal))));\
- return er;\
- }\
-}
-#define CHK_MASK_LEGAL(err,mask,legal) \
- CHK_MASK_LEGAL2(err,mask,legal,client->errorValue,BadValue)
-
-#define CHK_MASK_MATCH(err,affect,value) {\
- if ((value)&(~(affect))) { \
- client->errorValue= _XkbErrCode2((err),((value)&(~(affect))));\
- return BadMatch;\
- }\
-}
-#define CHK_MASK_OVERLAP(err,m1,m2) {\
- if ((m1)&(m2)) { \
- client->errorValue= _XkbErrCode2((err),((m1)&(m2)));\
- return BadMatch;\
- }\
-}
-#define CHK_KEY_RANGE2(err,first,num,x,ev,er) {\
- if (((unsigned)(first)+(num)-1)>(x)->max_key_code) {\
- (ev)=_XkbErrCode4(err,(first),(num),(x)->max_key_code);\
- return er;\
- }\
- else if ( (first)<(x)->min_key_code ) {\
- (ev)=_XkbErrCode3(err+1,(first),xkb->min_key_code);\
- return er;\
- }\
-}
-#define CHK_KEY_RANGE(err,first,num,x) \
- CHK_KEY_RANGE2(err,first,num,x,client->errorValue,BadValue)
-
-#define CHK_REQ_KEY_RANGE2(err,first,num,r,ev,er) {\
- if (((unsigned)(first)+(num)-1)>(r)->maxKeyCode) {\
- (ev)=_XkbErrCode4(err,(first),(num),(r)->maxKeyCode);\
- return er;\
- }\
- else if ( (first)<(r)->minKeyCode ) {\
- (ev)=_XkbErrCode3(err+1,(first),(r)->minKeyCode);\
- return er;\
- }\
-}
-#define CHK_REQ_KEY_RANGE(err,first,num,r) \
- CHK_REQ_KEY_RANGE2(err,first,num,r,client->errorValue,BadValue)
-
-/***====================================================================***/
-
-int
-ProcXkbUseExtension(ClientPtr client)
-{
- REQUEST(xkbUseExtensionReq);
- xkbUseExtensionReply rep;
- register int n;
- int supported;
-
- REQUEST_SIZE_MATCH(xkbUseExtensionReq);
- if (stuff->wantedMajor != SERVER_XKB_MAJOR_VERSION) {
- /* pre-release version 0.65 is compatible with 1.00 */
- supported= ((SERVER_XKB_MAJOR_VERSION==1)&&
- (stuff->wantedMajor==0)&&(stuff->wantedMinor==65));
- }
- else supported = 1;
-
- if ((supported) && (!(client->xkbClientFlags&_XkbClientInitialized))) {
- client->xkbClientFlags= _XkbClientInitialized;
- client->vMajor= stuff->wantedMajor;
- client->vMinor= stuff->wantedMinor;
- }
- else if (xkbDebugFlags&0x1) {
- ErrorF("[xkb] Rejecting client %d (0x%lx) (wants %d.%02d, have %d.%02d)\n",
- client->index,
- (long)client->clientAsMask,
- stuff->wantedMajor,stuff->wantedMinor,
- SERVER_XKB_MAJOR_VERSION,SERVER_XKB_MINOR_VERSION);
- }
- memset(&rep, 0, sizeof(xkbUseExtensionReply));
- rep.type = X_Reply;
- rep.supported = supported;
- rep.length = 0;
- rep.sequenceNumber = client->sequence;
- rep.serverMajor = SERVER_XKB_MAJOR_VERSION;
- rep.serverMinor = SERVER_XKB_MINOR_VERSION;
- if ( client->swapped ) {
- swaps(&rep.sequenceNumber, n);
- swaps(&rep.serverMajor, n);
- swaps(&rep.serverMinor, n);
- }
- WriteToClient(client,SIZEOF(xkbUseExtensionReply), (char *)&rep);
- return Success;
-}
-
-/***====================================================================***/
-
-int
-ProcXkbSelectEvents(ClientPtr client)
-{
- unsigned legal;
- DeviceIntPtr dev;
- XkbInterestPtr masks;
- REQUEST(xkbSelectEventsReq);
-
- REQUEST_AT_LEAST_SIZE(xkbSelectEventsReq);
-
- if (!(client->xkbClientFlags&_XkbClientInitialized))
- return BadAccess;
-
- CHK_ANY_DEVICE(dev, stuff->deviceSpec, client, DixUseAccess);
-
- if (((stuff->affectWhich&XkbMapNotifyMask)!=0)&&(stuff->affectMap)) {
- client->mapNotifyMask&= ~stuff->affectMap;
- client->mapNotifyMask|= (stuff->affectMap&stuff->map);
- }
- if ((stuff->affectWhich&(~XkbMapNotifyMask))==0)
- return Success;
-
- masks = XkbFindClientResource((DevicePtr)dev,client);
- if (!masks){
- XID id = FakeClientID(client->index);
- if (!AddResource(id,RT_XKBCLIENT,dev))
- return BadAlloc;
- masks= XkbAddClientResource((DevicePtr)dev,client,id);
- }
- if (masks) {
- union {
- CARD8 *c8;
- CARD16 *c16;
- CARD32 *c32;
- } from,to;
- register unsigned bit,ndx,maskLeft,dataLeft,size;
-
- from.c8= (CARD8 *)&stuff[1];
- dataLeft= (stuff->length*4)-SIZEOF(xkbSelectEventsReq);
- maskLeft= (stuff->affectWhich&(~XkbMapNotifyMask));
- for (ndx=0,bit=1; (maskLeft!=0); ndx++, bit<<=1) {
- if ((bit&maskLeft)==0)
- continue;
- maskLeft&= ~bit;
- switch (ndx) {
- case XkbNewKeyboardNotify:
- to.c16= &client->newKeyboardNotifyMask;
- legal= XkbAllNewKeyboardEventsMask;
- size= 2;
- break;
- case XkbStateNotify:
- to.c16= &masks->stateNotifyMask;
- legal= XkbAllStateEventsMask;
- size= 2;
- break;
- case XkbControlsNotify:
- to.c32= &masks->ctrlsNotifyMask;
- legal= XkbAllControlEventsMask;
- size= 4;
- break;
- case XkbIndicatorStateNotify:
- to.c32= &masks->iStateNotifyMask;
- legal= XkbAllIndicatorEventsMask;
- size= 4;
- break;
- case XkbIndicatorMapNotify:
- to.c32= &masks->iMapNotifyMask;
- legal= XkbAllIndicatorEventsMask;
- size= 4;
- break;
- case XkbNamesNotify:
- to.c16= &masks->namesNotifyMask;
- legal= XkbAllNameEventsMask;
- size= 2;
- break;
- case XkbCompatMapNotify:
- to.c8= &masks->compatNotifyMask;
- legal= XkbAllCompatMapEventsMask;
- size= 1;
- break;
- case XkbBellNotify:
- to.c8= &masks->bellNotifyMask;
- legal= XkbAllBellEventsMask;
- size= 1;
- break;
- case XkbActionMessage:
- to.c8= &masks->actionMessageMask;
- legal= XkbAllActionMessagesMask;
- size= 1;
- break;
- case XkbAccessXNotify:
- to.c16= &masks->accessXNotifyMask;
- legal= XkbAllAccessXEventsMask;
- size= 2;
- break;
- case XkbExtensionDeviceNotify:
- to.c16= &masks->extDevNotifyMask;
- legal= XkbAllExtensionDeviceEventsMask;
- size= 2;
- break;
- default:
- client->errorValue = _XkbErrCode2(33,bit);
- return BadValue;
- }
-
- if (stuff->clear&bit) {
- if (size==2) to.c16[0]= 0;
- else if (size==4) to.c32[0]= 0;
- else to.c8[0]= 0;
- }
- else if (stuff->selectAll&bit) {
- if (size==2) to.c16[0]= ~0;
- else if (size==4) to.c32[0]= ~0;
- else to.c8[0]= ~0;
- }
- else {
- if (dataLeft<(size*2))
- return BadLength;
- if (size==2) {
- CHK_MASK_MATCH(ndx,from.c16[0],from.c16[1]);
- CHK_MASK_LEGAL(ndx,from.c16[0],legal);
- to.c16[0]&= ~from.c16[0];
- to.c16[0]|= (from.c16[0]&from.c16[1]);
- }
- else if (size==4) {
- CHK_MASK_MATCH(ndx,from.c32[0],from.c32[1]);
- CHK_MASK_LEGAL(ndx,from.c32[0],legal);
- to.c32[0]&= ~from.c32[0];
- to.c32[0]|= (from.c32[0]&from.c32[1]);
- }
- else {
- CHK_MASK_MATCH(ndx,from.c8[0],from.c8[1]);
- CHK_MASK_LEGAL(ndx,from.c8[0],legal);
- to.c8[0]&= ~from.c8[0];
- to.c8[0]|= (from.c8[0]&from.c8[1]);
- size= 2;
- }
- from.c8+= (size*2);
- dataLeft-= (size*2);
- }
- }
- if (dataLeft>2) {
- ErrorF("[xkb] Extra data (%d bytes) after SelectEvents\n",dataLeft);
- return BadLength;
- }
- return Success;
- }
- return BadAlloc;
-}
-
-/***====================================================================***/
-/**
- * Ring a bell on the given device for the given client.
- */
-static int
-_XkbBell(ClientPtr client, DeviceIntPtr dev, WindowPtr pWin,
- int bellClass, int bellID, int pitch, int duration,
- int percent, int forceSound, int eventOnly, Atom name)
-{
- int base;
- pointer ctrl;
- int oldPitch, oldDuration;
- int newPercent;
-
- if (bellClass == KbdFeedbackClass) {
- KbdFeedbackPtr k;
- if (bellID==XkbDfltXIId)
- k= dev->kbdfeed;
- else {
- for (k=dev->kbdfeed; k; k=k->next) {
- if (k->ctrl.id == bellID)
- break;
- }
- }
- if (!k) {
- client->errorValue = _XkbErrCode2(0x5,bellID);
- return BadValue;
- }
- base = k->ctrl.bell;
- ctrl = (pointer) &(k->ctrl);
- oldPitch= k->ctrl.bell_pitch;
- oldDuration= k->ctrl.bell_duration;
- if (pitch!=0) {
- if (pitch==-1)
- k->ctrl.bell_pitch= defaultKeyboardControl.bell_pitch;
- else k->ctrl.bell_pitch= pitch;
- }
- if (duration!=0) {
- if (duration==-1)
- k->ctrl.bell_duration= defaultKeyboardControl.bell_duration;
- else k->ctrl.bell_duration= duration;
- }
- }
- else if (bellClass == BellFeedbackClass) {
- BellFeedbackPtr b;
- if (bellID==XkbDfltXIId)
- b= dev->bell;
- else {
- for (b=dev->bell; b; b=b->next) {
- if (b->ctrl.id == bellID)
- break;
- }
- }
- if (!b) {
- client->errorValue = _XkbErrCode2(0x6,bellID);
- return BadValue;
- }
- base = b->ctrl.percent;
- ctrl = (pointer) &(b->ctrl);
- oldPitch= b->ctrl.pitch;
- oldDuration= b->ctrl.duration;
- if (pitch!=0) {
- if (pitch==-1)
- b->ctrl.pitch= defaultKeyboardControl.bell_pitch;
- else b->ctrl.pitch= pitch;
- }
- if (duration!=0) {
- if (duration==-1)
- b->ctrl.duration= defaultKeyboardControl.bell_duration;
- else b->ctrl.duration= duration;
- }
- }
- else {
- client->errorValue = _XkbErrCode2(0x7, bellClass);
- return BadValue;
- }
-
- newPercent = (base * percent)/100;
- if (percent < 0)
- newPercent = base + newPercent;
- else newPercent = base - newPercent + percent;
-
- XkbHandleBell(forceSound, eventOnly,
- dev, newPercent, ctrl, bellClass,
- name, pWin, client);
- if ((pitch!=0)||(duration!=0)) {
- if (bellClass == KbdFeedbackClass) {
- KbdFeedbackPtr k;
- k= (KbdFeedbackPtr)ctrl;
- if (pitch!=0)
- k->ctrl.bell_pitch= oldPitch;
- if (duration!=0)
- k->ctrl.bell_duration= oldDuration;
- }
- else {
- BellFeedbackPtr b;
- b= (BellFeedbackPtr)ctrl;
- if (pitch!=0)
- b->ctrl.pitch= oldPitch;
- if (duration!=0)
- b->ctrl.duration= oldDuration;
- }
- }
-
- return Success;
-}
-
-int
-ProcXkbBell(ClientPtr client)
-{
- REQUEST(xkbBellReq);
- DeviceIntPtr dev;
- WindowPtr pWin;
- int rc;
-
- REQUEST_SIZE_MATCH(xkbBellReq);
-
- if (!(client->xkbClientFlags&_XkbClientInitialized))
- return BadAccess;
-
- CHK_BELL_DEVICE(dev, stuff->deviceSpec, client, DixBellAccess);
- CHK_ATOM_OR_NONE(stuff->name);
-
- /* device-independent checks request for sane values */
- if ((stuff->forceSound)&&(stuff->eventOnly)) {
- client->errorValue=_XkbErrCode3(0x1,stuff->forceSound,stuff->eventOnly);
- return BadMatch;
- }
- if (stuff->percent < -100 || stuff->percent > 100) {
- client->errorValue = _XkbErrCode2(0x2,stuff->percent);
- return BadValue;
- }
- if (stuff->duration<-1) {
- client->errorValue = _XkbErrCode2(0x3,stuff->duration);
- return BadValue;
- }
- if (stuff->pitch<-1) {
- client->errorValue = _XkbErrCode2(0x4,stuff->pitch);
- return BadValue;
- }
-
- if (stuff->bellClass == XkbDfltXIClass) {
- if (dev->kbdfeed!=NULL)
- stuff->bellClass= KbdFeedbackClass;
- else stuff->bellClass= BellFeedbackClass;
- }
-
- if (stuff->window!=None) {
- rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
- if (rc != Success) {
- client->errorValue= stuff->window;
- return rc;
- }
- }
- else pWin= NULL;
-
- /* Client wants to ring a bell on the core keyboard?
- Ring the bell on the core keyboard (which does nothing, but if that
- fails the client is screwed anyway), and then on all extension devices.
- Fail if the core keyboard fails but not the extension devices. this
- may cause some keyboards to ding and others to stay silent. Fix
- your client to use explicit keyboards to avoid this.
-
- dev is the device the client requested.
- */
- rc = _XkbBell(client, dev, pWin, stuff->bellClass, stuff->bellID,
- stuff->pitch, stuff->duration, stuff->percent,
- stuff->forceSound, stuff->eventOnly, stuff->name);
-
- if ((rc == Success) && ((stuff->deviceSpec == XkbUseCoreKbd) ||
- (stuff->deviceSpec == XkbUseCorePtr)))
- {
- DeviceIntPtr other;
- for (other = inputInfo.devices; other; other = other->next)
- {
- if ((other != dev) && other->key && !IsMaster(other) && GetMaster(other, MASTER_KEYBOARD) == dev)
- {
- rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixBellAccess);
- if (rc == Success)
- _XkbBell(client, other, pWin, stuff->bellClass,
- stuff->bellID, stuff->pitch, stuff->duration,
- stuff->percent, stuff->forceSound,
- stuff->eventOnly, stuff->name);
- }
- }
- rc = Success; /* reset to success, that's what we got for the VCK */
- }
-
- return rc;
-}
-
-/***====================================================================***/
-
-int
-ProcXkbGetState(ClientPtr client)
-{
- REQUEST(xkbGetStateReq);
- DeviceIntPtr dev;
- xkbGetStateReply rep;
- XkbStateRec *xkb;
-
- REQUEST_SIZE_MATCH(xkbGetStateReq);
-
- if (!(client->xkbClientFlags&_XkbClientInitialized))
- return BadAccess;
-
- CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
-
- xkb= &dev->key->xkbInfo->state;
- memset(&rep, 0, sizeof(xkbGetStateReply));
- rep.type= X_Reply;
- rep.sequenceNumber= client->sequence;
- rep.length = 0;
- rep.deviceID = dev->id;
- rep.mods = XkbStateFieldFromRec(xkb) & 0xff;
- rep.baseMods = xkb->base_mods;
- rep.lockedMods = xkb->locked_mods;
- rep.latchedMods = xkb->latched_mods;
- rep.group = xkb->group;
- rep.baseGroup = xkb->base_group;
- rep.latchedGroup = xkb->latched_group;
- rep.lockedGroup = xkb->locked_group;
- rep.compatState = xkb->compat_state;
- rep.ptrBtnState = xkb->ptr_buttons;
- if (client->swapped) {
- register int n;
- swaps(&rep.sequenceNumber,n);
- swaps(&rep.ptrBtnState,n);
- }
- WriteToClient(client, SIZEOF(xkbGetStateReply), (char *)&rep);
- return Success;
-}
-
-/***====================================================================***/
-
-int
-ProcXkbLatchLockState(ClientPtr client)
-{
- int status;
- DeviceIntPtr dev, tmpd;
- XkbStateRec oldState,*newState;
- CARD16 changed;
- xkbStateNotify sn;
- XkbEventCauseRec cause;
-
- REQUEST(xkbLatchLockStateReq);
- REQUEST_SIZE_MATCH(xkbLatchLockStateReq);
-
- if (!(client->xkbClientFlags & _XkbClientInitialized))
- return BadAccess;
-
- CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixSetAttrAccess);
- CHK_MASK_MATCH(0x01, stuff->affectModLocks, stuff->modLocks);
- CHK_MASK_MATCH(0x01, stuff->affectModLatches, stuff->modLatches);
-
- status = Success;
-
- for (tmpd = inputInfo.devices; tmpd; tmpd = tmpd->next) {
- if ((tmpd == dev) || (!IsMaster(tmpd) && GetMaster(tmpd, MASTER_KEYBOARD) == dev)) {
- if (!tmpd->key || !tmpd->key->xkbInfo)
- continue;
-
- oldState = tmpd->key->xkbInfo->state;
- newState = &tmpd->key->xkbInfo->state;
- if (stuff->affectModLocks) {
- newState->locked_mods &= ~stuff->affectModLocks;
- newState->locked_mods |= (stuff->affectModLocks & stuff->modLocks);
- }
- if (status == Success && stuff->lockGroup)
- newState->locked_group = stuff->groupLock;
- if (status == Success && stuff->affectModLatches)
- status = XkbLatchModifiers(tmpd, stuff->affectModLatches,
- stuff->modLatches);
- if (status == Success && stuff->latchGroup)
- status = XkbLatchGroup(tmpd, stuff->groupLatch);
-
- if (status != Success)
- return status;
-
- XkbComputeDerivedState(tmpd->key->xkbInfo);
-
- changed = XkbStateChangedFlags(&oldState, newState);
- if (changed) {
- sn.keycode = 0;
- sn.eventType = 0;
- sn.requestMajor = XkbReqCode;
- sn.requestMinor = X_kbLatchLockState;
- sn.changed = changed;
- XkbSendStateNotify(tmpd, &sn);
- changed = XkbIndicatorsToUpdate(tmpd, changed, FALSE);
- if (changed) {
- XkbSetCauseXkbReq(&cause, X_kbLatchLockState, client);
- XkbUpdateIndicators(tmpd, changed, TRUE, NULL, &cause);
- }
- }
- }
- }
-
- return Success;
-}
-
-/***====================================================================***/
-
-int
-ProcXkbGetControls(ClientPtr client)
-{
- xkbGetControlsReply rep;
- XkbControlsPtr xkb;
- DeviceIntPtr dev;
- register int n;
-
- REQUEST(xkbGetControlsReq);
- REQUEST_SIZE_MATCH(xkbGetControlsReq);
-
- if (!(client->xkbClientFlags&_XkbClientInitialized))
- return BadAccess;
-
- CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
-
- xkb = dev->key->xkbInfo->desc->ctrls;
- rep.type = X_Reply;
- rep.length = bytes_to_int32(SIZEOF(xkbGetControlsReply)-
- SIZEOF(xGenericReply));
- rep.sequenceNumber = client->sequence;
- rep.deviceID = ((DeviceIntPtr)dev)->id;
- rep.numGroups = xkb->num_groups;
- rep.groupsWrap = xkb->groups_wrap;
- rep.internalMods = xkb->internal.mask;
- rep.ignoreLockMods = xkb->ignore_lock.mask;
- rep.internalRealMods = xkb->internal.real_mods;
- rep.ignoreLockRealMods = xkb->ignore_lock.real_mods;
- rep.internalVMods = xkb->internal.vmods;
- rep.ignoreLockVMods = xkb->ignore_lock.vmods;
- rep.enabledCtrls = xkb->enabled_ctrls;
- rep.repeatDelay = xkb->repeat_delay;
- rep.repeatInterval = xkb->repeat_interval;
- rep.slowKeysDelay = xkb->slow_keys_delay;
- rep.debounceDelay = xkb->debounce_delay;
- rep.mkDelay = xkb->mk_delay;
- rep.mkInterval = xkb->mk_interval;
- rep.mkTimeToMax = xkb->mk_time_to_max;
- rep.mkMaxSpeed = xkb->mk_max_speed;
- rep.mkCurve = xkb->mk_curve;
- rep.mkDfltBtn = xkb->mk_dflt_btn;
- rep.axTimeout = xkb->ax_timeout;
- rep.axtCtrlsMask = xkb->axt_ctrls_mask;
- rep.axtCtrlsValues = xkb->axt_ctrls_values;
- rep.axtOptsMask = xkb->axt_opts_mask;
- rep.axtOptsValues = xkb->axt_opts_values;
- rep.axOptions = xkb->ax_options;
- memcpy(rep.perKeyRepeat,xkb->per_key_repeat,XkbPerKeyBitArraySize);
- if (client->swapped) {
- swaps(&rep.sequenceNumber, n);
- swapl(&rep.length,n);
- swaps(&rep.internalVMods, n);
- swaps(&rep.ignoreLockVMods, n);
- swapl(&rep.enabledCtrls, n);
- swaps(&rep.repeatDelay, n);
- swaps(&rep.repeatInterval, n);
- swaps(&rep.slowKeysDelay, n);
- swaps(&rep.debounceDelay, n);
- swaps(&rep.mkDelay, n);
- swaps(&rep.mkInterval, n);
- swaps(&rep.mkTimeToMax, n);
- swaps(&rep.mkMaxSpeed, n);
- swaps(&rep.mkCurve, n);
- swaps(&rep.axTimeout, n);
- swapl(&rep.axtCtrlsMask, n);
- swapl(&rep.axtCtrlsValues, n);
- swaps(&rep.axtOptsMask, n);
- swaps(&rep.axtOptsValues, n);
- swaps(&rep.axOptions, n);
- }
- WriteToClient(client, SIZEOF(xkbGetControlsReply), (char *)&rep);
- return Success;
-}
-
-int
-ProcXkbSetControls(ClientPtr client)
-{
- DeviceIntPtr dev, tmpd;
- XkbSrvInfoPtr xkbi;
- XkbControlsPtr ctrl;
- XkbControlsRec new,old;
- xkbControlsNotify cn;
- XkbEventCauseRec cause;
- XkbSrvLedInfoPtr sli;
-
- REQUEST(xkbSetControlsReq);
- REQUEST_SIZE_MATCH(xkbSetControlsReq);
-
- if (!(client->xkbClientFlags & _XkbClientInitialized))
- return BadAccess;
-
- CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess);
- CHK_MASK_LEGAL(0x01, stuff->changeCtrls, XkbAllControlsMask);
-
- for (tmpd = inputInfo.devices; tmpd; tmpd = tmpd->next) {
- if (!tmpd->key || !tmpd->key->xkbInfo)
- continue;
- if ((tmpd == dev) || (!IsMaster(tmpd) && GetMaster(tmpd, MASTER_KEYBOARD) == dev)) {
- xkbi = tmpd->key->xkbInfo;
- ctrl = xkbi->desc->ctrls;
- new = *ctrl;
- XkbSetCauseXkbReq(&cause, X_kbSetControls, client);
-
- if (stuff->changeCtrls & XkbInternalModsMask) {
- CHK_MASK_MATCH(0x02, stuff->affectInternalMods,
- stuff->internalMods);
- CHK_MASK_MATCH(0x03, stuff->affectInternalVMods,
- stuff->internalVMods);
-
- new.internal.real_mods &= ~(stuff->affectInternalMods);
- new.internal.real_mods |= (stuff->affectInternalMods &
- stuff->internalMods);
- new.internal.vmods &= ~(stuff->affectInternalVMods);
- new.internal.vmods |= (stuff->affectInternalVMods &
- stuff->internalVMods);
- new.internal.mask = new.internal.real_mods |
- XkbMaskForVMask(xkbi->desc,
- new.internal.vmods);
- }
-
- if (stuff->changeCtrls & XkbIgnoreLockModsMask) {
- CHK_MASK_MATCH(0x4, stuff->affectIgnoreLockMods,
- stuff->ignoreLockMods);
- CHK_MASK_MATCH(0x5, stuff->affectIgnoreLockVMods,
- stuff->ignoreLockVMods);
-
- new.ignore_lock.real_mods &= ~(stuff->affectIgnoreLockMods);
- new.ignore_lock.real_mods |= (stuff->affectIgnoreLockMods &
- stuff->ignoreLockMods);
- new.ignore_lock.vmods &= ~(stuff->affectIgnoreLockVMods);
- new.ignore_lock.vmods |= (stuff->affectIgnoreLockVMods &
- stuff->ignoreLockVMods);
- new.ignore_lock.mask = new.ignore_lock.real_mods |
- XkbMaskForVMask(xkbi->desc,
- new.ignore_lock.vmods);
- }
-
- CHK_MASK_MATCH(0x06, stuff->affectEnabledCtrls,
- stuff->enabledCtrls);
- if (stuff->affectEnabledCtrls) {
- CHK_MASK_LEGAL(0x07, stuff->affectEnabledCtrls,
- XkbAllBooleanCtrlsMask);
-
- new.enabled_ctrls &= ~(stuff->affectEnabledCtrls);
- new.enabled_ctrls |= (stuff->affectEnabledCtrls &
- stuff->enabledCtrls);
- }
-
- if (stuff->changeCtrls & XkbRepeatKeysMask) {
- if (stuff->repeatDelay < 1 || stuff->repeatInterval < 1) {
- client->errorValue = _XkbErrCode3(0x08, stuff->repeatDelay,
- stuff->repeatInterval);
- return BadValue;
- }
-
- new.repeat_delay = stuff->repeatDelay;
- new.repeat_interval = stuff->repeatInterval;
- }
-
- if (stuff->changeCtrls & XkbSlowKeysMask) {
- if (stuff->slowKeysDelay < 1) {
- client->errorValue = _XkbErrCode2(0x09,
- stuff->slowKeysDelay);
- return BadValue;
- }
-
- new.slow_keys_delay = stuff->slowKeysDelay;
- }
-
- if (stuff->changeCtrls & XkbBounceKeysMask) {
- if (stuff->debounceDelay < 1) {
- client->errorValue = _XkbErrCode2(0x0A,
- stuff->debounceDelay);
- return BadValue;
- }
-
- new.debounce_delay = stuff->debounceDelay;
- }
-
- if (stuff->changeCtrls & XkbMouseKeysMask) {
- if (stuff->mkDfltBtn > XkbMaxMouseKeysBtn) {
- client->errorValue = _XkbErrCode2(0x0B, stuff->mkDfltBtn);
- return BadValue;
- }
-
- new.mk_dflt_btn = stuff->mkDfltBtn;
- }
-
- if (stuff->changeCtrls & XkbMouseKeysAccelMask) {
- if (stuff->mkDelay < 1 || stuff->mkInterval < 1 ||
- stuff->mkTimeToMax < 1 || stuff->mkMaxSpeed < 1 ||
- stuff->mkCurve < -1000) {
- client->errorValue = _XkbErrCode2(0x0C,0);
- return BadValue;
- }
-
- new.mk_delay = stuff->mkDelay;
- new.mk_interval = stuff->mkInterval;
- new.mk_time_to_max = stuff->mkTimeToMax;
- new.mk_max_speed = stuff->mkMaxSpeed;
- new.mk_curve = stuff->mkCurve;
- AccessXComputeCurveFactor(xkbi, &new);
- }
-
- if (stuff->changeCtrls & XkbGroupsWrapMask) {
- unsigned act, num;
-
- act = XkbOutOfRangeGroupAction(stuff->groupsWrap);
- switch (act) {
- case XkbRedirectIntoRange:
- num = XkbOutOfRangeGroupNumber(stuff->groupsWrap);
- if (num >= new.num_groups) {
- client->errorValue = _XkbErrCode3(0x0D, new.num_groups,
- num);
- return BadValue;
- }
- case XkbWrapIntoRange:
- case XkbClampIntoRange:
- break;
- default:
- client->errorValue = _XkbErrCode2(0x0E, act);
- return BadValue;
- }
-
- new.groups_wrap= stuff->groupsWrap;
- }
-
- CHK_MASK_LEGAL(0x0F, stuff->axOptions, XkbAX_AllOptionsMask);
- if (stuff->changeCtrls & XkbAccessXKeysMask) {
- new.ax_options = stuff->axOptions & XkbAX_AllOptionsMask;
- }
- else {
- if (stuff->changeCtrls & XkbStickyKeysMask) {
- new.ax_options &= ~(XkbAX_SKOptionsMask);
- new.ax_options |= (stuff->axOptions & XkbAX_SKOptionsMask);
- }
-
- if (stuff->changeCtrls & XkbAccessXFeedbackMask) {
- new.ax_options &= ~(XkbAX_FBOptionsMask);
- new.ax_options |= (stuff->axOptions & XkbAX_FBOptionsMask);
- }
- }
-
- if (stuff->changeCtrls & XkbAccessXTimeoutMask) {
- if (stuff->axTimeout < 1) {
- client->errorValue = _XkbErrCode2(0x10, stuff->axTimeout);
- return BadValue;
- }
- CHK_MASK_MATCH(0x11, stuff->axtCtrlsMask,
- stuff->axtCtrlsValues);
- CHK_MASK_LEGAL(0x12, stuff->axtCtrlsMask,
- XkbAllBooleanCtrlsMask);
- CHK_MASK_MATCH(0x13, stuff->axtOptsMask, stuff->axtOptsValues);
- CHK_MASK_LEGAL(0x14, stuff->axtOptsMask, XkbAX_AllOptionsMask);
- new.ax_timeout = stuff->axTimeout;
- new.axt_ctrls_mask = stuff->axtCtrlsMask;
- new.axt_ctrls_values = (stuff->axtCtrlsValues &
- stuff->axtCtrlsMask);
- new.axt_opts_mask = stuff->axtOptsMask;
- new.axt_opts_values = (stuff->axtOptsValues &
- stuff->axtOptsMask);
- }
-
- if (stuff->changeCtrls & XkbPerKeyRepeatMask) {
- memcpy(new.per_key_repeat, stuff->perKeyRepeat,
- XkbPerKeyBitArraySize);
- if (xkbi->repeatKey &&
- !BitIsOn(new.per_key_repeat, xkbi->repeatKey)) {
- AccessXCancelRepeatKey(xkbi, xkbi->repeatKey);
- }
- }
-
- old= *ctrl;
- *ctrl= new;
- XkbDDXChangeControls(tmpd, &old, ctrl);
-
- if (XkbComputeControlsNotify(tmpd, &old, ctrl, &cn, FALSE)) {
- cn.keycode = 0;
- cn.eventType = 0;
- cn.requestMajor = XkbReqCode;
- cn.requestMinor = X_kbSetControls;
- XkbSendControlsNotify(tmpd, &cn);
- }
-
- sli = XkbFindSrvLedInfo(tmpd, XkbDfltXIClass, XkbDfltXIId, 0);
- if (sli)
- XkbUpdateIndicators(tmpd, sli->usesControls, TRUE, NULL,
- &cause);
-
- /* If sticky keys were disabled, clear all locks and latches */
- if ((old.enabled_ctrls & XkbStickyKeysMask) &&
- !(ctrl->enabled_ctrls & XkbStickyKeysMask))
- XkbClearAllLatchesAndLocks(tmpd, xkbi, TRUE, &cause);
- }
- }
-
- return Success;
-}
-
-/***====================================================================***/
-
-static int
-XkbSizeKeyTypes(XkbDescPtr xkb,xkbGetMapReply *rep)
-{
- XkbKeyTypeRec *type;
- unsigned i,len;
-
- len= 0;
- if (((rep->present&XkbKeyTypesMask)==0)||(rep->nTypes<1)||
- (!xkb)||(!xkb->map)||(!xkb->map->types)) {
- rep->present&= ~XkbKeyTypesMask;
- rep->firstType= rep->nTypes= 0;
- return 0;
- }
- type= &xkb->map->types[rep->firstType];
- for (i=0;i<rep->nTypes;i++,type++){
- len+= SIZEOF(xkbKeyTypeWireDesc);
- if (type->map_count>0) {
- len+= (type->map_count*SIZEOF(xkbKTMapEntryWireDesc));
- if (type->preserve)
- len+= (type->map_count*SIZEOF(xkbModsWireDesc));
- }
- }
- return len;
-}
-
-static char *
-XkbWriteKeyTypes( XkbDescPtr xkb,
- xkbGetMapReply * rep,
- char * buf,
- ClientPtr client)
-{
- XkbKeyTypePtr type;
- unsigned i;
- xkbKeyTypeWireDesc *wire;
-
- type= &xkb->map->types[rep->firstType];
- for (i=0;i<rep->nTypes;i++,type++) {
- register unsigned n;
- wire= (xkbKeyTypeWireDesc *)buf;
- wire->mask = type->mods.mask;
- wire->realMods = type->mods.real_mods;
- wire->virtualMods = type->mods.vmods;
- wire->numLevels = type->num_levels;
- wire->nMapEntries = type->map_count;
- wire->preserve = (type->preserve!=NULL);
- if (client->swapped) {
- register int n;
- swaps(&wire->virtualMods,n);
- }
-
- buf= (char *)&wire[1];
- if (wire->nMapEntries>0) {
- xkbKTMapEntryWireDesc * wire;
- XkbKTMapEntryPtr entry;
- wire= (xkbKTMapEntryWireDesc *)buf;
- entry= type->map;
- for (n=0;n<type->map_count;n++,wire++,entry++) {
- wire->active= entry->active;
- wire->mask= entry->mods.mask;
- wire->level= entry->level;
- wire->realMods= entry->mods.real_mods;
- wire->virtualMods= entry->mods.vmods;
- if (client->swapped) {
- register int n;
- swaps(&wire->virtualMods,n);
- }
- }
- buf= (char *)wire;
- if (type->preserve!=NULL) {
- xkbModsWireDesc * pwire;
- XkbModsPtr preserve;
- pwire= (xkbModsWireDesc *)buf;
- preserve= type->preserve;
- for (n=0;n<type->map_count;n++,pwire++,preserve++) {
- pwire->mask= preserve->mask;
- pwire->realMods= preserve->real_mods;
- pwire->virtualMods= preserve->vmods;
- if (client->swapped) {
- register int n;
- swaps(&pwire->virtualMods,n);
- }
- }
- buf= (char *)pwire;
- }
- }
- }
- return buf;
-}
-
-static int
-XkbSizeKeySyms(XkbDescPtr xkb,xkbGetMapReply *rep)
-{
- XkbSymMapPtr symMap;
- unsigned i,len;
- unsigned nSyms,nSymsThisKey;
-
- if (((rep->present&XkbKeySymsMask)==0)||(rep->nKeySyms<1)||
- (!xkb)||(!xkb->map)||(!xkb->map->key_sym_map)) {
- rep->present&= ~XkbKeySymsMask;
- rep->firstKeySym= rep->nKeySyms= 0;
- rep->totalSyms= 0;
- return 0;
- }
- len= rep->nKeySyms*SIZEOF(xkbSymMapWireDesc);
- symMap = &xkb->map->key_sym_map[rep->firstKeySym];
- for (i=nSyms=0;i<rep->nKeySyms;i++,symMap++) {
- if (symMap->offset!=0) {
- nSymsThisKey= XkbNumGroups(symMap->group_info)*symMap->width;
- nSyms+= nSymsThisKey;
- }
- }
- len+= nSyms*4;
- rep->totalSyms= nSyms;
- return len;
-}
-
-static int
-XkbSizeVirtualMods(XkbDescPtr xkb,xkbGetMapReply *rep)
-{
-register unsigned i,nMods,bit;
-
- if (((rep->present&XkbVirtualModsMask)==0)||(rep->virtualMods==0)||
- (!xkb)||(!xkb->server)) {
- rep->present&= ~XkbVirtualModsMask;
- rep->virtualMods= 0;
- return 0;
- }
- for (i=nMods=0,bit=1;i<XkbNumVirtualMods;i++,bit<<=1) {
- if (rep->virtualMods&bit)
- nMods++;
- }
- return XkbPaddedSize(nMods);
-}
-
-static char *
-XkbWriteKeySyms(XkbDescPtr xkb,xkbGetMapReply *rep,char *buf,ClientPtr client)
-{
-register KeySym * pSym;
-XkbSymMapPtr symMap;
-xkbSymMapWireDesc * outMap;
-register unsigned i;
-
- symMap = &xkb->map->key_sym_map[rep->firstKeySym];
- for (i=0;i<rep->nKeySyms;i++,symMap++) {
- outMap = (xkbSymMapWireDesc *)buf;
- outMap->ktIndex[0] = symMap->kt_index[0];
- outMap->ktIndex[1] = symMap->kt_index[1];
- outMap->ktIndex[2] = symMap->kt_index[2];
- outMap->ktIndex[3] = symMap->kt_index[3];
- outMap->groupInfo = symMap->group_info;
- outMap->width= symMap->width;
- outMap->nSyms = symMap->width*XkbNumGroups(symMap->group_info);
- buf= (char *)&outMap[1];
- if (outMap->nSyms==0)
- continue;
-
- pSym = &xkb->map->syms[symMap->offset];
- memcpy((char *)buf,(char *)pSym,outMap->nSyms*4);
- if (client->swapped) {
- register int n,nSyms= outMap->nSyms;
- swaps(&outMap->nSyms,n);
- while (nSyms-->0) {
- swapl(buf,n);
- buf+= 4;
- }
- }
- else buf+= outMap->nSyms*4;
- }
- return buf;
-}
-
-static int
-XkbSizeKeyActions(XkbDescPtr xkb,xkbGetMapReply *rep)
-{
- unsigned i,len,nActs;
- register KeyCode firstKey;
-
- if (((rep->present&XkbKeyActionsMask)==0)||(rep->nKeyActs<1)||
- (!xkb)||(!xkb->server)||(!xkb->server->key_acts)) {
- rep->present&= ~XkbKeyActionsMask;
- rep->firstKeyAct= rep->nKeyActs= 0;
- rep->totalActs= 0;
- return 0;
- }
- firstKey= rep->firstKeyAct;
- for (nActs=i=0;i<rep->nKeyActs;i++) {
- if (xkb->server->key_acts[i+firstKey]!=0)
- nActs+= XkbKeyNumActions(xkb,i+firstKey);
- }
- len= XkbPaddedSize(rep->nKeyActs)+(nActs*SIZEOF(xkbActionWireDesc));
- rep->totalActs= nActs;
- return len;
-}
-
-static char *
-XkbWriteKeyActions(XkbDescPtr xkb,xkbGetMapReply *rep,char *buf,
- ClientPtr client)
-{
- unsigned i;
- CARD8 * numDesc;
- XkbAnyAction * actDesc;
-
- numDesc = (CARD8 *)buf;
- for (i=0;i<rep->nKeyActs;i++) {
- if (xkb->server->key_acts[i+rep->firstKeyAct]==0)
- numDesc[i] = 0;
- else numDesc[i] = XkbKeyNumActions(xkb,(i+rep->firstKeyAct));
- }
- buf+= XkbPaddedSize(rep->nKeyActs);
-
- actDesc = (XkbAnyAction *)buf;
- for (i=0;i<rep->nKeyActs;i++) {
- if (xkb->server->key_acts[i+rep->firstKeyAct]!=0) {
- unsigned int num;
- num = XkbKeyNumActions(xkb,(i+rep->firstKeyAct));
- memcpy((char *)actDesc,
- (char*)XkbKeyActionsPtr(xkb,(i+rep->firstKeyAct)),
- num*SIZEOF(xkbActionWireDesc));
- actDesc+= num;
- }
- }
- buf = (char *)actDesc;
- return buf;
-}
-
-static int
-XkbSizeKeyBehaviors(XkbDescPtr xkb,xkbGetMapReply *rep)
-{
- unsigned i,len,nBhvr;
- XkbBehavior * bhv;
-
- if (((rep->present&XkbKeyBehaviorsMask)==0)||(rep->nKeyBehaviors<1)||
- (!xkb)||(!xkb->server)||(!xkb->server->behaviors)) {
- rep->present&= ~XkbKeyBehaviorsMask;
- rep->firstKeyBehavior= rep->nKeyBehaviors= 0;
- rep->totalKeyBehaviors= 0;
- return 0;
- }
- bhv= &xkb->server->behaviors[rep->firstKeyBehavior];
- for (nBhvr=i=0;i<rep->nKeyBehaviors;i++,bhv++) {
- if (bhv->type!=XkbKB_Default)
- nBhvr++;
- }
- len= nBhvr*SIZEOF(xkbBehaviorWireDesc);
- rep->totalKeyBehaviors= nBhvr;
- return len;
-}
-
-static char *
-XkbWriteKeyBehaviors(XkbDescPtr xkb,xkbGetMapReply *rep,char *buf,
- ClientPtr client)
-{
- unsigned i;
- xkbBehaviorWireDesc *wire;
- XkbBehavior *pBhvr;
-
- wire = (xkbBehaviorWireDesc *)buf;
- pBhvr= &xkb->server->behaviors[rep->firstKeyBehavior];
- for (i=0;i<rep->nKeyBehaviors;i++,pBhvr++) {
- if (pBhvr->type!=XkbKB_Default) {
- wire->key= i+rep->firstKeyBehavior;
- wire->type= pBhvr->type;
- wire->data= pBhvr->data;
- wire++;
- }
- }
- buf = (char *)wire;
- return buf;
-}
-
-static int
-XkbSizeExplicit(XkbDescPtr xkb,xkbGetMapReply *rep)
-{
- unsigned i,len,nRtrn;
-
- if (((rep->present&XkbExplicitComponentsMask)==0)||(rep->nKeyExplicit<1)||
- (!xkb)||(!xkb->server)||(!xkb->server->explicit)) {
- rep->present&= ~XkbExplicitComponentsMask;
- rep->firstKeyExplicit= rep->nKeyExplicit= 0;
- rep->totalKeyExplicit= 0;
- return 0;
- }
- for (nRtrn=i=0;i<rep->nKeyExplicit;i++) {
- if (xkb->server->explicit[i+rep->firstKeyExplicit]!=0)
- nRtrn++;
- }
- rep->totalKeyExplicit= nRtrn;
- len= XkbPaddedSize(nRtrn*2); /* two bytes per non-zero explicit component */
- return len;
-}
-
-static char *
-XkbWriteExplicit(XkbDescPtr xkb,xkbGetMapReply *rep,char *buf,ClientPtr client)
-{
-unsigned i;
-char * start;
-unsigned char * pExp;
-
- start= buf;
- pExp= &xkb->server->explicit[rep->firstKeyExplicit];
- for (i=0;i<rep->nKeyExplicit;i++,pExp++) {
- if (*pExp!=0) {
- *buf++= i+rep->firstKeyExplicit;
- *buf++= *pExp;
- }
- }
- i= XkbPaddedSize(buf-start)-(buf-start); /* pad to word boundary */
- return buf+i;
-}
-
-static int
-XkbSizeModifierMap(XkbDescPtr xkb,xkbGetMapReply *rep)
-{
- unsigned i,len,nRtrn;
-
- if (((rep->present&XkbModifierMapMask)==0)||(rep->nModMapKeys<1)||
- (!xkb)||(!xkb->map)||(!xkb->map->modmap)) {
- rep->present&= ~XkbModifierMapMask;
- rep->firstModMapKey= rep->nModMapKeys= 0;
- rep->totalModMapKeys= 0;
- return 0;
- }
- for (nRtrn=i=0;i<rep->nModMapKeys;i++) {
- if (xkb->map->modmap[i+rep->firstModMapKey]!=0)
- nRtrn++;
- }
- rep->totalModMapKeys= nRtrn;
- len= XkbPaddedSize(nRtrn*2); /* two bytes per non-zero modmap component */
- return len;
-}
-
-static char *
-XkbWriteModifierMap(XkbDescPtr xkb,xkbGetMapReply *rep,char *buf,
- ClientPtr client)
-{
-unsigned i;
-char * start;
-unsigned char * pMap;
-
- start= buf;
- pMap= &xkb->map->modmap[rep->firstModMapKey];
- for (i=0;i<rep->nModMapKeys;i++,pMap++) {
- if (*pMap!=0) {
- *buf++= i+rep->firstModMapKey;
- *buf++= *pMap;
- }
- }
- i= XkbPaddedSize(buf-start)-(buf-start); /* pad to word boundary */
- return buf+i;
-}
-
-static int
-XkbSizeVirtualModMap(XkbDescPtr xkb,xkbGetMapReply *rep)
-{
- unsigned i,len,nRtrn;
-
- if (((rep->present&XkbVirtualModMapMask)==0)||(rep->nVModMapKeys<1)||
- (!xkb)||(!xkb->server)||(!xkb->server->vmodmap)) {
- rep->present&= ~XkbVirtualModMapMask;
- rep->firstVModMapKey= rep->nVModMapKeys= 0;
- rep->totalVModMapKeys= 0;
- return 0;
- }
- for (nRtrn=i=0;i<rep->nVModMapKeys;i++) {
- if (xkb->server->vmodmap[i+rep->firstVModMapKey]!=0)
- nRtrn++;
- }
- rep->totalVModMapKeys= nRtrn;
- len= nRtrn*SIZEOF(xkbVModMapWireDesc);
- return len;
-}
-
-static char *
-XkbWriteVirtualModMap(XkbDescPtr xkb,xkbGetMapReply *rep,char *buf,
- ClientPtr client)
-{
-unsigned i;
-xkbVModMapWireDesc * wire;
-unsigned short * pMap;
-
- wire= (xkbVModMapWireDesc *)buf;
- pMap= &xkb->server->vmodmap[rep->firstVModMapKey];
- for (i=0;i<rep->nVModMapKeys;i++,pMap++) {
- if (*pMap!=0) {
- wire->key= i+rep->firstVModMapKey;
- wire->vmods= *pMap;
- wire++;
- }
- }
- return (char *)wire;
-}
-
-static Status
-XkbComputeGetMapReplySize(XkbDescPtr xkb,xkbGetMapReply *rep)
-{
-int len;
-
- rep->minKeyCode= xkb->min_key_code;
- rep->maxKeyCode= xkb->max_key_code;
- len= XkbSizeKeyTypes(xkb,rep);
- len+= XkbSizeKeySyms(xkb,rep);
- len+= XkbSizeKeyActions(xkb,rep);
- len+= XkbSizeKeyBehaviors(xkb,rep);
- len+= XkbSizeVirtualMods(xkb,rep);
- len+= XkbSizeExplicit(xkb,rep);
- len+= XkbSizeModifierMap(xkb,rep);
- len+= XkbSizeVirtualModMap(xkb,rep);
- rep->length+= (len/4);
- return Success;
-}
-
-static int
-XkbSendMap(ClientPtr client,XkbDescPtr xkb,xkbGetMapReply *rep)
-{
-unsigned i,len;
-char *desc,*start;
-
- len= (rep->length*4)-(SIZEOF(xkbGetMapReply)-SIZEOF(xGenericReply));
- start= desc= calloc(1, len);
- if (!start)
- return BadAlloc;
- if ( rep->nTypes>0 )
- desc = XkbWriteKeyTypes(xkb,rep,desc,client);
- if ( rep->nKeySyms>0 )
- desc = XkbWriteKeySyms(xkb,rep,desc,client);
- if ( rep->nKeyActs>0 )
- desc = XkbWriteKeyActions(xkb,rep,desc,client);
- if ( rep->totalKeyBehaviors>0 )
- desc = XkbWriteKeyBehaviors(xkb,rep,desc,client);
- if ( rep->virtualMods ) {
- register int sz,bit;
- for (i=sz=0,bit=1;i<XkbNumVirtualMods;i++,bit<<=1) {
- if (rep->virtualMods&bit) {
- desc[sz++]= xkb->server->vmods[i];
- }
- }
- desc+= XkbPaddedSize(sz);
- }
- if ( rep->totalKeyExplicit>0 )
- desc= XkbWriteExplicit(xkb,rep,desc,client);
- if ( rep->totalModMapKeys>0 )
- desc= XkbWriteModifierMap(xkb,rep,desc,client);
- if ( rep->totalVModMapKeys>0 )
- desc= XkbWriteVirtualModMap(xkb,rep,desc,client);
- if ((desc-start)!=(len)) {
- ErrorF("[xkb] BOGUS LENGTH in write keyboard desc, expected %d, got %ld\n",
- len, (unsigned long)(desc-start));
- }
- if (client->swapped) {
- register int n;
- swaps(&rep->sequenceNumber,n);
- swapl(&rep->length,n);
- swaps(&rep->present,n);
- swaps(&rep->totalSyms,n);
- swaps(&rep->totalActs,n);
- }
- WriteToClient(client, (i=SIZEOF(xkbGetMapReply)), (char *)rep);
- WriteToClient(client, len, start);
- free((char *)start);
- return Success;
-}
-
-int
-ProcXkbGetMap(ClientPtr client)
-{
- DeviceIntPtr dev;
- xkbGetMapReply rep;
- XkbDescRec *xkb;
- int n,status;
-
- REQUEST(xkbGetMapReq);
- REQUEST_SIZE_MATCH(xkbGetMapReq);
-
- if (!(client->xkbClientFlags&_XkbClientInitialized))
- return BadAccess;
-
- CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
- CHK_MASK_OVERLAP(0x01,stuff->full,stuff->partial);
- CHK_MASK_LEGAL(0x02,stuff->full,XkbAllMapComponentsMask);
- CHK_MASK_LEGAL(0x03,stuff->partial,XkbAllMapComponentsMask);
-
- xkb= dev->key->xkbInfo->desc;
- memset(&rep, 0, sizeof(xkbGetMapReply));
- rep.type= X_Reply;
- rep.sequenceNumber= client->sequence;
- rep.length = (SIZEOF(xkbGetMapReply)-SIZEOF(xGenericReply))>>2;
- rep.deviceID = dev->id;
- rep.present = stuff->partial|stuff->full;
- rep.minKeyCode = xkb->min_key_code;
- rep.maxKeyCode = xkb->max_key_code;
- if ( stuff->full&XkbKeyTypesMask ) {
- rep.firstType = 0;
- rep.nTypes = xkb->map->num_types;
- }
- else if (stuff->partial&XkbKeyTypesMask) {
- if (((unsigned)stuff->firstType+stuff->nTypes)>xkb->map->num_types) {
- client->errorValue = _XkbErrCode4(0x04,xkb->map->num_types,
- stuff->firstType,stuff->nTypes);
- return BadValue;
- }
- rep.firstType = stuff->firstType;
- rep.nTypes = stuff->nTypes;
- }
- else rep.nTypes = 0;
- rep.totalTypes = xkb->map->num_types;
-
- n= XkbNumKeys(xkb);
- if ( stuff->full&XkbKeySymsMask ) {
- rep.firstKeySym = xkb->min_key_code;
- rep.nKeySyms = n;
- }
- else if (stuff->partial&XkbKeySymsMask) {
- CHK_KEY_RANGE(0x05,stuff->firstKeySym,stuff->nKeySyms,xkb);
- rep.firstKeySym = stuff->firstKeySym;
- rep.nKeySyms = stuff->nKeySyms;
- }
- else rep.nKeySyms = 0;
- rep.totalSyms= 0;
-
- if ( stuff->full&XkbKeyActionsMask ) {
- rep.firstKeyAct= xkb->min_key_code;
- rep.nKeyActs= n;
- }
- else if (stuff->partial&XkbKeyActionsMask) {
- CHK_KEY_RANGE(0x07,stuff->firstKeyAct,stuff->nKeyActs,xkb);
- rep.firstKeyAct= stuff->firstKeyAct;
- rep.nKeyActs= stuff->nKeyActs;
- }
- else rep.nKeyActs= 0;
- rep.totalActs= 0;
-
- if ( stuff->full&XkbKeyBehaviorsMask ) {
- rep.firstKeyBehavior = xkb->min_key_code;
- rep.nKeyBehaviors = n;
- }
- else if (stuff->partial&XkbKeyBehaviorsMask) {
- CHK_KEY_RANGE(0x09,stuff->firstKeyBehavior,stuff->nKeyBehaviors,xkb);
- rep.firstKeyBehavior= stuff->firstKeyBehavior;
- rep.nKeyBehaviors= stuff->nKeyBehaviors;
- }
- else rep.nKeyBehaviors = 0;
- rep.totalKeyBehaviors= 0;
-
- if (stuff->full&XkbVirtualModsMask)
- rep.virtualMods= ~0;
- else if (stuff->partial&XkbVirtualModsMask)
- rep.virtualMods= stuff->virtualMods;
-
- if (stuff->full&XkbExplicitComponentsMask) {
- rep.firstKeyExplicit= xkb->min_key_code;
- rep.nKeyExplicit= n;
- }
- else if (stuff->partial&XkbExplicitComponentsMask) {
- CHK_KEY_RANGE(0x0B,stuff->firstKeyExplicit,stuff->nKeyExplicit,xkb);
- rep.firstKeyExplicit= stuff->firstKeyExplicit;
- rep.nKeyExplicit= stuff->nKeyExplicit;
- }
- else rep.nKeyExplicit = 0;
- rep.totalKeyExplicit= 0;
-
- if (stuff->full&XkbModifierMapMask) {
- rep.firstModMapKey= xkb->min_key_code;
- rep.nModMapKeys= n;
- }
- else if (stuff->partial&XkbModifierMapMask) {
- CHK_KEY_RANGE(0x0D,stuff->firstModMapKey,stuff->nModMapKeys,xkb);
- rep.firstModMapKey= stuff->firstModMapKey;
- rep.nModMapKeys= stuff->nModMapKeys;
- }
- else rep.nModMapKeys = 0;
- rep.totalModMapKeys= 0;
-
- if (stuff->full&XkbVirtualModMapMask) {
- rep.firstVModMapKey= xkb->min_key_code;
- rep.nVModMapKeys= n;
- }
- else if (stuff->partial&XkbVirtualModMapMask) {
- CHK_KEY_RANGE(0x0F,stuff->firstVModMapKey,stuff->nVModMapKeys,xkb);
- rep.firstVModMapKey= stuff->firstVModMapKey;
- rep.nVModMapKeys= stuff->nVModMapKeys;
- }
- else rep.nVModMapKeys = 0;
- rep.totalVModMapKeys= 0;
-
- if ((status=XkbComputeGetMapReplySize(xkb,&rep))!=Success)
- return status;
- return XkbSendMap(client,xkb,&rep);
-}
-
-/***====================================================================***/
-
-static int
-CheckKeyTypes( ClientPtr client,
- XkbDescPtr xkb,
- xkbSetMapReq * req,
- xkbKeyTypeWireDesc **wireRtrn,
- int * nMapsRtrn,
- CARD8 * mapWidthRtrn)
-{
-unsigned nMaps;
-register unsigned i,n;
-register CARD8 * map;
-register xkbKeyTypeWireDesc *wire = *wireRtrn;
-
- if (req->firstType>((unsigned)xkb->map->num_types)) {
- *nMapsRtrn = _XkbErrCode3(0x01,req->firstType,xkb->map->num_types);
- return 0;
- }
- if (req->flags&XkbSetMapResizeTypes) {
- nMaps = req->firstType+req->nTypes;
- if (nMaps<XkbNumRequiredTypes) { /* canonical types must be there */
- *nMapsRtrn= _XkbErrCode4(0x02,req->firstType,req->nTypes,4);
- return 0;
- }
- }
- else if (req->present&XkbKeyTypesMask) {
- nMaps = xkb->map->num_types;
- if ((req->firstType+req->nTypes)>nMaps) {
- *nMapsRtrn = req->firstType+req->nTypes;
- return 0;
- }
- }
- else {
- *nMapsRtrn = xkb->map->num_types;
- for (i=0;i<xkb->map->num_types;i++) {
- mapWidthRtrn[i] = xkb->map->types[i].num_levels;
- }
- return 1;
- }
-
- for (i=0;i<req->firstType;i++) {
- mapWidthRtrn[i] = xkb->map->types[i].num_levels;
- }
- for (i=0;i<req->nTypes;i++) {
- unsigned width;
- if (client->swapped) {
- register int s;
- swaps(&wire->virtualMods,s);
- }
- n= i+req->firstType;
- width= wire->numLevels;
- if (width<1) {
- *nMapsRtrn= _XkbErrCode3(0x04,n,width);
- return 0;
- }
- else if ((n==XkbOneLevelIndex)&&(width!=1)) { /* must be width 1 */
- *nMapsRtrn= _XkbErrCode3(0x05,n,width);
- return 0;
- }
- else if ((width!=2)&&
- ((n==XkbTwoLevelIndex)||(n==XkbKeypadIndex)||
- (n==XkbAlphabeticIndex))) {
- /* TWO_LEVEL, ALPHABETIC and KEYPAD must be width 2 */
- *nMapsRtrn= _XkbErrCode3(0x05,n,width);
- return 0;
- }
- if (wire->nMapEntries>0) {
- xkbKTSetMapEntryWireDesc * mapWire;
- xkbModsWireDesc * preWire;
- mapWire= (xkbKTSetMapEntryWireDesc *)&wire[1];
- preWire= (xkbModsWireDesc *)&mapWire[wire->nMapEntries];
- for (n=0;n<wire->nMapEntries;n++) {
- if (client->swapped) {
- register int s;
- swaps(&mapWire[n].virtualMods,s);
- }
- if (mapWire[n].realMods&(~wire->realMods)) {
- *nMapsRtrn= _XkbErrCode4(0x06,n,mapWire[n].realMods,
- wire->realMods);
- return 0;
- }
- if (mapWire[n].virtualMods&(~wire->virtualMods)) {
- *nMapsRtrn= _XkbErrCode3(0x07,n,mapWire[n].virtualMods);
- return 0;
- }
- if (mapWire[n].level>=wire->numLevels) {
- *nMapsRtrn= _XkbErrCode4(0x08,n,wire->numLevels,
- mapWire[n].level);
- return 0;
- }
- if (wire->preserve) {
- if (client->swapped) {
- register int s;
- swaps(&preWire[n].virtualMods,s);
- }
- if (preWire[n].realMods&(~mapWire[n].realMods)) {
- *nMapsRtrn= _XkbErrCode4(0x09,n,preWire[n].realMods,
- mapWire[n].realMods);
- return 0;
- }
- if (preWire[n].virtualMods&(~mapWire[n].virtualMods)) {
- *nMapsRtrn=_XkbErrCode3(0x0a,n,preWire[n].virtualMods);
- return 0;
- }
- }
- }
- if (wire->preserve)
- map= (CARD8 *)&preWire[wire->nMapEntries];
- else map= (CARD8 *)&mapWire[wire->nMapEntries];
- }
- else map= (CARD8 *)&wire[1];
- mapWidthRtrn[i+req->firstType] = wire->numLevels;
- wire= (xkbKeyTypeWireDesc *)map;
- }
- for (i=req->firstType+req->nTypes;i<nMaps;i++) {
- mapWidthRtrn[i] = xkb->map->types[i].num_levels;
- }
- *nMapsRtrn = nMaps;
- *wireRtrn = wire;
- return 1;
-}
-
-static int
-CheckKeySyms( ClientPtr client,
- XkbDescPtr xkb,
- xkbSetMapReq * req,
- int nTypes,
- CARD8 * mapWidths,
- CARD16 * symsPerKey,
- xkbSymMapWireDesc ** wireRtrn,
- int * errorRtrn)
-{
-register unsigned i;
-XkbSymMapPtr map;
-xkbSymMapWireDesc* wire = *wireRtrn;
-
- if (!(XkbKeySymsMask&req->present))
- return 1;
- CHK_REQ_KEY_RANGE2(0x11,req->firstKeySym,req->nKeySyms,req,(*errorRtrn),0);
- for (i=0;i<req->nKeySyms;i++) {
- KeySym *pSyms;
- register unsigned nG;
- if (client->swapped) {
- swaps(&wire->nSyms,nG);
- }
- nG = XkbNumGroups(wire->groupInfo);
- if (nG>XkbNumKbdGroups) {
- *errorRtrn = _XkbErrCode3(0x14,i+req->firstKeySym,nG);
- return 0;
- }
- if (nG>0) {
- register int g,w;
- for (g=w=0;g<nG;g++) {
- if (wire->ktIndex[g]>=(unsigned)nTypes) {
- *errorRtrn= _XkbErrCode4(0x15,i+req->firstKeySym,g,
- wire->ktIndex[g]);
- return 0;
- }
- if (mapWidths[wire->ktIndex[g]]>w)
- w= mapWidths[wire->ktIndex[g]];
- }
- if (wire->width!=w) {
- *errorRtrn= _XkbErrCode3(0x16,i+req->firstKeySym,wire->width);
- return 0;
- }
- w*= nG;
- symsPerKey[i+req->firstKeySym] = w;
- if (w!=wire->nSyms) {
- *errorRtrn=_XkbErrCode4(0x16,i+req->firstKeySym,wire->nSyms,w);
- return 0;
- }
- }
- else if (wire->nSyms!=0) {
- *errorRtrn = _XkbErrCode3(0x17,i+req->firstKeySym,wire->nSyms);
- return 0;
- }
- pSyms = (KeySym *)&wire[1];
- wire = (xkbSymMapWireDesc *)&pSyms[wire->nSyms];
- }
-
- map = &xkb->map->key_sym_map[i];
- for (;i<=(unsigned)xkb->max_key_code;i++,map++) {
- register int g,nG,w;
- nG= XkbKeyNumGroups(xkb,i);
- for (w=g=0;g<nG;g++) {
- if (map->kt_index[g]>=(unsigned)nTypes) {
- *errorRtrn = _XkbErrCode4(0x18,i,g,map->kt_index[g]);
- return 0;
- }
- if (mapWidths[map->kt_index[g]]>w)
- w= mapWidths[map->kt_index[g]];
- }
- symsPerKey[i] = w*nG;
- }
- *wireRtrn = wire;
- return 1;
-}
-
-static int
-CheckKeyActions( XkbDescPtr xkb,
- xkbSetMapReq * req,
- int nTypes,
- CARD8 * mapWidths,
- CARD16 * symsPerKey,
- CARD8 ** wireRtrn,
- int * nActsRtrn)
-{
-int nActs;
-CARD8 * wire = *wireRtrn;
-register unsigned i;
-
- if (!(XkbKeyActionsMask&req->present))
- return 1;
- CHK_REQ_KEY_RANGE2(0x21,req->firstKeyAct,req->nKeyActs,req,(*nActsRtrn),0);
- for (nActs=i=0;i<req->nKeyActs;i++) {
- if (wire[0]!=0) {
- if (wire[0]==symsPerKey[i+req->firstKeyAct])
- nActs+= wire[0];
- else {
- *nActsRtrn= _XkbErrCode3(0x23,i+req->firstKeyAct,wire[0]);
- return 0;
- }
- }
- wire++;
- }
- if (req->nKeyActs%4)
- wire+= 4-(req->nKeyActs%4);
- *wireRtrn = (CARD8 *)(((XkbAnyAction *)wire)+nActs);
- *nActsRtrn = nActs;
- return 1;
-}
-
-static int
-CheckKeyBehaviors( XkbDescPtr xkb,
- xkbSetMapReq * req,
- xkbBehaviorWireDesc ** wireRtrn,
- int * errorRtrn)
-{
-register xkbBehaviorWireDesc * wire = *wireRtrn;
-register XkbServerMapPtr server = xkb->server;
-register unsigned i;
-unsigned first,last;
-
- if (((req->present&XkbKeyBehaviorsMask)==0)||(req->nKeyBehaviors<1)) {
- req->present&= ~XkbKeyBehaviorsMask;
- req->nKeyBehaviors= 0;
- return 1;
- }
- first= req->firstKeyBehavior;
- last= req->firstKeyBehavior+req->nKeyBehaviors-1;
- if (first<req->minKeyCode) {
- *errorRtrn = _XkbErrCode3(0x31,first,req->minKeyCode);
- return 0;
- }
- if (last>req->maxKeyCode) {
- *errorRtrn = _XkbErrCode3(0x32,last,req->maxKeyCode);
- return 0;
- }
-
- for (i=0;i<req->totalKeyBehaviors;i++,wire++) {
- if ((wire->key<first)||(wire->key>last)) {
- *errorRtrn = _XkbErrCode4(0x33,first,last,wire->key);
- return 0;
- }
- if ((wire->type&XkbKB_Permanent)&&
- ((server->behaviors[wire->key].type!=wire->type)||
- (server->behaviors[wire->key].data!=wire->data))) {
- *errorRtrn = _XkbErrCode3(0x33,wire->key,wire->type);
- return 0;
- }
- if ((wire->type==XkbKB_RadioGroup)&&
- ((wire->data&(~XkbKB_RGAllowNone))>XkbMaxRadioGroups)) {
- *errorRtrn= _XkbErrCode4(0x34,wire->key,wire->data,
- XkbMaxRadioGroups);
- return 0;
- }
- if ((wire->type==XkbKB_Overlay1)||(wire->type==XkbKB_Overlay2)) {
- CHK_KEY_RANGE2(0x35,wire->key,1,xkb,*errorRtrn,0);
- }
- }
- *wireRtrn = wire;
- return 1;
-}
-
-static int
-CheckVirtualMods( XkbDescRec * xkb,
- xkbSetMapReq * req,
- CARD8 ** wireRtrn,
- int * errorRtrn)
-{
-register CARD8 *wire = *wireRtrn;
-register unsigned i,nMods,bit;
-
- if (((req->present&XkbVirtualModsMask)==0)||(req->virtualMods==0))
- return 1;
- for (i=nMods=0,bit=1;i<XkbNumVirtualMods;i++,bit<<=1) {
- if (req->virtualMods&bit)
- nMods++;
- }
- *wireRtrn= (wire+XkbPaddedSize(nMods));
- return 1;
-}
-
-static int
-CheckKeyExplicit( XkbDescPtr xkb,
- xkbSetMapReq * req,
- CARD8 ** wireRtrn,
- int * errorRtrn)
-{
-register CARD8 * wire = *wireRtrn;
-CARD8 * start;
-register unsigned i;
-int first,last;
-
- if (((req->present&XkbExplicitComponentsMask)==0)||(req->nKeyExplicit<1)) {
- req->present&= ~XkbExplicitComponentsMask;
- req->nKeyExplicit= 0;
- return 1;
- }
- first= req->firstKeyExplicit;
- last= first+req->nKeyExplicit-1;
- if (first<req->minKeyCode) {
- *errorRtrn = _XkbErrCode3(0x51,first,req->minKeyCode);
- return 0;
- }
- if (last>req->maxKeyCode) {
- *errorRtrn = _XkbErrCode3(0x52,last,req->maxKeyCode);
- return 0;
- }
- start= wire;
- for (i=0;i<req->totalKeyExplicit;i++,wire+=2) {
- if ((wire[0]<first)||(wire[0]>last)) {
- *errorRtrn = _XkbErrCode4(0x53,first,last,wire[0]);
- return 0;
- }
- if (wire[1]&(~XkbAllExplicitMask)) {
- *errorRtrn= _XkbErrCode3(0x52,~XkbAllExplicitMask,wire[1]);
- return 0;
- }
- }
- wire+= XkbPaddedSize(wire-start)-(wire-start);
- *wireRtrn= wire;
- return 1;
-}
-
-static int
-CheckModifierMap(XkbDescPtr xkb,xkbSetMapReq *req,CARD8 **wireRtrn,int *errRtrn)
-{
-register CARD8 * wire = *wireRtrn;
-CARD8 * start;
-register unsigned i;
-int first,last;
-
- if (((req->present&XkbModifierMapMask)==0)||(req->nModMapKeys<1)) {
- req->present&= ~XkbModifierMapMask;
- req->nModMapKeys= 0;
- return 1;
- }
- first= req->firstModMapKey;
- last= first+req->nModMapKeys-1;
- if (first<req->minKeyCode) {
- *errRtrn = _XkbErrCode3(0x61,first,req->minKeyCode);
- return 0;
- }
- if (last>req->maxKeyCode) {
- *errRtrn = _XkbErrCode3(0x62,last,req->maxKeyCode);
- return 0;
- }
- start= wire;
- for (i=0;i<req->totalModMapKeys;i++,wire+=2) {
- if ((wire[0]<first)||(wire[0]>last)) {
- *errRtrn = _XkbErrCode4(0x63,first,last,wire[0]);
- return 0;
- }
- }
- wire+= XkbPaddedSize(wire-start)-(wire-start);
- *wireRtrn= wire;
- return 1;
-}
-
-static int
-CheckVirtualModMap( XkbDescPtr xkb,
- xkbSetMapReq *req,
- xkbVModMapWireDesc **wireRtrn,
- int *errRtrn)
-{
-register xkbVModMapWireDesc * wire = *wireRtrn;
-register unsigned i;
-int first,last;
-
- if (((req->present&XkbVirtualModMapMask)==0)||(req->nVModMapKeys<1)) {
- req->present&= ~XkbVirtualModMapMask;
- req->nVModMapKeys= 0;
- return 1;
- }
- first= req->firstVModMapKey;
- last= first+req->nVModMapKeys-1;
- if (first<req->minKeyCode) {
- *errRtrn = _XkbErrCode3(0x71,first,req->minKeyCode);
- return 0;
- }
- if (last>req->maxKeyCode) {
- *errRtrn = _XkbErrCode3(0x72,last,req->maxKeyCode);
- return 0;
- }
- for (i=0;i<req->totalVModMapKeys;i++,wire++) {
- if ((wire->key<first)||(wire->key>last)) {
- *errRtrn = _XkbErrCode4(0x73,first,last,wire->key);
- return 0;
- }
- }
- *wireRtrn= wire;
- return 1;
-}
-
-static char *
-SetKeyTypes( XkbDescPtr xkb,
- xkbSetMapReq * req,
- xkbKeyTypeWireDesc * wire,
- XkbChangesPtr changes)
-{
-register unsigned i;
-unsigned first,last;
-CARD8 *map;
-
- if ((unsigned)(req->firstType+req->nTypes)>xkb->map->size_types) {
- i= req->firstType+req->nTypes;
- if (XkbAllocClientMap(xkb,XkbKeyTypesMask,i)!=Success) {
- return NULL;
- }
- }
- if ((unsigned)(req->firstType+req->nTypes)>xkb->map->num_types)
- xkb->map->num_types= req->firstType+req->nTypes;
-
- for (i=0;i<req->nTypes;i++) {
- XkbKeyTypePtr pOld;
- register unsigned n;
-
- if (XkbResizeKeyType(xkb,i+req->firstType,wire->nMapEntries,
- wire->preserve,wire->numLevels)!=Success) {
- return NULL;
- }
- pOld = &xkb->map->types[i+req->firstType];
- map = (CARD8 *)&wire[1];
-
- pOld->mods.real_mods = wire->realMods;
- pOld->mods.vmods= wire->virtualMods;
- pOld->num_levels = wire->numLevels;
- pOld->map_count= wire->nMapEntries;
-
- pOld->mods.mask= pOld->mods.real_mods|
- XkbMaskForVMask(xkb,pOld->mods.vmods);
-
- if (wire->nMapEntries) {
- xkbKTSetMapEntryWireDesc *mapWire;
- xkbModsWireDesc *preWire;
- unsigned tmp;
- mapWire= (xkbKTSetMapEntryWireDesc *)map;
- preWire= (xkbModsWireDesc *)&mapWire[wire->nMapEntries];
- for (n=0;n<wire->nMapEntries;n++) {
- pOld->map[n].active= 1;
- pOld->map[n].mods.mask= mapWire[n].realMods;
- pOld->map[n].mods.real_mods= mapWire[n].realMods;
- pOld->map[n].mods.vmods= mapWire[n].virtualMods;
- pOld->map[n].level= mapWire[n].level;
- if (mapWire[n].virtualMods!=0) {
- tmp= XkbMaskForVMask(xkb,mapWire[n].virtualMods);
- pOld->map[n].active= (tmp!=0);
- pOld->map[n].mods.mask|= tmp;
- }
- if (wire->preserve) {
- pOld->preserve[n].real_mods= preWire[n].realMods;
- pOld->preserve[n].vmods= preWire[n].virtualMods;
- tmp= XkbMaskForVMask(xkb,preWire[n].virtualMods);
- pOld->preserve[n].mask= preWire[n].realMods|tmp;
- }
- }
- if (wire->preserve)
- map= (CARD8 *)&preWire[wire->nMapEntries];
- else map= (CARD8 *)&mapWire[wire->nMapEntries];
- }
- else map= (CARD8 *)&wire[1];
- wire = (xkbKeyTypeWireDesc *)map;
- }
- first= req->firstType;
- last= first+req->nTypes-1; /* last changed type */
- if (changes->map.changed&XkbKeyTypesMask) {
- int oldLast;
- oldLast= changes->map.first_type+changes->map.num_types-1;
- if (changes->map.first_type<first)
- first= changes->map.first_type;
- if (oldLast>last)
- last= oldLast;
- }
- changes->map.changed|= XkbKeyTypesMask;
- changes->map.first_type = first;
- changes->map.num_types = (last-first)+1;
- return (char *)wire;
-}
-
-static char *
-SetKeySyms( ClientPtr client,
- XkbDescPtr xkb,
- xkbSetMapReq * req,
- xkbSymMapWireDesc * wire,
- XkbChangesPtr changes,
- DeviceIntPtr dev)
-{
-register unsigned i,s;
-XkbSymMapPtr oldMap;
-KeySym * newSyms;
-KeySym * pSyms;
-unsigned first,last;
-
- oldMap = &xkb->map->key_sym_map[req->firstKeySym];
- for (i=0;i<req->nKeySyms;i++,oldMap++) {
- pSyms = (KeySym *)&wire[1];
- if (wire->nSyms>0) {
- newSyms = XkbResizeKeySyms(xkb,i+req->firstKeySym,wire->nSyms);
- for (s=0;s<wire->nSyms;s++) {
- newSyms[s]= pSyms[s];
- }
- if (client->swapped) {
- int n;
- for (s=0;s<wire->nSyms;s++) {
- swapl(&newSyms[s],n);
- }
- }
- }
- oldMap->kt_index[0] = wire->ktIndex[0];
- oldMap->kt_index[1] = wire->ktIndex[1];
- oldMap->kt_index[2] = wire->ktIndex[2];
- oldMap->kt_index[3] = wire->ktIndex[3];
- oldMap->group_info = wire->groupInfo;
- oldMap->width = wire->width;
- wire= (xkbSymMapWireDesc *)&pSyms[wire->nSyms];
- }
- first= req->firstKeySym;
- last= first+req->nKeySyms-1;
- if (changes->map.changed&XkbKeySymsMask) {
- int oldLast= (changes->map.first_key_sym+changes->map.num_key_syms-1);
- if (changes->map.first_key_sym<first)
- first= changes->map.first_key_sym;
- if (oldLast>last)
- last= oldLast;
- }
- changes->map.changed|= XkbKeySymsMask;
- changes->map.first_key_sym = first;
- changes->map.num_key_syms = (last-first+1);
-
- s= 0;
- for (i=xkb->min_key_code;i<=xkb->max_key_code;i++) {
- if (XkbKeyNumGroups(xkb,i)>s)
- s= XkbKeyNumGroups(xkb,i);
- }
- if (s!=xkb->ctrls->num_groups) {
- xkbControlsNotify cn;
- XkbControlsRec old;
- cn.keycode= 0;
- cn.eventType= 0;
- cn.requestMajor= XkbReqCode;
- cn.requestMinor= X_kbSetMap;
- old= *xkb->ctrls;
- xkb->ctrls->num_groups= s;
- if (XkbComputeControlsNotify(dev,&old,xkb->ctrls,&cn,FALSE))
- XkbSendControlsNotify(dev,&cn);
- }
- return (char *)wire;
-}
-
-static char *
-SetKeyActions( XkbDescPtr xkb,
- xkbSetMapReq * req,
- CARD8 * wire,
- XkbChangesPtr changes)
-{
-register unsigned i,first,last;
-CARD8 * nActs = wire;
-XkbAction * newActs;
-
- wire+= XkbPaddedSize(req->nKeyActs);
- for (i=0;i<req->nKeyActs;i++) {
- if (nActs[i]==0)
- xkb->server->key_acts[i+req->firstKeyAct]= 0;
- else {
- newActs= XkbResizeKeyActions(xkb,i+req->firstKeyAct,nActs[i]);
- memcpy((char *)newActs,(char *)wire,
- nActs[i]*SIZEOF(xkbActionWireDesc));
- wire+= nActs[i]*SIZEOF(xkbActionWireDesc);
- }
- }
- first= req->firstKeyAct;
- last= (first+req->nKeyActs-1);
- if (changes->map.changed&XkbKeyActionsMask) {
- int oldLast;
- oldLast= changes->map.first_key_act+changes->map.num_key_acts-1;
- if (changes->map.first_key_act<first)
- first= changes->map.first_key_act;
- if (oldLast>last)
- last= oldLast;
- }
- changes->map.changed|= XkbKeyActionsMask;
- changes->map.first_key_act= first;
- changes->map.num_key_acts= (last-first+1);
- return (char *)wire;
-}
-
-static char *
-SetKeyBehaviors( XkbSrvInfoPtr xkbi,
- xkbSetMapReq *req,
- xkbBehaviorWireDesc *wire,
- XkbChangesPtr changes)
-{
-register unsigned i;
-int maxRG = -1;
-XkbDescPtr xkb = xkbi->desc;
-XkbServerMapPtr server = xkb->server;
-unsigned first,last;
-
- first= req->firstKeyBehavior;
- last= req->firstKeyBehavior+req->nKeyBehaviors-1;
- memset(&server->behaviors[first], 0, req->nKeyBehaviors*sizeof(XkbBehavior));
- for (i=0;i<req->totalKeyBehaviors;i++) {
- if ((server->behaviors[wire->key].type&XkbKB_Permanent)==0) {
- server->behaviors[wire->key].type= wire->type;
- server->behaviors[wire->key].data= wire->data;
- if ((wire->type==XkbKB_RadioGroup)&&(((int)wire->data)>maxRG))
- maxRG= wire->data + 1;
- }
- wire++;
- }
-
- if (maxRG>(int)xkbi->nRadioGroups) {
- int sz = maxRG*sizeof(XkbRadioGroupRec);
- if (xkbi->radioGroups)
- xkbi->radioGroups= realloc(xkbi->radioGroups,sz);
- else xkbi->radioGroups= calloc(1, sz);
- if (xkbi->radioGroups) {
- if (xkbi->nRadioGroups)
- memset(&xkbi->radioGroups[xkbi->nRadioGroups], 0,
- (maxRG-xkbi->nRadioGroups)*sizeof(XkbRadioGroupRec));
- xkbi->nRadioGroups= maxRG;
- }
- else xkbi->nRadioGroups= 0;
- /* should compute members here */
- }
- if (changes->map.changed&XkbKeyBehaviorsMask) {
- unsigned oldLast;
- oldLast= changes->map.first_key_behavior+
- changes->map.num_key_behaviors-1;
- if (changes->map.first_key_behavior<req->firstKeyBehavior)
- first= changes->map.first_key_behavior;
- if (oldLast>last)
- last= oldLast;
- }
- changes->map.changed|= XkbKeyBehaviorsMask;
- changes->map.first_key_behavior = first;
- changes->map.num_key_behaviors = (last-first+1);
- return (char *)wire;
-}
-
-static char *
-SetVirtualMods(XkbSrvInfoPtr xkbi,xkbSetMapReq *req,CARD8 *wire,
- XkbChangesPtr changes)
-{
-register int i,bit,nMods;
-XkbServerMapPtr srv = xkbi->desc->server;
-
- if (((req->present&XkbVirtualModsMask)==0)||(req->virtualMods==0))
- return (char *)wire;
- for (i=nMods=0,bit=1;i<XkbNumVirtualMods;i++,bit<<=1) {
- if (req->virtualMods&bit) {
- if (srv->vmods[i]!=wire[nMods]) {
- changes->map.changed|= XkbVirtualModsMask;
- changes->map.vmods|= bit;
- srv->vmods[i]= wire[nMods];
- }
- nMods++;
- }
- }
- return (char *)(wire+XkbPaddedSize(nMods));
-}
-
-static char *
-SetKeyExplicit(XkbSrvInfoPtr xkbi,xkbSetMapReq *req,CARD8 *wire,
- XkbChangesPtr changes)
-{
-register unsigned i,first,last;
-XkbServerMapPtr xkb = xkbi->desc->server;
-CARD8 * start;
-
- start= wire;
- first= req->firstKeyExplicit;
- last= req->firstKeyExplicit+req->nKeyExplicit-1;
- memset(&xkb->explicit[first], 0, req->nKeyExplicit);
- for (i=0;i<req->totalKeyExplicit;i++,wire+= 2) {
- xkb->explicit[wire[0]]= wire[1];
- }
- if (first>0) {
- if (changes->map.changed&XkbExplicitComponentsMask) {
- int oldLast;
- oldLast= changes->map.first_key_explicit+
- changes->map.num_key_explicit-1;
- if (changes->map.first_key_explicit<first)
- first= changes->map.first_key_explicit;
- if (oldLast>last)
- last= oldLast;
- }
- changes->map.first_key_explicit= first;
- changes->map.num_key_explicit= (last-first)+1;
- }
- wire+= XkbPaddedSize(wire-start)-(wire-start);
- return (char *)wire;
-}
-
-static char *
-SetModifierMap( XkbSrvInfoPtr xkbi,
- xkbSetMapReq * req,
- CARD8 * wire,
- XkbChangesPtr changes)
-{
-register unsigned i,first,last;
-XkbClientMapPtr xkb = xkbi->desc->map;
-CARD8 * start;
-
- start= wire;
- first= req->firstModMapKey;
- last= req->firstModMapKey+req->nModMapKeys-1;
- memset(&xkb->modmap[first], 0, req->nModMapKeys);
- for (i=0;i<req->totalModMapKeys;i++,wire+= 2) {
- xkb->modmap[wire[0]]= wire[1];
- }
- if (first>0) {
- if (changes->map.changed&XkbModifierMapMask) {
- int oldLast;
- oldLast= changes->map.first_modmap_key+
- changes->map.num_modmap_keys-1;
- if (changes->map.first_modmap_key<first)
- first= changes->map.first_modmap_key;
- if (oldLast>last)
- last= oldLast;
- }
- changes->map.first_modmap_key= first;
- changes->map.num_modmap_keys= (last-first)+1;
- }
- wire+= XkbPaddedSize(wire-start)-(wire-start);
- return (char *)wire;
-}
-
-static char *
-SetVirtualModMap( XkbSrvInfoPtr xkbi,
- xkbSetMapReq * req,
- xkbVModMapWireDesc * wire,
- XkbChangesPtr changes)
-{
-register unsigned i,first,last;
-XkbServerMapPtr srv = xkbi->desc->server;
-
- first= req->firstVModMapKey;
- last= req->firstVModMapKey+req->nVModMapKeys-1;
- memset(&srv->vmodmap[first], 0, req->nVModMapKeys*sizeof(unsigned short));
- for (i=0;i<req->totalVModMapKeys;i++,wire++) {
- srv->vmodmap[wire->key]= wire->vmods;
- }
- if (first>0) {
- if (changes->map.changed&XkbVirtualModMapMask) {
- int oldLast;
- oldLast= changes->map.first_vmodmap_key+
- changes->map.num_vmodmap_keys-1;
- if (changes->map.first_vmodmap_key<first)
- first= changes->map.first_vmodmap_key;
- if (oldLast>last)
- last= oldLast;
- }
- changes->map.first_vmodmap_key= first;
- changes->map.num_vmodmap_keys= (last-first)+1;
- }
- return (char *)wire;
-}
-
-/**
- * Check if the given request can be applied to the given device but don't
- * actually do anything..
- */
-static int
-_XkbSetMapChecks(ClientPtr client, DeviceIntPtr dev, xkbSetMapReq *req, char* values)
-{
- XkbSrvInfoPtr xkbi;
- XkbDescPtr xkb;
- int error;
- int nTypes = 0, nActions;
- CARD8 mapWidths[XkbMaxLegalKeyCode + 1] = {0};
- CARD16 symsPerKey[XkbMaxLegalKeyCode + 1] = {0};
- XkbSymMapPtr map;
- int i;
-
- xkbi= dev->key->xkbInfo;
- xkb = xkbi->desc;
-
- if ((xkb->min_key_code != req->minKeyCode)||
- (xkb->max_key_code != req->maxKeyCode)) {
- if (client->vMajor!=1) { /* pre 1.0 versions of Xlib have a bug */
- req->minKeyCode= xkb->min_key_code;
- req->maxKeyCode= xkb->max_key_code;
- }
- else {
- if (!XkbIsLegalKeycode(req->minKeyCode)) {
- client->errorValue = _XkbErrCode3(2, req->minKeyCode, req->maxKeyCode);
- return BadValue;
- }
- if (req->minKeyCode > req->maxKeyCode) {
- client->errorValue = _XkbErrCode3(3, req->minKeyCode, req->maxKeyCode);
- return BadMatch;
- }
- }
- }
-
- if ((req->present & XkbKeyTypesMask) &&
- (!CheckKeyTypes(client,xkb,req,(xkbKeyTypeWireDesc **)&values,
- &nTypes,mapWidths))) {
- client->errorValue = nTypes;
- return BadValue;
- }
-
- /* symsPerKey/mapWidths must be filled regardless of client-side flags */
- map = &xkb->map->key_sym_map[xkb->min_key_code];
- for (i=xkb->min_key_code;i<xkb->max_key_code;i++,map++) {
- register int g,ng,w;
- ng= XkbNumGroups(map->group_info);
- for (w=g=0;g<ng;g++) {
- if (map->kt_index[g]>=(unsigned)nTypes) {
- client->errorValue = _XkbErrCode4(0x13,i,g,map->kt_index[g]);
- return 0;
- }
- if (mapWidths[map->kt_index[g]]>w)
- w= mapWidths[map->kt_index[g]];
- }
- symsPerKey[i] = w*ng;
- }
-
- if ((req->present & XkbKeySymsMask) &&
- (!CheckKeySyms(client,xkb,req,nTypes,mapWidths,symsPerKey,
- (xkbSymMapWireDesc **)&values,&error))) {
- client->errorValue = error;
- return BadValue;
- }
-
- if ((req->present & XkbKeyActionsMask) &&
- (!CheckKeyActions(xkb,req,nTypes,mapWidths,symsPerKey,
- (CARD8 **)&values,&nActions))) {
- client->errorValue = nActions;
- return BadValue;
- }
-
- if ((req->present & XkbKeyBehaviorsMask) &&
- (!CheckKeyBehaviors(xkb,req,(xkbBehaviorWireDesc**)&values,&error))) {
- client->errorValue = error;
- return BadValue;
- }
-
- if ((req->present & XkbVirtualModsMask) &&
- (!CheckVirtualMods(xkb,req,(CARD8 **)&values,&error))) {
- client->errorValue= error;
- return BadValue;
- }
- if ((req->present&XkbExplicitComponentsMask) &&
- (!CheckKeyExplicit(xkb,req,(CARD8 **)&values,&error))) {
- client->errorValue= error;
- return BadValue;
- }
- if ((req->present&XkbModifierMapMask) &&
- (!CheckModifierMap(xkb,req,(CARD8 **)&values,&error))) {
- client->errorValue= error;
- return BadValue;
- }
- if ((req->present&XkbVirtualModMapMask) &&
- (!CheckVirtualModMap(xkb,req,(xkbVModMapWireDesc **)&values,&error))) {
- client->errorValue= error;
- return BadValue;
- }
-
- if (((values-((char *)req))/4)!= req->length) {
- ErrorF("[xkb] Internal error! Bad length in XkbSetMap (after check)\n");
- client->errorValue = values-((char *)&req[1]);
- return BadLength;
- }
-
- return Success;
-}
-
-/**
- * Apply the given request on the given device.
- */
-static int
-_XkbSetMap(ClientPtr client, DeviceIntPtr dev, xkbSetMapReq *req, char *values)
-{
- XkbEventCauseRec cause;
- XkbChangesRec change;
- Bool sentNKN;
- XkbSrvInfoPtr xkbi;
- XkbDescPtr xkb;
-
- xkbi= dev->key->xkbInfo;
- xkb = xkbi->desc;
-
- XkbSetCauseXkbReq(&cause,X_kbSetMap,client);
- memset(&change, 0, sizeof(change));
- sentNKN = FALSE;
- if ((xkb->min_key_code!=req->minKeyCode)||
- (xkb->max_key_code!=req->maxKeyCode)) {
- Status status;
- xkbNewKeyboardNotify nkn;
- nkn.deviceID = nkn.oldDeviceID = dev->id;
- nkn.oldMinKeyCode = xkb->min_key_code;
- nkn.oldMaxKeyCode = xkb->max_key_code;
- status= XkbChangeKeycodeRange(xkb, req->minKeyCode,
- req->maxKeyCode, &change);
- if (status != Success)
- return status; /* oh-oh. what about the other keyboards? */
- nkn.minKeyCode = xkb->min_key_code;
- nkn.maxKeyCode = xkb->max_key_code;
- nkn.requestMajor = XkbReqCode;
- nkn.requestMinor = X_kbSetMap;
- nkn.changed = XkbNKN_KeycodesMask;
- XkbSendNewKeyboardNotify(dev,&nkn);
- sentNKN = TRUE;
- }
-
- if (req->present&XkbKeyTypesMask) {
- values = SetKeyTypes(xkb,req,(xkbKeyTypeWireDesc *)values,&change);
- if (!values) goto allocFailure;
- }
- if (req->present&XkbKeySymsMask) {
- values = SetKeySyms(client,xkb,req,(xkbSymMapWireDesc *)values,&change,dev);
- if (!values) goto allocFailure;
- }
- if (req->present&XkbKeyActionsMask) {
- values = SetKeyActions(xkb,req,(CARD8 *)values,&change);
- if (!values) goto allocFailure;
- }
- if (req->present&XkbKeyBehaviorsMask) {
- values= SetKeyBehaviors(xkbi,req,(xkbBehaviorWireDesc *)values,&change);
- if (!values) goto allocFailure;
- }
- if (req->present&XkbVirtualModsMask)
- values= SetVirtualMods(xkbi,req,(CARD8 *)values,&change);
- if (req->present&XkbExplicitComponentsMask)
- values= SetKeyExplicit(xkbi,req,(CARD8 *)values,&change);
- if (req->present&XkbModifierMapMask)
- values= SetModifierMap(xkbi,req,(CARD8 *)values,&change);
- if (req->present&XkbVirtualModMapMask)
- values= SetVirtualModMap(xkbi,req,(xkbVModMapWireDesc *)values,&change);
- if (((values-((char *)req))/4)!=req->length) {
- ErrorF("[xkb] Internal error! Bad length in XkbSetMap (after set)\n");
- client->errorValue = values-((char *)&req[1]);
- return BadLength;
- }
- if (req->flags&XkbSetMapRecomputeActions) {
- KeyCode first,last,firstMM,lastMM;
- if (change.map.num_key_syms>0) {
- first= change.map.first_key_sym;
- last= first+change.map.num_key_syms-1;
- }
- else first= last= 0;
- if (change.map.num_modmap_keys>0) {
- firstMM= change.map.first_modmap_key;
- lastMM= first+change.map.num_modmap_keys-1;
- }
- else firstMM= lastMM= 0;
- if ((last>0) && (lastMM>0)) {
- if (firstMM<first)
- first= firstMM;
- if (lastMM>last)
- last= lastMM;
- }
- else if (lastMM>0) {
- first= firstMM;
- last= lastMM;
- }
- if (last>0) {
- unsigned check= 0;
- XkbUpdateActions(dev,first,(last-first+1),&change,&check,&cause);
- if (check)
- XkbCheckSecondaryEffects(xkbi,check,&change,&cause);
- }
- }
- if (!sentNKN)
- XkbSendNotification(dev,&change,&cause);
-
- return Success;
-allocFailure:
- return BadAlloc;
-}
-
-
-int
-ProcXkbSetMap(ClientPtr client)
-{
- DeviceIntPtr dev;
- char * tmp;
- int rc;
-
- REQUEST(xkbSetMapReq);
- REQUEST_AT_LEAST_SIZE(xkbSetMapReq);
-
- if (!(client->xkbClientFlags&_XkbClientInitialized))
- return BadAccess;
-
- CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess);
- CHK_MASK_LEGAL(0x01,stuff->present,XkbAllMapComponentsMask);
-
- tmp = (char *)&stuff[1];
-
- /* Check if we can to the SetMap on the requested device. If this
- succeeds, do the same thing for all extension devices (if needed).
- If any of them fails, fail. */
- rc = _XkbSetMapChecks(client, dev, stuff, tmp);
-
- if (rc != Success)
- return rc;
-
- if (stuff->deviceSpec == XkbUseCoreKbd)
- {
- DeviceIntPtr other;
- for (other = inputInfo.devices; other; other = other->next)
- {
- if ((other != dev) && other->key && !IsMaster(other) && GetMaster(other, MASTER_KEYBOARD) == dev)
- {
- rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixManageAccess);
- if (rc == Success)
- {
- rc = _XkbSetMapChecks(client, other, stuff, tmp);
- if (rc != Success)
- return rc;
- }
- }
- }
- }
-
- /* We know now that we will succed with the SetMap. In theory anyway. */
- rc = _XkbSetMap(client, dev, stuff, tmp);
- if (rc != Success)
- return rc;
-
- if (stuff->deviceSpec == XkbUseCoreKbd)
- {
- DeviceIntPtr other;
- for (other = inputInfo.devices; other; other = other->next)
- {
- if ((other != dev) && other->key && !IsMaster(other) && GetMaster(other, MASTER_KEYBOARD) == dev)
- {
- rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixManageAccess);
- if (rc == Success)
- _XkbSetMap(client, other, stuff, tmp);
- /* ignore rc. if the SetMap failed although the check above
- reported true there isn't much we can do. we still need to
- set all other devices, hoping that at least they stay in
- sync. */
- }
- }
- }
-
- return Success;
-}
-
-/***====================================================================***/
-
-static Status
-XkbComputeGetCompatMapReplySize( XkbCompatMapPtr compat,
- xkbGetCompatMapReply * rep)
-{
-unsigned size,nGroups;
-
- nGroups= 0;
- if (rep->groups!=0) {
- register int i,bit;
- for (i=0,bit=1;i<XkbNumKbdGroups;i++,bit<<=1) {
- if (rep->groups&bit)
- nGroups++;
- }
- }
- size= nGroups*SIZEOF(xkbModsWireDesc);
- size+= (rep->nSI*SIZEOF(xkbSymInterpretWireDesc));
- rep->length= size/4;
- return Success;
-}
-
-static int
-XkbSendCompatMap( ClientPtr client,
- XkbCompatMapPtr compat,
- xkbGetCompatMapReply * rep)
-{
-char * data;
-int size;
-
- size= rep->length*4;
- if (size>0) {
- data = malloc(size);
- if (data) {
- register unsigned i,bit;
- xkbModsWireDesc * grp;
- XkbSymInterpretPtr sym= &compat->sym_interpret[rep->firstSI];
- xkbSymInterpretWireDesc *wire = (xkbSymInterpretWireDesc *)data;
- for (i=0;i<rep->nSI;i++,sym++,wire++) {
- wire->sym= sym->sym;
- wire->mods= sym->mods;
- wire->match= sym->match;
- wire->virtualMod= sym->virtual_mod;
- wire->flags= sym->flags;
- memcpy((char*)&wire->act,(char*)&sym->act,sz_xkbActionWireDesc);
- if (client->swapped) {
- register int n;
- swapl(&wire->sym,n);
- }
- }
- if (rep->groups) {
- grp = (xkbModsWireDesc *)wire;
- for (i=0,bit=1;i<XkbNumKbdGroups;i++,bit<<=1) {
- if (rep->groups&bit) {
- grp->mask= compat->groups[i].mask;
- grp->realMods= compat->groups[i].real_mods;
- grp->virtualMods= compat->groups[i].vmods;
- if (client->swapped) {
- register int n;
- swaps(&grp->virtualMods,n);
- }
- grp++;
- }
- }
- wire= (xkbSymInterpretWireDesc*)grp;
- }
- }
- else return BadAlloc;
- }
- else data= NULL;
-
- if (client->swapped) {
- register int n;
- swaps(&rep->sequenceNumber,n);
- swapl(&rep->length,n);
- swaps(&rep->firstSI,n);
- swaps(&rep->nSI,n);
- swaps(&rep->nTotalSI,n);
- }
-
- WriteToClient(client, SIZEOF(xkbGetCompatMapReply), (char *)rep);
- if (data) {
- WriteToClient(client, size, data);
- free((char *)data);
- }
- return Success;
-}
-
-int
-ProcXkbGetCompatMap(ClientPtr client)
-{
- xkbGetCompatMapReply rep;
- DeviceIntPtr dev;
- XkbDescPtr xkb;
- XkbCompatMapPtr compat;
-
- REQUEST(xkbGetCompatMapReq);
- REQUEST_SIZE_MATCH(xkbGetCompatMapReq);
-
- if (!(client->xkbClientFlags&_XkbClientInitialized))
- return BadAccess;
-
- CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
-
- xkb = dev->key->xkbInfo->desc;
- compat= xkb->compat;
-
- rep.type = X_Reply;
- rep.deviceID = dev->id;
- rep.sequenceNumber = client->sequence;
- rep.length = 0;
- rep.firstSI = stuff->firstSI;
- rep.nSI = stuff->nSI;
- if (stuff->getAllSI) {
- rep.firstSI = 0;
- rep.nSI = compat->num_si;
- }
- else if ((((unsigned)stuff->nSI)>0)&&
- ((unsigned)(stuff->firstSI+stuff->nSI-1)>=compat->num_si)) {
- client->errorValue = _XkbErrCode2(0x05,compat->num_si);
- return BadValue;
- }
- rep.nTotalSI = compat->num_si;
- rep.groups= stuff->groups;
- XkbComputeGetCompatMapReplySize(compat,&rep);
- return XkbSendCompatMap(client,compat,&rep);
-}
-
-/**
- * Apply the given request on the given device.
- * If dryRun is TRUE, then value checks are performed, but the device isn't
- * modified.
- */
-static int
-_XkbSetCompatMap(ClientPtr client, DeviceIntPtr dev,
- xkbSetCompatMapReq *req, char* data, BOOL dryRun)
-{
- XkbSrvInfoPtr xkbi;
- XkbDescPtr xkb;
- XkbCompatMapPtr compat;
- int nGroups;
- unsigned i,bit;
-
- xkbi = dev->key->xkbInfo;
- xkb = xkbi->desc;
- compat = xkb->compat;
-
- if ((req->nSI>0)||(req->truncateSI)) {
- xkbSymInterpretWireDesc *wire;
- if (req->firstSI>compat->num_si) {
- client->errorValue = _XkbErrCode2(0x02,compat->num_si);
- return BadValue;
- }
- wire= (xkbSymInterpretWireDesc *)data;
- wire+= req->nSI;
- data = (char *)wire;
- }
-
- nGroups= 0;
- if (req->groups!=0) {
- for (i=0,bit=1;i<XkbNumKbdGroups;i++,bit<<=1) {
- if ( req->groups&bit )
- nGroups++;
- }
- }
- data+= nGroups*SIZEOF(xkbModsWireDesc);
- if (((data-((char *)req))/4)!=req->length) {
- return BadLength;
- }
-
- /* Done all the checks we can do */
- if (dryRun)
- return Success;
-
- data = (char *)&req[1];
- if (req->nSI>0) {
- xkbSymInterpretWireDesc *wire = (xkbSymInterpretWireDesc *)data;
- XkbSymInterpretPtr sym;
- if ((unsigned)(req->firstSI+req->nSI)>compat->num_si) {
- compat->num_si= req->firstSI+req->nSI;
- compat->sym_interpret= realloc(compat->sym_interpret,
- compat->num_si * sizeof(XkbSymInterpretRec));
- if (!compat->sym_interpret) {
- compat->num_si= 0;
- return BadAlloc;
- }
- }
- else if (req->truncateSI) {
- compat->num_si = req->firstSI+req->nSI;
- }
- sym = &compat->sym_interpret[req->firstSI];
- for (i=0;i<req->nSI;i++,wire++,sym++) {
- if (client->swapped) {
- int n;
- swapl(&wire->sym,n);
- }
- sym->sym= wire->sym;
- sym->mods= wire->mods;
- sym->match= wire->match;
- sym->flags= wire->flags;
- sym->virtual_mod= wire->virtualMod;
- memcpy((char *)&sym->act,(char *)&wire->act,
- SIZEOF(xkbActionWireDesc));
- }
- data = (char *)wire;
- }
- else if (req->truncateSI) {
- compat->num_si = req->firstSI;
- }
-
- if (req->groups!=0) {
- unsigned i, bit;
- xkbModsWireDesc *wire = (xkbModsWireDesc *)data;
- for (i = 0, bit = 1; i < XkbNumKbdGroups; i++, bit <<= 1) {
- if (req->groups & bit) {
- if (client->swapped) {
- int n;
- swaps(&wire->virtualMods,n);
- }
- compat->groups[i].mask= wire->realMods;
- compat->groups[i].real_mods= wire->realMods;
- compat->groups[i].vmods= wire->virtualMods;
- if (wire->virtualMods!=0) {
- unsigned tmp;
- tmp= XkbMaskForVMask(xkb,wire->virtualMods);
- compat->groups[i].mask|= tmp;
- }
- data+= SIZEOF(xkbModsWireDesc);
- wire= (xkbModsWireDesc *)data;
- }
- }
- }
- i= XkbPaddedSize((data-((char *)req)));
- if ((i/4)!=req->length) {
- ErrorF("[xkb] Internal length error on read in _XkbSetCompatMap\n");
- return BadLength;
- }
-
- if (dev->xkb_interest) {
- xkbCompatMapNotify ev;
- ev.deviceID = dev->id;
- ev.changedGroups = req->groups;
- ev.firstSI = req->firstSI;
- ev.nSI = req->nSI;
- ev.nTotalSI = compat->num_si;
- XkbSendCompatMapNotify(dev,&ev);
- }
-
- if (req->recomputeActions) {
- XkbChangesRec change;
- unsigned check;
- XkbEventCauseRec cause;
-
- XkbSetCauseXkbReq(&cause,X_kbSetCompatMap,client);
- memset(&change, 0, sizeof(XkbChangesRec));
- XkbUpdateActions(dev,xkb->min_key_code,XkbNumKeys(xkb),&change,&check,
- &cause);
- if (check)
- XkbCheckSecondaryEffects(xkbi,check,&change,&cause);
- XkbSendNotification(dev,&change,&cause);
- }
- return Success;
-}
-
-int
-ProcXkbSetCompatMap(ClientPtr client)
-{
- DeviceIntPtr dev;
- char *data;
- int rc;
-
- REQUEST(xkbSetCompatMapReq);
- REQUEST_AT_LEAST_SIZE(xkbSetCompatMapReq);
-
- if (!(client->xkbClientFlags&_XkbClientInitialized))
- return BadAccess;
-
- CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess);
-
- data = (char *)&stuff[1];
-
- /* check first using a dry-run */
- rc = _XkbSetCompatMap(client, dev, stuff, data, TRUE);
- if (rc != Success)
- return rc;
- if (stuff->deviceSpec == XkbUseCoreKbd)
- {
- DeviceIntPtr other;
- for (other = inputInfo.devices; other; other = other->next)
- {
- if ((other != dev) && other->key && !IsMaster(other) && GetMaster(other, MASTER_KEYBOARD) == dev)
- {
- rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixManageAccess);
- if (rc == Success)
- {
- /* dry-run */
- rc = _XkbSetCompatMap(client, other, stuff, data, TRUE);
- if (rc != Success)
- return rc;
- }
- }
- }
- }
-
- /* Yay, the dry-runs succeed. Let's apply */
- rc = _XkbSetCompatMap(client, dev, stuff, data, FALSE);
- if (rc != Success)
- return rc;
- if (stuff->deviceSpec == XkbUseCoreKbd)
- {
- DeviceIntPtr other;
- for (other = inputInfo.devices; other; other = other->next)
- {
- if ((other != dev) && other->key && !IsMaster(other) && GetMaster(other, MASTER_KEYBOARD) == dev)
- {
- rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixManageAccess);
- if (rc == Success)
- {
- rc = _XkbSetCompatMap(client, other, stuff, data, FALSE);
- if (rc != Success)
- return rc;
- }
- }
- }
- }
-
- return Success;
-}
-
-/***====================================================================***/
-
-int
-ProcXkbGetIndicatorState(ClientPtr client)
-{
- xkbGetIndicatorStateReply rep;
- XkbSrvLedInfoPtr sli;
- DeviceIntPtr dev;
- register int i;
-
- REQUEST(xkbGetIndicatorStateReq);
- REQUEST_SIZE_MATCH(xkbGetIndicatorStateReq);
-
- if (!(client->xkbClientFlags&_XkbClientInitialized))
- return BadAccess;
-
- CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixReadAccess);
-
- sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId,
- XkbXI_IndicatorStateMask);
- if (!sli)
- return BadAlloc;
-
- rep.type = X_Reply;
- rep.sequenceNumber = client->sequence;
- rep.length = 0;
- rep.deviceID = dev->id;
- rep.state = sli->effectiveState;
-
- if (client->swapped) {
- swaps(&rep.sequenceNumber,i);
- swapl(&rep.state,i);
- }
- WriteToClient(client, SIZEOF(xkbGetIndicatorStateReply), (char *)&rep);
- return Success;
-}
-
-/***====================================================================***/
-
-static Status
-XkbComputeGetIndicatorMapReplySize(
- XkbIndicatorPtr indicators,
- xkbGetIndicatorMapReply *rep)
-{
-register int i,bit;
-int nIndicators;
-
- rep->realIndicators = indicators->phys_indicators;
- for (i=nIndicators=0,bit=1;i<XkbNumIndicators;i++,bit<<=1) {
- if (rep->which&bit)
- nIndicators++;
- }
- rep->length = (nIndicators*SIZEOF(xkbIndicatorMapWireDesc))/4;
- return Success;
-}
-
-static int
-XkbSendIndicatorMap( ClientPtr client,
- XkbIndicatorPtr indicators,
- xkbGetIndicatorMapReply * rep)
-{
-int length;
-CARD8 * map;
-register int i;
-register unsigned bit;
-
- length = rep->length*4;
- if (length>0) {
- CARD8 *to;
- to= map= malloc(length);
- if (map) {
- xkbIndicatorMapWireDesc *wire = (xkbIndicatorMapWireDesc *)to;
- for (i=0,bit=1;i<XkbNumIndicators;i++,bit<<=1) {
- if (rep->which&bit) {
- wire->flags= indicators->maps[i].flags;
- wire->whichGroups= indicators->maps[i].which_groups;
- wire->groups= indicators->maps[i].groups;
- wire->whichMods= indicators->maps[i].which_mods;
- wire->mods= indicators->maps[i].mods.mask;
- wire->realMods= indicators->maps[i].mods.real_mods;
- wire->virtualMods= indicators->maps[i].mods.vmods;
- wire->ctrls= indicators->maps[i].ctrls;
- if (client->swapped) {
- register int n;
- swaps(&wire->virtualMods,n);
- swapl(&wire->ctrls,n);
- }
- wire++;
- }
- }
- to = (CARD8 *)wire;
- if ((to-map)!=length) {
- client->errorValue = _XkbErrCode2(0xff,length);
- free(map);
- return BadLength;
- }
- }
- else return BadAlloc;
- }
- else map = NULL;
- if (client->swapped) {
- swaps(&rep->sequenceNumber,i);
- swapl(&rep->length,i);
- swapl(&rep->which,i);
- swapl(&rep->realIndicators,i);
- }
- WriteToClient(client, SIZEOF(xkbGetIndicatorMapReply), (char *)rep);
- if (map) {
- WriteToClient(client, length, (char *)map);
- free((char *)map);
- }
- return Success;
-}
-
-int
-ProcXkbGetIndicatorMap(ClientPtr client)
-{
-xkbGetIndicatorMapReply rep;
-DeviceIntPtr dev;
-XkbDescPtr xkb;
-XkbIndicatorPtr leds;
-
- REQUEST(xkbGetIndicatorMapReq);
- REQUEST_SIZE_MATCH(xkbGetIndicatorMapReq);
-
- if (!(client->xkbClientFlags&_XkbClientInitialized))
- return BadAccess;
-
- CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
-
- xkb= dev->key->xkbInfo->desc;
- leds= xkb->indicators;
-
- rep.type = X_Reply;
- rep.sequenceNumber = client->sequence;
- rep.length = 0;
- rep.deviceID = dev->id;
- rep.which = stuff->which;
- XkbComputeGetIndicatorMapReplySize(leds,&rep);
- return XkbSendIndicatorMap(client,leds,&rep);
-}
-
-/**
- * Apply the given map to the given device. Which specifies which components
- * to apply.
- */
-static int
-_XkbSetIndicatorMap(ClientPtr client, DeviceIntPtr dev,
- int which, xkbIndicatorMapWireDesc *desc)
-{
- XkbSrvInfoPtr xkbi;
- XkbSrvLedInfoPtr sli;
- XkbEventCauseRec cause;
- int i, bit;
-
- xkbi = dev->key->xkbInfo;
-
- sli= XkbFindSrvLedInfo(dev, XkbDfltXIClass, XkbDfltXIId,
- XkbXI_IndicatorMapsMask);
- if (!sli)
- return BadAlloc;
-
- for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) {
- if (which & bit) {
- sli->maps[i].flags = desc->flags;
- sli->maps[i].which_groups = desc->whichGroups;
- sli->maps[i].groups = desc->groups;
- sli->maps[i].which_mods = desc->whichMods;
- sli->maps[i].mods.mask = desc->mods;
- sli->maps[i].mods.real_mods = desc->mods;
- sli->maps[i].mods.vmods= desc->virtualMods;
- sli->maps[i].ctrls = desc->ctrls;
- if (desc->virtualMods!=0) {
- unsigned tmp;
- tmp= XkbMaskForVMask(xkbi->desc,desc->virtualMods);
- sli->maps[i].mods.mask= desc->mods|tmp;
- }
- desc++;
- }
- }
-
- XkbSetCauseXkbReq(&cause,X_kbSetIndicatorMap,client);
- XkbApplyLedMapChanges(dev,sli,which,NULL,NULL,&cause);
-
- return Success;
-}
-
-int
-ProcXkbSetIndicatorMap(ClientPtr client)
-{
- int i, bit;
- int nIndicators;
- DeviceIntPtr dev;
- xkbIndicatorMapWireDesc *from;
- int rc;
-
- REQUEST(xkbSetIndicatorMapReq);
- REQUEST_AT_LEAST_SIZE(xkbSetIndicatorMapReq);
-
- if (!(client->xkbClientFlags&_XkbClientInitialized))
- return BadAccess;
-
- CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixSetAttrAccess);
-
- if (stuff->which==0)
- return Success;
-
- for (nIndicators=i=0,bit=1;i<XkbNumIndicators;i++,bit<<=1) {
- if (stuff->which&bit)
- nIndicators++;
- }
- if (stuff->length!=((SIZEOF(xkbSetIndicatorMapReq)+
- (nIndicators*SIZEOF(xkbIndicatorMapWireDesc)))/4)) {
- return BadLength;
- }
-
- from = (xkbIndicatorMapWireDesc *)&stuff[1];
- for (i=0,bit=1;i<XkbNumIndicators;i++,bit<<=1) {
- if (stuff->which&bit) {
- if (client->swapped) {
- int n;
- swaps(&from->virtualMods,n);
- swapl(&from->ctrls,n);
- }
- CHK_MASK_LEGAL(i,from->whichGroups,XkbIM_UseAnyGroup);
- CHK_MASK_LEGAL(i,from->whichMods,XkbIM_UseAnyMods);
- from++;
- }
- }
-
- from = (xkbIndicatorMapWireDesc *)&stuff[1];
- rc = _XkbSetIndicatorMap(client, dev, stuff->which, from);
- if (rc != Success)
- return rc;
-
- if (stuff->deviceSpec == XkbUseCoreKbd)
- {
- DeviceIntPtr other;
- for (other = inputInfo.devices; other; other = other->next)
- {
- if ((other != dev) && other->key && !IsMaster(other) && GetMaster(other, MASTER_KEYBOARD) == dev)
- {
- rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixSetAttrAccess);
- if (rc == Success)
- _XkbSetIndicatorMap(client, other, stuff->which, from);
- }
- }
- }
-
- return Success;
-}
-
-/***====================================================================***/
-
-int
-ProcXkbGetNamedIndicator(ClientPtr client)
-{
- DeviceIntPtr dev;
- xkbGetNamedIndicatorReply rep;
- register int i = 0;
- XkbSrvLedInfoPtr sli;
- XkbIndicatorMapPtr map = NULL;
-
- REQUEST(xkbGetNamedIndicatorReq);
- REQUEST_SIZE_MATCH(xkbGetNamedIndicatorReq);
-
- if (!(client->xkbClientFlags&_XkbClientInitialized))
- return BadAccess;
-
- CHK_LED_DEVICE(dev, stuff->deviceSpec, client, DixReadAccess);
- CHK_ATOM_ONLY(stuff->indicator);
-
- sli= XkbFindSrvLedInfo(dev,stuff->ledClass,stuff->ledID,0);
- if (!sli)
- return BadAlloc;
-
- i= 0;
- map= NULL;
- if ((sli->names)&&(sli->maps)) {
- for (i=0;i<XkbNumIndicators;i++) {
- if (stuff->indicator==sli->names[i]) {
- map= &sli->maps[i];
- break;
- }
- }
- }
-
- rep.type= X_Reply;
- rep.length = 0;
- rep.sequenceNumber = client->sequence;
- rep.deviceID = dev->id;
- rep.indicator= stuff->indicator;
- if (map!=NULL) {
- rep.found= TRUE;
- rep.on= ((sli->effectiveState&(1<<i))!=0);
- rep.realIndicator= ((sli->physIndicators&(1<<i))!=0);
- rep.ndx= i;
- rep.flags= map->flags;
- rep.whichGroups= map->which_groups;
- rep.groups= map->groups;
- rep.whichMods= map->which_mods;
- rep.mods= map->mods.mask;
- rep.realMods= map->mods.real_mods;
- rep.virtualMods= map->mods.vmods;
- rep.ctrls= map->ctrls;
- rep.supported= TRUE;
- }
- else {
- rep.found= FALSE;
- rep.on= FALSE;
- rep.realIndicator= FALSE;
- rep.ndx= XkbNoIndicator;
- rep.flags= 0;
- rep.whichGroups= 0;
- rep.groups= 0;
- rep.whichMods= 0;
- rep.mods= 0;
- rep.realMods= 0;
- rep.virtualMods= 0;
- rep.ctrls= 0;
- rep.supported= TRUE;
- }
- if ( client->swapped ) {
- register int n;
- swapl(&rep.length,n);
- swaps(&rep.sequenceNumber,n);
- swapl(&rep.indicator,n);
- swaps(&rep.virtualMods,n);
- swapl(&rep.ctrls,n);
- }
-
- WriteToClient(client,SIZEOF(xkbGetNamedIndicatorReply), (char *)&rep);
- return Success;
-}
-
-
-/**
- * Find the IM on the device.
- * Returns the map, or NULL if the map doesn't exist.
- * If the return value is NULL, led_return is undefined. Otherwise, led_return
- * is set to the led index of the map.
- */
-static XkbIndicatorMapPtr
-_XkbFindNamedIndicatorMap(XkbSrvLedInfoPtr sli, Atom indicator,
- int *led_return)
-{
- XkbIndicatorMapPtr map;
-
- /* search for the right indicator */
- map = NULL;
- if (sli->names && sli->maps) {
- int led;
-
- for (led = 0; (led < XkbNumIndicators) && (map == NULL); led++) {
- if (sli->names[led] == indicator) {
- map= &sli->maps[led];
- *led_return = led;
- break;
- }
- }
- }
-
- return map;
-}
-
-/**
- * Creates an indicator map on the device. If dryRun is TRUE, it only checks
- * if creation is possible, but doesn't actually create it.
- */
-static int
-_XkbCreateIndicatorMap(DeviceIntPtr dev, Atom indicator,
- int ledClass, int ledID,
- XkbIndicatorMapPtr *map_return, int *led_return,
- Bool dryRun)
-{
- XkbSrvLedInfoPtr sli;
- XkbIndicatorMapPtr map;
- int led;
-
- sli = XkbFindSrvLedInfo(dev, ledClass, ledID, XkbXI_IndicatorsMask);
- if (!sli)
- return BadAlloc;
-
- map = _XkbFindNamedIndicatorMap(sli, indicator, &led);
-
- if (!map)
- {
- /* find first unused indicator maps and assign the name to it */
- for (led = 0, map = NULL; (led < XkbNumIndicators) && (map == NULL); led++) {
- if ((sli->names) && (sli->maps) && (sli->names[led] == None) &&
- (!XkbIM_InUse(&sli->maps[led])))
- {
- map = &sli->maps[led];
- if (!dryRun)
- sli->names[led] = indicator;
- break;
- }
- }
- }
-
- if (!map)
- return BadAlloc;
-
- *led_return = led;
- *map_return = map;
- return Success;
-}
-
-static int
-_XkbSetNamedIndicator(ClientPtr client, DeviceIntPtr dev,
- xkbSetNamedIndicatorReq *stuff)
-{
- unsigned int extDevReason;
- unsigned int statec, namec, mapc;
- XkbSrvLedInfoPtr sli;
- int led = 0;
- XkbIndicatorMapPtr map;
- DeviceIntPtr kbd;
- XkbEventCauseRec cause;
- xkbExtensionDeviceNotify ed;
- XkbChangesRec changes;
- int rc;
-
- rc = _XkbCreateIndicatorMap(dev, stuff->indicator, stuff->ledClass,
- stuff->ledID, &map, &led, FALSE);
- if (rc != Success || !map) /* oh-oh */
- return rc;
-
- sli = XkbFindSrvLedInfo(dev, stuff->ledClass, stuff->ledID,
- XkbXI_IndicatorsMask);
- if (!sli)
- return BadAlloc;
-
- namec = mapc = statec = 0;
- extDevReason = 0;
-
- namec |= (1<<led);
- sli->namesPresent |= ((stuff->indicator != None) ? (1 << led) : 0);
- extDevReason |= XkbXI_IndicatorNamesMask;
-
- if (stuff->setMap) {
- map->flags = stuff->flags;
- map->which_groups = stuff->whichGroups;
- map->groups = stuff->groups;
- map->which_mods = stuff->whichMods;
- map->mods.mask = stuff->realMods;
- map->mods.real_mods = stuff->realMods;
- map->mods.vmods= stuff->virtualMods;
- map->ctrls = stuff->ctrls;
- mapc|= (1<<led);
- }
-
- if ((stuff->setState) && ((map->flags & XkbIM_NoExplicit) == 0))
- {
- if (stuff->on) sli->explicitState |= (1<<led);
- else sli->explicitState &= ~(1<<led);
- statec |= ((sli->effectiveState ^ sli->explicitState) & (1 << led));
- }
-
- memset((char *)&ed, 0, sizeof(xkbExtensionDeviceNotify));
- memset((char *)&changes, 0, sizeof(XkbChangesRec));
- XkbSetCauseXkbReq(&cause,X_kbSetNamedIndicator,client);
- if (namec)
- XkbApplyLedNameChanges(dev,sli,namec,&ed,&changes,&cause);
- if (mapc)
- XkbApplyLedMapChanges(dev,sli,mapc,&ed,&changes,&cause);
- if (statec)
- XkbApplyLedStateChanges(dev,sli,statec,&ed,&changes,&cause);
-
- kbd = dev;
- if ((sli->flags&XkbSLI_HasOwnState)==0)
- kbd = inputInfo.keyboard;
- XkbFlushLedEvents(dev, kbd, sli, &ed, &changes, &cause);
-
- return Success;
-}
-
-int
-ProcXkbSetNamedIndicator(ClientPtr client)
-{
- int rc;
- DeviceIntPtr dev;
- int led = 0;
- XkbIndicatorMapPtr map;
-
- REQUEST(xkbSetNamedIndicatorReq);
- REQUEST_SIZE_MATCH(xkbSetNamedIndicatorReq);
-
- if (!(client->xkbClientFlags&_XkbClientInitialized))
- return BadAccess;
-
- CHK_LED_DEVICE(dev, stuff->deviceSpec, client, DixSetAttrAccess);
- CHK_ATOM_ONLY(stuff->indicator);
- CHK_MASK_LEGAL(0x10,stuff->whichGroups,XkbIM_UseAnyGroup);
- CHK_MASK_LEGAL(0x11,stuff->whichMods,XkbIM_UseAnyMods);
-
- /* Dry-run for checks */
- rc = _XkbCreateIndicatorMap(dev, stuff->indicator,
- stuff->ledClass, stuff->ledID,
- &map, &led, TRUE);
- if (rc != Success || !map) /* couldn't be created or didn't exist */
- return rc;
-
- if (stuff->deviceSpec == XkbUseCoreKbd ||
- stuff->deviceSpec == XkbUseCorePtr)
- {
- DeviceIntPtr other;
- for (other = inputInfo.devices; other; other = other->next)
- {
- if ((other != dev) && !IsMaster(other) && GetMaster(other, MASTER_KEYBOARD) == dev &&
- (other->kbdfeed || other->leds) &&
- (XaceHook(XACE_DEVICE_ACCESS, client, other, DixSetAttrAccess) == Success))
- {
- rc = _XkbCreateIndicatorMap(other, stuff->indicator,
- stuff->ledClass, stuff->ledID,
- &map, &led, TRUE);
- if (rc != Success || !map)
- return rc;
- }
- }
- }
-
- /* All checks passed, let's do it */
- rc = _XkbSetNamedIndicator(client, dev, stuff);
- if (rc != Success)
- return rc;
-
- if (stuff->deviceSpec == XkbUseCoreKbd ||
- stuff->deviceSpec == XkbUseCorePtr)
- {
- DeviceIntPtr other;
- for (other = inputInfo.devices; other; other = other->next)
- {
- if ((other != dev) && !IsMaster(other) && GetMaster(other, MASTER_KEYBOARD) == dev &&
- (other->kbdfeed || other->leds) &&
- (XaceHook(XACE_DEVICE_ACCESS, client, other, DixSetAttrAccess) == Success))
- {
- _XkbSetNamedIndicator(client, other, stuff);
- }
- }
- }
-
- return Success;
-}
-
-/***====================================================================***/
-
-static CARD32
-_XkbCountAtoms(Atom *atoms,int maxAtoms,int *count)
-{
-register unsigned int i,bit,nAtoms;
-register CARD32 atomsPresent;
-
- for (i=nAtoms=atomsPresent=0,bit=1;i<maxAtoms;i++,bit<<=1) {
- if (atoms[i]!=None) {
- atomsPresent|= bit;
- nAtoms++;
- }
- }
- if (count)
- *count= nAtoms;
- return atomsPresent;
-}
-
-static char *
-_XkbWriteAtoms(char *wire,Atom *atoms,int maxAtoms,int swap)
-{
-register unsigned int i;
-Atom *atm;
-
- atm = (Atom *)wire;
- for (i=0;i<maxAtoms;i++) {
- if (atoms[i]!=None) {
- *atm= atoms[i];
- if (swap) {
- register int n;
- swapl(atm,n);
- }
- atm++;
- }
- }
- return (char *)atm;
-}
-
-static Status
-XkbComputeGetNamesReplySize(XkbDescPtr xkb,xkbGetNamesReply *rep)
-{
-register unsigned which,length;
-register int i;
-
- rep->minKeyCode= xkb->min_key_code;
- rep->maxKeyCode= xkb->max_key_code;
- which= rep->which;
- length= 0;
- if (xkb->names!=NULL) {
- if (which&XkbKeycodesNameMask) length++;
- if (which&XkbGeometryNameMask) length++;
- if (which&XkbSymbolsNameMask) length++;
- if (which&XkbPhysSymbolsNameMask) length++;
- if (which&XkbTypesNameMask) length++;
- if (which&XkbCompatNameMask) length++;
- }
- else which&= ~XkbComponentNamesMask;
-
- if (xkb->map!=NULL) {
- if (which&XkbKeyTypeNamesMask)
- length+= xkb->map->num_types;
- rep->nTypes= xkb->map->num_types;
- if (which&XkbKTLevelNamesMask) {
- XkbKeyTypePtr pType = xkb->map->types;
- int nKTLevels = 0;
-
- length+= XkbPaddedSize(xkb->map->num_types)/4;
- for (i=0;i<xkb->map->num_types;i++,pType++) {
- if (pType->level_names!=NULL)
- nKTLevels+= pType->num_levels;
- }
- rep->nKTLevels= nKTLevels;
- length+= nKTLevels;
- }
- }
- else {
- rep->nTypes= 0;
- rep->nKTLevels= 0;
- which&= ~(XkbKeyTypeNamesMask|XkbKTLevelNamesMask);
- }
-
- rep->minKeyCode= xkb->min_key_code;
- rep->maxKeyCode= xkb->max_key_code;
- rep->indicators= 0;
- rep->virtualMods= 0;
- rep->groupNames= 0;
- if (xkb->names!=NULL) {
- if (which&XkbIndicatorNamesMask) {
- int nLeds;
- rep->indicators=
- _XkbCountAtoms(xkb->names->indicators,XkbNumIndicators,&nLeds);
- length+= nLeds;
- if (nLeds==0)
- which&= ~XkbIndicatorNamesMask;
- }
-
- if (which&XkbVirtualModNamesMask) {
- int nVMods;
- rep->virtualMods=
- _XkbCountAtoms(xkb->names->vmods,XkbNumVirtualMods,&nVMods);
- length+= nVMods;
- if (nVMods==0)
- which&= ~XkbVirtualModNamesMask;
- }
-
- if (which&XkbGroupNamesMask) {
- int nGroups;
- rep->groupNames=
- _XkbCountAtoms(xkb->names->groups,XkbNumKbdGroups,&nGroups);
- length+= nGroups;
- if (nGroups==0)
- which&= ~XkbGroupNamesMask;
- }
-
- if ((which&XkbKeyNamesMask)&&(xkb->names->keys))
- length+= rep->nKeys;
- else which&= ~XkbKeyNamesMask;
-
- if ((which&XkbKeyAliasesMask)&&
- (xkb->names->key_aliases)&&(xkb->names->num_key_aliases>0)) {
- rep->nKeyAliases= xkb->names->num_key_aliases;
- length+= rep->nKeyAliases*2;
- }
- else {
- which&= ~XkbKeyAliasesMask;
- rep->nKeyAliases= 0;
- }
-
- if ((which&XkbRGNamesMask)&&(xkb->names->num_rg>0))
- length+= xkb->names->num_rg;
- else which&= ~XkbRGNamesMask;
- }
- else {
- which&= ~(XkbIndicatorNamesMask|XkbVirtualModNamesMask);
- which&= ~(XkbGroupNamesMask|XkbKeyNamesMask|XkbKeyAliasesMask);
- which&= ~XkbRGNamesMask;
- }
-
- rep->length= length;
- rep->which= which;
- return Success;
-}
-
-static int
-XkbSendNames(ClientPtr client,XkbDescPtr xkb,xkbGetNamesReply *rep)
-{
-register unsigned i,length,which;
-char * start;
-char * desc;
-register int n;
-
- length= rep->length*4;
- which= rep->which;
- if (client->swapped) {
- swaps(&rep->sequenceNumber,n);
- swapl(&rep->length,n);
- swapl(&rep->which,n);
- swaps(&rep->virtualMods,n);
- swapl(&rep->indicators,n);
- }
-
- start = desc = calloc(1, length);
- if ( !start )
- return BadAlloc;
- if (xkb->names) {
- if (which&XkbKeycodesNameMask) {
- *((CARD32 *)desc)= xkb->names->keycodes;
- if (client->swapped) {
- swapl(desc,n);
- }
- desc+= 4;
- }
- if (which&XkbGeometryNameMask) {
- *((CARD32 *)desc)= xkb->names->geometry;
- if (client->swapped) {
- swapl(desc,n);
- }
- desc+= 4;
- }
- if (which&XkbSymbolsNameMask) {
- *((CARD32 *)desc)= xkb->names->symbols;
- if (client->swapped) {
- swapl(desc,n);
- }
- desc+= 4;
- }
- if (which&XkbPhysSymbolsNameMask) {
- register CARD32 *atm= (CARD32 *)desc;
- atm[0]= (CARD32)xkb->names->phys_symbols;
- if (client->swapped) {
- swapl(&atm[0],n);
- }
- desc+= 4;
- }
- if (which&XkbTypesNameMask) {
- *((CARD32 *)desc)= (CARD32)xkb->names->types;
- if (client->swapped) {
- swapl(desc,n);
- }
- desc+= 4;
- }
- if (which&XkbCompatNameMask) {
- *((CARD32 *)desc)= (CARD32)xkb->names->compat;
- if (client->swapped) {
- swapl(desc,n);
- }
- desc+= 4;
- }
- if (which&XkbKeyTypeNamesMask) {
- register CARD32 *atm= (CARD32 *)desc;
- register XkbKeyTypePtr type= xkb->map->types;
-
- for (i=0;i<xkb->map->num_types;i++,atm++,type++) {
- *atm= (CARD32)type->name;
- if (client->swapped) {
- swapl(atm,n);
- }
- }
- desc= (char *)atm;
- }
- if (which&XkbKTLevelNamesMask && xkb->map) {
- XkbKeyTypePtr type = xkb->map->types;
- register CARD32 *atm;
- for (i=0;i<rep->nTypes;i++,type++) {
- *desc++ = type->num_levels;
- }
- desc+= XkbPaddedSize(rep->nTypes)-rep->nTypes;
-
- atm= (CARD32 *)desc;
- type = xkb->map->types;
- for (i=0;i<xkb->map->num_types;i++,type++) {
- register unsigned l;
- if (type->level_names) {
- for (l=0;l<type->num_levels;l++,atm++) {
- *atm= type->level_names[l];
- if (client->swapped) {
- swapl(atm,n);
- }
- }
- desc+= type->num_levels*4;
- }
- }
- }
- if (which&XkbIndicatorNamesMask) {
- desc= _XkbWriteAtoms(desc,xkb->names->indicators,XkbNumIndicators,
- client->swapped);
- }
- if (which&XkbVirtualModNamesMask) {
- desc= _XkbWriteAtoms(desc,xkb->names->vmods,XkbNumVirtualMods,
- client->swapped);
- }
- if (which&XkbGroupNamesMask) {
- desc= _XkbWriteAtoms(desc,xkb->names->groups,XkbNumKbdGroups,
- client->swapped);
- }
- if (which&XkbKeyNamesMask) {
- for (i=0;i<rep->nKeys;i++,desc+= sizeof(XkbKeyNameRec)) {
- *((XkbKeyNamePtr)desc)= xkb->names->keys[i+rep->firstKey];
- }
- }
- if (which&XkbKeyAliasesMask) {
- XkbKeyAliasPtr pAl;
- pAl= xkb->names->key_aliases;
- for (i=0;i<rep->nKeyAliases;i++,pAl++,desc+=2*XkbKeyNameLength) {
- *((XkbKeyAliasPtr)desc)= *pAl;
- }
- }
- if ((which&XkbRGNamesMask)&&(rep->nRadioGroups>0)) {
- register CARD32 *atm= (CARD32 *)desc;
- for (i=0;i<rep->nRadioGroups;i++,atm++) {
- *atm= (CARD32)xkb->names->radio_groups[i];
- if (client->swapped) {
- swapl(atm,n);
- }
- }
- desc+= rep->nRadioGroups*4;
- }
- }
-
- if ((desc-start)!=(length)) {
- ErrorF("[xkb] BOGUS LENGTH in write names, expected %d, got %ld\n",
- length, (unsigned long)(desc-start));
- }
- WriteToClient(client, SIZEOF(xkbGetNamesReply), (char *)rep);
- WriteToClient(client, length, start);
- free((char *)start);
- return Success;
-}
-
-int
-ProcXkbGetNames(ClientPtr client)
-{
- DeviceIntPtr dev;
- XkbDescPtr xkb;
- xkbGetNamesReply rep;
-
- REQUEST(xkbGetNamesReq);
- REQUEST_SIZE_MATCH(xkbGetNamesReq);
-
- if (!(client->xkbClientFlags&_XkbClientInitialized))
- return BadAccess;
-
- CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
- CHK_MASK_LEGAL(0x01,stuff->which,XkbAllNamesMask);
-
- xkb = dev->key->xkbInfo->desc;
- memset(&rep, 0, sizeof(xkbGetNamesReply));
- rep.type= X_Reply;
- rep.sequenceNumber= client->sequence;
- rep.length = 0;
- rep.deviceID = dev->id;
- rep.which = stuff->which;
- rep.nTypes = xkb->map->num_types;
- rep.firstKey = xkb->min_key_code;
- rep.nKeys = XkbNumKeys(xkb);
- if (xkb->names!=NULL) {
- rep.nKeyAliases= xkb->names->num_key_aliases;
- rep.nRadioGroups = xkb->names->num_rg;
- }
- else {
- rep.nKeyAliases= rep.nRadioGroups= 0;
- }
- XkbComputeGetNamesReplySize(xkb,&rep);
- return XkbSendNames(client,xkb,&rep);
-}
-
-/***====================================================================***/
-
-static CARD32 *
-_XkbCheckAtoms(CARD32 *wire,int nAtoms,int swapped,Atom *pError)
-{
-register int i;
-
- for (i=0;i<nAtoms;i++,wire++) {
- if (swapped) {
- register int n;
- swapl(wire,n);
- }
- if ((((Atom)*wire)!=None)&&(!ValidAtom((Atom)*wire))) {
- *pError= ((Atom)*wire);
- return NULL;
- }
- }
- return wire;
-}
-
-static CARD32 *
-_XkbCheckMaskedAtoms(CARD32 *wire,int nAtoms,CARD32 present,int swapped,
- Atom *pError)
-{
-register unsigned i,bit;
-
- for (i=0,bit=1;(i<nAtoms)&&(present);i++,bit<<=1) {
- if ((present&bit)==0)
- continue;
- if (swapped) {
- register int n;
- swapl(wire,n);
- }
- if ((((Atom)*wire)!=None)&&(!ValidAtom(((Atom)*wire)))) {
- *pError= (Atom)*wire;
- return NULL;
- }
- wire++;
- }
- return wire;
-}
-
-static Atom *
-_XkbCopyMaskedAtoms( Atom *wire,
- Atom *dest,
- int nAtoms,
- CARD32 present)
-{
-register int i,bit;
-
- for (i=0,bit=1;(i<nAtoms)&&(present);i++,bit<<=1) {
- if ((present&bit)==0)
- continue;
- dest[i]= *wire++;
- }
- return wire;
-}
-
-static Bool
-_XkbCheckTypeName(Atom name,int typeNdx)
-{
-const char * str;
-
- str= NameForAtom(name);
- if ((strcmp(str,"ONE_LEVEL")==0)||(strcmp(str,"TWO_LEVEL")==0)||
- (strcmp(str,"ALPHABETIC")==0)||(strcmp(str,"KEYPAD")==0))
- return FALSE;
- return TRUE;
-}
-
-/**
- * Check the device-dependent data in the request against the device. Returns
- * Success, or the appropriate error code.
- */
-static int
-_XkbSetNamesCheck(ClientPtr client, DeviceIntPtr dev,
- xkbSetNamesReq *stuff, CARD32 *data)
-{
- XkbDescRec *xkb;
- XkbNamesRec *names;
- CARD32 *tmp;
- Atom bad;
-
- tmp = data;
- xkb = dev->key->xkbInfo->desc;
- names = xkb->names;
-
-
- if (stuff->which & XkbKeyTypeNamesMask) {
- int i;
- CARD32 *old;
- if ( stuff->nTypes<1 ) {
- client->errorValue = _XkbErrCode2(0x02,stuff->nTypes);
- return BadValue;
- }
- if ((unsigned)(stuff->firstType+stuff->nTypes-1)>=xkb->map->num_types) {
- client->errorValue = _XkbErrCode4(0x03,stuff->firstType,
- stuff->nTypes,
- xkb->map->num_types);
- return BadValue;
- }
- if (((unsigned)stuff->firstType)<=XkbLastRequiredType) {
- client->errorValue = _XkbErrCode2(0x04,stuff->firstType);
- return BadAccess;
- }
- old= tmp;
- tmp= _XkbCheckAtoms(tmp,stuff->nTypes,client->swapped,&bad);
- if (!tmp) {
- client->errorValue= bad;
- return BadAtom;
- }
- for (i=0;i<stuff->nTypes;i++,old++) {
- if (!_XkbCheckTypeName((Atom)*old,stuff->firstType+i))
- client->errorValue= _XkbErrCode2(0x05,i);
- }
- }
- if (stuff->which&XkbKTLevelNamesMask) {
- unsigned i;
- XkbKeyTypePtr type;
- CARD8 * width;
- if ( stuff->nKTLevels<1 ) {
- client->errorValue = _XkbErrCode2(0x05,stuff->nKTLevels);
- return BadValue;
- }
- if ((unsigned)(stuff->firstKTLevel+stuff->nKTLevels-1)>=
- xkb->map->num_types) {
- client->errorValue = _XkbErrCode4(0x06,stuff->firstKTLevel,
- stuff->nKTLevels,xkb->map->num_types);
- return BadValue;
- }
- width = (CARD8 *)tmp;
- tmp= (CARD32 *)(((char *)tmp)+XkbPaddedSize(stuff->nKTLevels));
- type = &xkb->map->types[stuff->firstKTLevel];
- for (i=0;i<stuff->nKTLevels;i++,type++) {
- if (width[i]==0)
- continue;
- else if (width[i]!=type->num_levels) {
- client->errorValue= _XkbErrCode4(0x07,i+stuff->firstKTLevel,
- type->num_levels,width[i]);
- return BadMatch;
- }
- tmp= _XkbCheckAtoms(tmp,width[i],client->swapped,&bad);
- if (!tmp) {
- client->errorValue= bad;
- return BadAtom;
- }
- }
- }
- if (stuff->which&XkbIndicatorNamesMask) {
- if (stuff->indicators==0) {
- client->errorValue= 0x08;
- return BadMatch;
- }
- tmp= _XkbCheckMaskedAtoms(tmp,XkbNumIndicators,stuff->indicators,
- client->swapped,&bad);
- if (!tmp) {
- client->errorValue= bad;
- return BadAtom;
- }
- }
- if (stuff->which&XkbVirtualModNamesMask) {
- if (stuff->virtualMods==0) {
- client->errorValue= 0x09;
- return BadMatch;
- }
- tmp= _XkbCheckMaskedAtoms(tmp,XkbNumVirtualMods,
- (CARD32)stuff->virtualMods,
- client->swapped,&bad);
- if (!tmp) {
- client->errorValue = bad;
- return BadAtom;
- }
- }
- if (stuff->which&XkbGroupNamesMask) {
- if (stuff->groupNames==0) {
- client->errorValue= 0x0a;
- return BadMatch;
- }
- tmp= _XkbCheckMaskedAtoms(tmp,XkbNumKbdGroups,
- (CARD32)stuff->groupNames,
- client->swapped,&bad);
- if (!tmp) {
- client->errorValue = bad;
- return BadAtom;
- }
- }
- if (stuff->which&XkbKeyNamesMask) {
- if (stuff->firstKey<(unsigned)xkb->min_key_code) {
- client->errorValue= _XkbErrCode3(0x0b,xkb->min_key_code,
- stuff->firstKey);
- return BadValue;
- }
- if (((unsigned)(stuff->firstKey+stuff->nKeys-1)>xkb->max_key_code)||
- (stuff->nKeys<1)) {
- client->errorValue= _XkbErrCode4(0x0c,xkb->max_key_code,
- stuff->firstKey,stuff->nKeys);
- return BadValue;
- }
- tmp+= stuff->nKeys;
- }
- if ((stuff->which&XkbKeyAliasesMask)&&(stuff->nKeyAliases>0)) {
- tmp+= stuff->nKeyAliases*2;
- }
- if (stuff->which&XkbRGNamesMask) {
- if ( stuff->nRadioGroups<1 ) {
- client->errorValue= _XkbErrCode2(0x0d,stuff->nRadioGroups);
- return BadValue;
- }
- tmp= _XkbCheckAtoms(tmp,stuff->nRadioGroups,client->swapped,&bad);
- if (!tmp) {
- client->errorValue= bad;
- return BadAtom;
- }
- }
- if ((tmp-((CARD32 *)stuff))!=stuff->length) {
- client->errorValue = stuff->length;
- return BadLength;
- }
-
-
-
- return Success;
-}
-
-static int
-_XkbSetNames(ClientPtr client, DeviceIntPtr dev, xkbSetNamesReq *stuff)
-{
- XkbDescRec *xkb;
- XkbNamesRec *names;
- CARD32 *tmp;
- xkbNamesNotify nn;
-
- tmp = (CARD32 *)&stuff[1];
- xkb = dev->key->xkbInfo->desc;
- names = xkb->names;
-
- if (XkbAllocNames(xkb,stuff->which,stuff->nRadioGroups,
- stuff->nKeyAliases)!=Success) {
- return BadAlloc;
- }
-
- memset(&nn, 0, sizeof(xkbNamesNotify));
- nn.changed= stuff->which;
- tmp = (CARD32 *)&stuff[1];
- if (stuff->which&XkbKeycodesNameMask)
- names->keycodes= *tmp++;
- if (stuff->which&XkbGeometryNameMask)
- names->geometry= *tmp++;
- if (stuff->which&XkbSymbolsNameMask)
- names->symbols= *tmp++;
- if (stuff->which&XkbPhysSymbolsNameMask)
- names->phys_symbols= *tmp++;
- if (stuff->which&XkbTypesNameMask)
- names->types= *tmp++;
- if (stuff->which&XkbCompatNameMask)
- names->compat= *tmp++;
- if ((stuff->which&XkbKeyTypeNamesMask)&&(stuff->nTypes>0)) {
- register unsigned i;
- register XkbKeyTypePtr type;
-
- type= &xkb->map->types[stuff->firstType];
- for (i=0;i<stuff->nTypes;i++,type++) {
- type->name= *tmp++;
- }
- nn.firstType= stuff->firstType;
- nn.nTypes= stuff->nTypes;
- }
- if (stuff->which&XkbKTLevelNamesMask) {
- register XkbKeyTypePtr type;
- register unsigned i;
- CARD8 *width;
-
- width = (CARD8 *)tmp;
- tmp= (CARD32 *)(((char *)tmp)+XkbPaddedSize(stuff->nKTLevels));
- type= &xkb->map->types[stuff->firstKTLevel];
- for (i=0;i<stuff->nKTLevels;i++,type++) {
- if (width[i]>0) {
- if (type->level_names) {
- register unsigned n;
- for (n=0;n<width[i];n++) {
- type->level_names[n]= tmp[n];
- }
- }
- tmp+= width[i];
- }
- }
- nn.firstLevelName= 0;
- nn.nLevelNames= stuff->nTypes;
- }
- if (stuff->which&XkbIndicatorNamesMask) {
- tmp= _XkbCopyMaskedAtoms(tmp,names->indicators,XkbNumIndicators,
- stuff->indicators);
- nn.changedIndicators= stuff->indicators;
- }
- if (stuff->which&XkbVirtualModNamesMask) {
- tmp= _XkbCopyMaskedAtoms(tmp,names->vmods,XkbNumVirtualMods,
- stuff->virtualMods);
- nn.changedVirtualMods= stuff->virtualMods;
- }
- if (stuff->which&XkbGroupNamesMask) {
- tmp= _XkbCopyMaskedAtoms(tmp,names->groups,XkbNumKbdGroups,
- stuff->groupNames);
- nn.changedVirtualMods= stuff->groupNames;
- }
- if (stuff->which&XkbKeyNamesMask) {
- memcpy((char*)&names->keys[stuff->firstKey],(char *)tmp,
- stuff->nKeys*XkbKeyNameLength);
- tmp+= stuff->nKeys;
- nn.firstKey= stuff->firstKey;
- nn.nKeys= stuff->nKeys;
- }
- if (stuff->which&XkbKeyAliasesMask) {
- if (stuff->nKeyAliases>0) {
- register int na= stuff->nKeyAliases;
- if (XkbAllocNames(xkb,XkbKeyAliasesMask,0,na)!=Success)
- return BadAlloc;
- memcpy((char *)names->key_aliases,(char *)tmp,
- stuff->nKeyAliases*sizeof(XkbKeyAliasRec));
- tmp+= stuff->nKeyAliases*2;
- }
- else if (names->key_aliases!=NULL) {
- free(names->key_aliases);
- names->key_aliases= NULL;
- names->num_key_aliases= 0;
- }
- nn.nAliases= names->num_key_aliases;
- }
- if (stuff->which&XkbRGNamesMask) {
- if (stuff->nRadioGroups>0) {
- register unsigned i,nrg;
- nrg= stuff->nRadioGroups;
- if (XkbAllocNames(xkb,XkbRGNamesMask,nrg,0)!=Success)
- return BadAlloc;
-
- for (i=0;i<stuff->nRadioGroups;i++) {
- names->radio_groups[i]= tmp[i];
- }
- tmp+= stuff->nRadioGroups;
- }
- else if (names->radio_groups) {
- free(names->radio_groups);
- names->radio_groups= NULL;
- names->num_rg= 0;
- }
- nn.nRadioGroups= names->num_rg;
- }
- if (nn.changed) {
- Bool needExtEvent;
- needExtEvent= (nn.changed&XkbIndicatorNamesMask)!=0;
- XkbSendNamesNotify(dev,&nn);
- if (needExtEvent) {
- XkbSrvLedInfoPtr sli;
- xkbExtensionDeviceNotify edev;
- register int i;
- register unsigned bit;
-
- sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId,
- XkbXI_IndicatorsMask);
- sli->namesPresent= 0;
- for (i=0,bit=1;i<XkbNumIndicators;i++,bit<<=1) {
- if (names->indicators[i]!=None)
- sli->namesPresent|= bit;
- }
- memset(&edev, 0, sizeof(xkbExtensionDeviceNotify));
- edev.reason= XkbXI_IndicatorNamesMask;
- edev.ledClass= KbdFeedbackClass;
- edev.ledID= dev->kbdfeed->ctrl.id;
- edev.ledsDefined= sli->namesPresent|sli->mapsPresent;
- edev.ledState= sli->effectiveState;
- edev.firstBtn= 0;
- edev.nBtns= 0;
- edev.supported= XkbXI_AllFeaturesMask;
- edev.unsupported= 0;
- XkbSendExtensionDeviceNotify(dev,client,&edev);
- }
- }
- return Success;
-}
-
-int
-ProcXkbSetNames(ClientPtr client)
-{
- DeviceIntPtr dev;
- CARD32 *tmp;
- Atom bad;
- int rc;
-
- REQUEST(xkbSetNamesReq);
- REQUEST_AT_LEAST_SIZE(xkbSetNamesReq);
-
- if (!(client->xkbClientFlags&_XkbClientInitialized))
- return BadAccess;
-
- CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess);
- CHK_MASK_LEGAL(0x01,stuff->which,XkbAllNamesMask);
-
- /* check device-independent stuff */
- tmp = (CARD32 *)&stuff[1];
-
- if (stuff->which&XkbKeycodesNameMask) {
- tmp= _XkbCheckAtoms(tmp,1,client->swapped,&bad);
- if (!tmp) {
- client->errorValue = bad;
- return BadAtom;
- }
- }
- if (stuff->which&XkbGeometryNameMask) {
- tmp= _XkbCheckAtoms(tmp,1,client->swapped,&bad);
- if (!tmp) {
- client->errorValue = bad;
- return BadAtom;
- }
- }
- if (stuff->which&XkbSymbolsNameMask) {
- tmp= _XkbCheckAtoms(tmp,1,client->swapped,&bad);
- if (!tmp) {
- client->errorValue = bad;
- return BadAtom;
- }
- }
- if (stuff->which&XkbPhysSymbolsNameMask) {
- tmp= _XkbCheckAtoms(tmp,1,client->swapped,&bad);
- if (!tmp) {
- client->errorValue= bad;
- return BadAtom;
- }
- }
- if (stuff->which&XkbTypesNameMask) {
- tmp= _XkbCheckAtoms(tmp,1,client->swapped,&bad);
- if (!tmp) {
- client->errorValue = bad;
- return BadAtom;
- }
- }
- if (stuff->which&XkbCompatNameMask) {
- tmp= _XkbCheckAtoms(tmp,1,client->swapped,&bad);
- if (!tmp) {
- client->errorValue = bad;
- return BadAtom;
- }
- }
-
- /* start of device-dependent tests */
- rc = _XkbSetNamesCheck(client, dev, stuff, tmp);
- if (rc != Success)
- return rc;
-
- if (stuff->deviceSpec == XkbUseCoreKbd)
- {
- DeviceIntPtr other;
- for (other = inputInfo.devices; other; other = other->next)
- {
- if ((other != dev) && other->key && !IsMaster(other) && GetMaster(other, MASTER_KEYBOARD) == dev)
- {
-
- rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixManageAccess);
- if (rc == Success)
- {
- rc = _XkbSetNamesCheck(client, other, stuff, tmp);
- if (rc != Success)
- return rc;
- }
- }
- }
- }
-
- /* everything is okay -- update names */
-
- rc = _XkbSetNames(client, dev, stuff);
- if (rc != Success)
- return rc;
-
- if (stuff->deviceSpec == XkbUseCoreKbd)
- {
- DeviceIntPtr other;
- for (other = inputInfo.devices; other; other = other->next)
- {
- if ((other != dev) && other->key && !IsMaster(other) && GetMaster(other, MASTER_KEYBOARD) == dev)
- {
-
- rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixManageAccess);
- if (rc == Success)
- _XkbSetNames(client, other, stuff);
- }
- }
- }
-
- /* everything is okay -- update names */
-
- return Success;
-}
-
-/***====================================================================***/
-
-#include "xkbgeom.h"
-
-#define XkbSizeCountedString(s) ((s)?((((2+strlen(s))+3)/4)*4):4)
-
-static char *
-XkbWriteCountedString(char *wire,char *str,Bool swap)
-{
- CARD16 len,*pLen;
-
- if (!str)
- return wire;
-
- len= strlen(str);
- pLen= (CARD16 *)wire;
- *pLen= len;
- if (swap) {
- register int n;
- swaps(pLen,n);
- }
- memcpy(&wire[2],str,len);
- wire+= ((2+len+3)/4)*4;
- return wire;
-}
-
-static int
-XkbSizeGeomProperties(XkbGeometryPtr geom)
-{
-register int i,size;
-XkbPropertyPtr prop;
-
- for (size=i=0,prop=geom->properties;i<geom->num_properties;i++,prop++) {
- size+= XkbSizeCountedString(prop->name);
- size+= XkbSizeCountedString(prop->value);
- }
- return size;
-}
-
-static char *
-XkbWriteGeomProperties(char *wire,XkbGeometryPtr geom,Bool swap)
-{
-register int i;
-register XkbPropertyPtr prop;
-
- for (i=0,prop=geom->properties;i<geom->num_properties;i++,prop++) {
- wire= XkbWriteCountedString(wire,prop->name,swap);
- wire= XkbWriteCountedString(wire,prop->value,swap);
- }
- return wire;
-}
-
-static int
-XkbSizeGeomKeyAliases(XkbGeometryPtr geom)
-{
- return geom->num_key_aliases*(2*XkbKeyNameLength);
-}
-
-static char *
-XkbWriteGeomKeyAliases(char *wire,XkbGeometryPtr geom,Bool swap)
-{
-register int sz;
-
- sz= geom->num_key_aliases*(XkbKeyNameLength*2);
- if (sz>0) {
- memcpy(wire,(char *)geom->key_aliases,sz);
- wire+= sz;
- }
- return wire;
-}
-
-static int
-XkbSizeGeomColors(XkbGeometryPtr geom)
-{
-register int i,size;
-register XkbColorPtr color;
-
- for (i=size=0,color=geom->colors;i<geom->num_colors;i++,color++) {
- size+= XkbSizeCountedString(color->spec);
- }
- return size;
-}
-
-static char *
-XkbWriteGeomColors(char *wire,XkbGeometryPtr geom,Bool swap)
-{
-register int i;
-register XkbColorPtr color;
-
- for (i=0,color=geom->colors;i<geom->num_colors;i++,color++) {
- wire= XkbWriteCountedString(wire,color->spec,swap);
- }
- return wire;
-}
-
-static int
-XkbSizeGeomShapes(XkbGeometryPtr geom)
-{
-register int i,size;
-register XkbShapePtr shape;
-
- for (i=size=0,shape=geom->shapes;i<geom->num_shapes;i++,shape++) {
- register int n;
- register XkbOutlinePtr ol;
- size+= SIZEOF(xkbShapeWireDesc);
- for (n=0,ol=shape->outlines;n<shape->num_outlines;n++,ol++) {
- size+= SIZEOF(xkbOutlineWireDesc);
- size+= ol->num_points*SIZEOF(xkbPointWireDesc);
- }
- }
- return size;
-}
-
-static char *
-XkbWriteGeomShapes(char *wire,XkbGeometryPtr geom,Bool swap)
-{
-int i;
-XkbShapePtr shape;
-xkbShapeWireDesc * shapeWire;
-
- for (i=0,shape=geom->shapes;i<geom->num_shapes;i++,shape++) {
- register int o;
- XkbOutlinePtr ol;
- xkbOutlineWireDesc * olWire;
- shapeWire= (xkbShapeWireDesc *)wire;
- shapeWire->name= shape->name;
- shapeWire->nOutlines= shape->num_outlines;
- if (shape->primary!=NULL)
- shapeWire->primaryNdx= XkbOutlineIndex(shape,shape->primary);
- else shapeWire->primaryNdx= XkbNoShape;
- if (shape->approx!=NULL)
- shapeWire->approxNdx= XkbOutlineIndex(shape,shape->approx);
- else shapeWire->approxNdx= XkbNoShape;
- if (swap) {
- register int n;
- swapl(&shapeWire->name,n);
- }
- wire= (char *)&shapeWire[1];
- for (o=0,ol=shape->outlines;o<shape->num_outlines;o++,ol++) {
- register int p;
- XkbPointPtr pt;
- xkbPointWireDesc * ptWire;
- olWire= (xkbOutlineWireDesc *)wire;
- olWire->nPoints= ol->num_points;
- olWire->cornerRadius= ol->corner_radius;
- wire= (char *)&olWire[1];
- ptWire= (xkbPointWireDesc *)wire;
- for (p=0,pt=ol->points;p<ol->num_points;p++,pt++) {
- ptWire[p].x= pt->x;
- ptWire[p].y= pt->y;
- if (swap) {
- register int n;
- swaps(&ptWire[p].x,n);
- swaps(&ptWire[p].y,n);
- }
- }
- wire= (char *)&ptWire[ol->num_points];
- }
- }
- return wire;
-}
-
-static int
-XkbSizeGeomDoodads(int num_doodads,XkbDoodadPtr doodad)
-{
-register int i,size;
-
- for (i=size=0;i<num_doodads;i++,doodad++) {
- size+= SIZEOF(xkbAnyDoodadWireDesc);
- if (doodad->any.type==XkbTextDoodad) {
- size+= XkbSizeCountedString(doodad->text.text);
- size+= XkbSizeCountedString(doodad->text.font);
- }
- else if (doodad->any.type==XkbLogoDoodad) {
- size+= XkbSizeCountedString(doodad->logo.logo_name);
- }
- }
- return size;
-}
-
-static char *
-XkbWriteGeomDoodads(char *wire,int num_doodads,XkbDoodadPtr doodad,Bool swap)
-{
-register int i;
-xkbDoodadWireDesc * doodadWire;
-
- for (i=0;i<num_doodads;i++,doodad++) {
- doodadWire= (xkbDoodadWireDesc *)wire;
- wire= (char *)&doodadWire[1];
- memset(doodadWire, 0, SIZEOF(xkbDoodadWireDesc));
- doodadWire->any.name= doodad->any.name;
- doodadWire->any.type= doodad->any.type;
- doodadWire->any.priority= doodad->any.priority;
- doodadWire->any.top= doodad->any.top;
- doodadWire->any.left= doodad->any.left;
- if (swap) {
- register int n;
- swapl(&doodadWire->any.name,n);
- swaps(&doodadWire->any.top,n);
- swaps(&doodadWire->any.left,n);
- }
- switch (doodad->any.type) {
- case XkbOutlineDoodad:
- case XkbSolidDoodad:
- doodadWire->shape.angle= doodad->shape.angle;
- doodadWire->shape.colorNdx= doodad->shape.color_ndx;
- doodadWire->shape.shapeNdx= doodad->shape.shape_ndx;
- if (swap) {
- register int n;
- swaps(&doodadWire->shape.angle,n);
- }
- break;
- case XkbTextDoodad:
- doodadWire->text.angle= doodad->text.angle;
- doodadWire->text.width= doodad->text.width;
- doodadWire->text.height= doodad->text.height;
- doodadWire->text.colorNdx= doodad->text.color_ndx;
- if (swap) {
- register int n;
- swaps(&doodadWire->text.angle,n);
- swaps(&doodadWire->text.width,n);
- swaps(&doodadWire->text.height,n);
- }
- wire= XkbWriteCountedString(wire,doodad->text.text,swap);
- wire= XkbWriteCountedString(wire,doodad->text.font,swap);
- break;
- case XkbIndicatorDoodad:
- doodadWire->indicator.shapeNdx= doodad->indicator.shape_ndx;
- doodadWire->indicator.onColorNdx=doodad->indicator.on_color_ndx;
- doodadWire->indicator.offColorNdx=
- doodad->indicator.off_color_ndx;
- break;
- case XkbLogoDoodad:
- doodadWire->logo.angle= doodad->logo.angle;
- doodadWire->logo.colorNdx= doodad->logo.color_ndx;
- doodadWire->logo.shapeNdx= doodad->logo.shape_ndx;
- wire= XkbWriteCountedString(wire,doodad->logo.logo_name,swap);
- break;
- default:
- ErrorF("[xkb] Unknown doodad type %d in XkbWriteGeomDoodads\n",
- doodad->any.type);
- ErrorF("[xkb] Ignored\n");
- break;
- }
- }
- return wire;
-}
-
-static char *
-XkbWriteGeomOverlay(char *wire,XkbOverlayPtr ol,Bool swap)
-{
-register int r;
-XkbOverlayRowPtr row;
-xkbOverlayWireDesc * olWire;
-
- olWire= (xkbOverlayWireDesc *)wire;
- olWire->name= ol->name;
- olWire->nRows= ol->num_rows;
- if (swap) {
- register int n;
- swapl(&olWire->name,n);
- }
- wire= (char *)&olWire[1];
- for (r=0,row=ol->rows;r<ol->num_rows;r++,row++) {
- unsigned int k;
- XkbOverlayKeyPtr key;
- xkbOverlayRowWireDesc * rowWire;
- rowWire= (xkbOverlayRowWireDesc *)wire;
- rowWire->rowUnder= row->row_under;
- rowWire->nKeys= row->num_keys;
- wire= (char *)&rowWire[1];
- for (k=0,key=row->keys;k<row->num_keys;k++,key++) {
- xkbOverlayKeyWireDesc * keyWire;
- keyWire= (xkbOverlayKeyWireDesc *)wire;
- memcpy(keyWire->over,key->over.name,XkbKeyNameLength);
- memcpy(keyWire->under,key->under.name,XkbKeyNameLength);
- wire= (char *)&keyWire[1];
- }
- }
- return wire;
-}
-
-static int
-XkbSizeGeomSections(XkbGeometryPtr geom)
-{
-register int i,size;
-XkbSectionPtr section;
-
- for (i=size=0,section=geom->sections;i<geom->num_sections;i++,section++) {
- size+= SIZEOF(xkbSectionWireDesc);
- if (section->rows) {
- int r;
- XkbRowPtr row;
- for (r=0,row=section->rows;r<section->num_rows;row++,r++) {
- size+= SIZEOF(xkbRowWireDesc);
- size+= row->num_keys*SIZEOF(xkbKeyWireDesc);
- }
- }
- if (section->doodads)
- size+= XkbSizeGeomDoodads(section->num_doodads,section->doodads);
- if (section->overlays) {
- int o;
- XkbOverlayPtr ol;
- for (o=0,ol=section->overlays;o<section->num_overlays;o++,ol++) {
- int r;
- XkbOverlayRowPtr row;
- size+= SIZEOF(xkbOverlayWireDesc);
- for (r=0,row=ol->rows;r<ol->num_rows;r++,row++) {
- size+= SIZEOF(xkbOverlayRowWireDesc);
- size+= row->num_keys*SIZEOF(xkbOverlayKeyWireDesc);
- }
- }
- }
- }
- return size;
-}
-
-static char *
-XkbWriteGeomSections(char *wire,XkbGeometryPtr geom,Bool swap)
-{
-register int i;
-XkbSectionPtr section;
-xkbSectionWireDesc * sectionWire;
-
- for (i=0,section=geom->sections;i<geom->num_sections;i++,section++) {
- sectionWire= (xkbSectionWireDesc *)wire;
- sectionWire->name= section->name;
- sectionWire->top= section->top;
- sectionWire->left= section->left;
- sectionWire->width= section->width;
- sectionWire->height= section->height;
- sectionWire->angle= section->angle;
- sectionWire->priority= section->priority;
- sectionWire->nRows= section->num_rows;
- sectionWire->nDoodads= section->num_doodads;
- sectionWire->nOverlays= section->num_overlays;
- sectionWire->pad= 0;
- if (swap) {
- register int n;
- swapl(§ionWire->name,n);
- swaps(§ionWire->top,n);
- swaps(§ionWire->left,n);
- swaps(§ionWire->width,n);
- swaps(§ionWire->height,n);
- swaps(§ionWire->angle,n);
- }
- wire= (char *)§ionWire[1];
- if (section->rows) {
- int r;
- XkbRowPtr row;
- xkbRowWireDesc * rowWire;
- for (r=0,row=section->rows;r<section->num_rows;r++,row++) {
- rowWire= (xkbRowWireDesc *)wire;
- rowWire->top= row->top;
- rowWire->left= row->left;
- rowWire->nKeys= row->num_keys;
- rowWire->vertical= row->vertical;
- rowWire->pad= 0;
- if (swap) {
- register int n;
- swaps(&rowWire->top,n);
- swaps(&rowWire->left,n);
- }
- wire= (char *)&rowWire[1];
- if (row->keys) {
- int k;
- XkbKeyPtr key;
- xkbKeyWireDesc * keyWire;
- keyWire= (xkbKeyWireDesc *)wire;
- for (k=0,key=row->keys;k<row->num_keys;k++,key++) {
- memcpy(keyWire[k].name,key->name.name,XkbKeyNameLength);
- keyWire[k].gap= key->gap;
- keyWire[k].shapeNdx= key->shape_ndx;
- keyWire[k].colorNdx= key->color_ndx;
- if (swap) {
- register int n;
- swaps(&keyWire[k].gap,n);
- }
- }
- wire= (char *)&keyWire[row->num_keys];
- }
- }
- }
- if (section->doodads) {
- wire= XkbWriteGeomDoodads(wire,
- section->num_doodads,section->doodads,
- swap);
- }
- if (section->overlays) {
- register int o;
- for (o=0;o<section->num_overlays;o++) {
- wire= XkbWriteGeomOverlay(wire,§ion->overlays[o],swap);
- }
- }
- }
- return wire;
-}
-
-static Status
-XkbComputeGetGeometryReplySize( XkbGeometryPtr geom,
- xkbGetGeometryReply * rep,
- Atom name)
-{
-int len;
-
- if (geom!=NULL) {
- len= XkbSizeCountedString(geom->label_font);
- len+= XkbSizeGeomProperties(geom);
- len+= XkbSizeGeomColors(geom);
- len+= XkbSizeGeomShapes(geom);
- len+= XkbSizeGeomSections(geom);
- len+= XkbSizeGeomDoodads(geom->num_doodads,geom->doodads);
- len+= XkbSizeGeomKeyAliases(geom);
- rep->length= len/4;
- rep->found= TRUE;
- rep->name= geom->name;
- rep->widthMM= geom->width_mm;
- rep->heightMM= geom->height_mm;
- rep->nProperties= geom->num_properties;
- rep->nColors= geom->num_colors;
- rep->nShapes= geom->num_shapes;
- rep->nSections= geom->num_sections;
- rep->nDoodads= geom->num_doodads;
- rep->nKeyAliases= geom->num_key_aliases;
- rep->baseColorNdx= XkbGeomColorIndex(geom,geom->base_color);
- rep->labelColorNdx= XkbGeomColorIndex(geom,geom->label_color);
- }
- else {
- rep->length= 0;
- rep->found= FALSE;
- rep->name= name;
- rep->widthMM= rep->heightMM= 0;
- rep->nProperties= rep->nColors= rep->nShapes= 0;
- rep->nSections= rep->nDoodads= 0;
- rep->nKeyAliases= 0;
- rep->labelColorNdx= rep->baseColorNdx= 0;
- }
- return Success;
-}
-
-static int
-XkbSendGeometry( ClientPtr client,
- XkbGeometryPtr geom,
- xkbGetGeometryReply * rep,
- Bool freeGeom)
-{
- char *desc,*start;
- int len;
-
- if (geom!=NULL) {
- len= rep->length*4;
- start= desc= malloc(len);
- if (!start)
- return BadAlloc;
- desc= XkbWriteCountedString(desc,geom->label_font,client->swapped);
- if ( rep->nProperties>0 )
- desc = XkbWriteGeomProperties(desc,geom,client->swapped);
- if ( rep->nColors>0 )
- desc = XkbWriteGeomColors(desc,geom,client->swapped);
- if ( rep->nShapes>0 )
- desc = XkbWriteGeomShapes(desc,geom,client->swapped);
- if ( rep->nSections>0 )
- desc = XkbWriteGeomSections(desc,geom,client->swapped);
- if ( rep->nDoodads>0 )
- desc = XkbWriteGeomDoodads(desc,geom->num_doodads,geom->doodads,
- client->swapped);
- if ( rep->nKeyAliases>0 )
- desc = XkbWriteGeomKeyAliases(desc,geom,client->swapped);
- if ((desc-start)!=(len)) {
- ErrorF("[xkb] BOGUS LENGTH in XkbSendGeometry, expected %d, got %ld\n",
- len, (unsigned long)(desc-start));
- }
- }
- else {
- len= 0;
- start= NULL;
- }
- if (client->swapped) {
- register int n;
- swaps(&rep->sequenceNumber,n);
- swapl(&rep->length,n);
- swapl(&rep->name,n);
- swaps(&rep->widthMM,n);
- swaps(&rep->heightMM,n);
- swaps(&rep->nProperties,n);
- swaps(&rep->nColors,n);
- swaps(&rep->nShapes,n);
- swaps(&rep->nSections,n);
- swaps(&rep->nDoodads,n);
- swaps(&rep->nKeyAliases,n);
- }
- WriteToClient(client, SIZEOF(xkbGetGeometryReply), (char *)rep);
- if (len>0)
- WriteToClient(client, len, start);
- if (start!=NULL)
- free((char *)start);
- if (freeGeom)
- XkbFreeGeometry(geom,XkbGeomAllMask,TRUE);
- return Success;
-}
-
-int
-ProcXkbGetGeometry(ClientPtr client)
-{
- DeviceIntPtr dev;
- xkbGetGeometryReply rep;
- XkbGeometryPtr geom;
- Bool shouldFree;
- Status status;
-
- REQUEST(xkbGetGeometryReq);
- REQUEST_SIZE_MATCH(xkbGetGeometryReq);
-
- if (!(client->xkbClientFlags&_XkbClientInitialized))
- return BadAccess;
-
- CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
- CHK_ATOM_OR_NONE(stuff->name);
-
- geom= XkbLookupNamedGeometry(dev,stuff->name,&shouldFree);
- rep.type= X_Reply;
- rep.deviceID= dev->id;
- rep.sequenceNumber= client->sequence;
- rep.length= 0;
- status= XkbComputeGetGeometryReplySize(geom,&rep,stuff->name);
- if (status!=Success)
- return status;
- else return XkbSendGeometry(client,geom,&rep,shouldFree);
-}
-
-/***====================================================================***/
-
-static char *
-_GetCountedString(char **wire_inout,Bool swap)
-{
-char * wire,*str;
-CARD16 len,*plen;
-
- wire= *wire_inout;
- plen= (CARD16 *)wire;
- if (swap) {
- register int n;
- swaps(plen,n);
- }
- len= *plen;
- str= malloc(len+1);
- if (str) {
- memcpy(str,&wire[2],len);
- str[len]= '\0';
- }
- wire+= XkbPaddedSize(len+2);
- *wire_inout= wire;
- return str;
-}
-
-static Status
-_CheckSetDoodad( char ** wire_inout,
- XkbGeometryPtr geom,
- XkbSectionPtr section,
- ClientPtr client)
-{
-char * wire;
-xkbDoodadWireDesc * dWire;
-XkbDoodadPtr doodad;
-
- dWire= (xkbDoodadWireDesc *)(*wire_inout);
- wire= (char *)&dWire[1];
- if (client->swapped) {
- register int n;
- swapl(&dWire->any.name,n);
- swaps(&dWire->any.top,n);
- swaps(&dWire->any.left,n);
- swaps(&dWire->any.angle,n);
- }
- CHK_ATOM_ONLY(dWire->any.name);
- doodad= XkbAddGeomDoodad(geom,section,dWire->any.name);
- if (!doodad)
- return BadAlloc;
- doodad->any.type= dWire->any.type;
- doodad->any.priority= dWire->any.priority;
- doodad->any.top= dWire->any.top;
- doodad->any.left= dWire->any.left;
- doodad->any.angle= dWire->any.angle;
- switch (doodad->any.type) {
- case XkbOutlineDoodad:
- case XkbSolidDoodad:
- if (dWire->shape.colorNdx>=geom->num_colors) {
- client->errorValue= _XkbErrCode3(0x40,geom->num_colors,
- dWire->shape.colorNdx);
- return BadMatch;
- }
- if (dWire->shape.shapeNdx>=geom->num_shapes) {
- client->errorValue= _XkbErrCode3(0x41,geom->num_shapes,
- dWire->shape.shapeNdx);
- return BadMatch;
- }
- doodad->shape.color_ndx= dWire->shape.colorNdx;
- doodad->shape.shape_ndx= dWire->shape.shapeNdx;
- break;
- case XkbTextDoodad:
- if (dWire->text.colorNdx>=geom->num_colors) {
- client->errorValue= _XkbErrCode3(0x42,geom->num_colors,
- dWire->text.colorNdx);
- return BadMatch;
- }
- if (client->swapped) {
- register int n;
- swaps(&dWire->text.width,n);
- swaps(&dWire->text.height,n);
- }
- doodad->text.width= dWire->text.width;
- doodad->text.height= dWire->text.height;
- doodad->text.color_ndx= dWire->text.colorNdx;
- doodad->text.text= _GetCountedString(&wire,client->swapped);
- doodad->text.font= _GetCountedString(&wire,client->swapped);
- break;
- case XkbIndicatorDoodad:
- if (dWire->indicator.onColorNdx>=geom->num_colors) {
- client->errorValue= _XkbErrCode3(0x43,geom->num_colors,
- dWire->indicator.onColorNdx);
- return BadMatch;
- }
- if (dWire->indicator.offColorNdx>=geom->num_colors) {
- client->errorValue= _XkbErrCode3(0x44,geom->num_colors,
- dWire->indicator.offColorNdx);
- return BadMatch;
- }
- if (dWire->indicator.shapeNdx>=geom->num_shapes) {
- client->errorValue= _XkbErrCode3(0x45,geom->num_shapes,
- dWire->indicator.shapeNdx);
- return BadMatch;
- }
- doodad->indicator.shape_ndx= dWire->indicator.shapeNdx;
- doodad->indicator.on_color_ndx= dWire->indicator.onColorNdx;
- doodad->indicator.off_color_ndx= dWire->indicator.offColorNdx;
- break;
- case XkbLogoDoodad:
- if (dWire->logo.colorNdx>=geom->num_colors) {
- client->errorValue= _XkbErrCode3(0x46,geom->num_colors,
- dWire->logo.colorNdx);
- return BadMatch;
- }
- if (dWire->logo.shapeNdx>=geom->num_shapes) {
- client->errorValue= _XkbErrCode3(0x47,geom->num_shapes,
- dWire->logo.shapeNdx);
- return BadMatch;
- }
- doodad->logo.color_ndx= dWire->logo.colorNdx;
- doodad->logo.shape_ndx= dWire->logo.shapeNdx;
- doodad->logo.logo_name= _GetCountedString(&wire,client->swapped);
- break;
- default:
- client->errorValue= _XkbErrCode2(0x4F,dWire->any.type);
- return BadValue;
- }
- *wire_inout= wire;
- return Success;
-}
-
-static Status
-_CheckSetOverlay( char ** wire_inout,
- XkbGeometryPtr geom,
- XkbSectionPtr section,
- ClientPtr client)
-{
-register int r;
-char * wire;
-XkbOverlayPtr ol;
-xkbOverlayWireDesc * olWire;
-xkbOverlayRowWireDesc * rWire;
-
- wire= *wire_inout;
- olWire= (xkbOverlayWireDesc *)wire;
- if (client->swapped) {
- register int n;
- swapl(&olWire->name,n);
- }
- CHK_ATOM_ONLY(olWire->name);
- ol= XkbAddGeomOverlay(section,olWire->name,olWire->nRows);
- rWire= (xkbOverlayRowWireDesc *)&olWire[1];
- for (r=0;r<olWire->nRows;r++) {
- register int k;
- xkbOverlayKeyWireDesc * kWire;
- XkbOverlayRowPtr row;
-
- if (rWire->rowUnder>section->num_rows) {
- client->errorValue= _XkbErrCode4(0x20,r,section->num_rows,
- rWire->rowUnder);
- return BadMatch;
- }
- row= XkbAddGeomOverlayRow(ol,rWire->rowUnder,rWire->nKeys);
- kWire= (xkbOverlayKeyWireDesc *)&rWire[1];
- for (k=0;k<rWire->nKeys;k++,kWire++) {
- if (XkbAddGeomOverlayKey(ol,row,
- (char *)kWire->over,(char *)kWire->under)==NULL) {
- client->errorValue= _XkbErrCode3(0x21,r,k);
- return BadMatch;
- }
- }
- rWire= (xkbOverlayRowWireDesc *)kWire;
- }
- olWire= (xkbOverlayWireDesc *)rWire;
- wire= (char *)olWire;
- *wire_inout= wire;
- return Success;
-}
-
-static Status
-_CheckSetSections( XkbGeometryPtr geom,
- xkbSetGeometryReq * req,
- char ** wire_inout,
- ClientPtr client)
-{
-Status status;
-register int s;
-char * wire;
-xkbSectionWireDesc * sWire;
-XkbSectionPtr section;
-
- wire= *wire_inout;
- if (req->nSections<1)
- return Success;
- sWire= (xkbSectionWireDesc *)wire;
- for (s=0;s<req->nSections;s++) {
- register int r;
- xkbRowWireDesc * rWire;
- if (client->swapped) {
- register int n;
- swapl(&sWire->name,n);
- swaps(&sWire->top,n);
- swaps(&sWire->left,n);
- swaps(&sWire->width,n);
- swaps(&sWire->height,n);
- swaps(&sWire->angle,n);
- }
- CHK_ATOM_ONLY(sWire->name);
- section= XkbAddGeomSection(geom,sWire->name,sWire->nRows,
- sWire->nDoodads,sWire->nOverlays);
- if (!section)
- return BadAlloc;
- section->priority= sWire->priority;
- section->top= sWire->top;
- section->left= sWire->left;
- section->width= sWire->width;
- section->height= sWire->height;
- section->angle= sWire->angle;
- rWire= (xkbRowWireDesc *)&sWire[1];
- for (r=0;r<sWire->nRows;r++) {
- register int k;
- XkbRowPtr row;
- xkbKeyWireDesc * kWire;
- if (client->swapped) {
- register int n;
- swaps(&rWire->top,n);
- swaps(&rWire->left,n);
- }
- row= XkbAddGeomRow(section,rWire->nKeys);
- if (!row)
- return BadAlloc;
- row->top= rWire->top;
- row->left= rWire->left;
- row->vertical= rWire->vertical;
- kWire= (xkbKeyWireDesc *)&rWire[1];
- for (k=0;k<rWire->nKeys;k++) {
- XkbKeyPtr key;
- key= XkbAddGeomKey(row);
- if (!key)
- return BadAlloc;
- memcpy(key->name.name,kWire[k].name,XkbKeyNameLength);
- key->gap= kWire[k].gap;
- key->shape_ndx= kWire[k].shapeNdx;
- key->color_ndx= kWire[k].colorNdx;
- if (key->shape_ndx>=geom->num_shapes) {
- client->errorValue= _XkbErrCode3(0x10,key->shape_ndx,
- geom->num_shapes);
- return BadMatch;
- }
- if (key->color_ndx>=geom->num_colors) {
- client->errorValue= _XkbErrCode3(0x11,key->color_ndx,
- geom->num_colors);
- return BadMatch;
- }
- }
- rWire= (xkbRowWireDesc *)&kWire[rWire->nKeys];
- }
- wire= (char *)rWire;
- if (sWire->nDoodads>0) {
- register int d;
- for (d=0;d<sWire->nDoodads;d++) {
- status=_CheckSetDoodad(&wire,geom,section,client);
- if (status!=Success)
- return status;
- }
- }
- if (sWire->nOverlays>0) {
- register int o;
- for (o=0;o<sWire->nOverlays;o++) {
- status= _CheckSetOverlay(&wire,geom,section,client);
- if (status!=Success)
- return status;
- }
- }
- sWire= (xkbSectionWireDesc *)wire;
- }
- wire= (char *)sWire;
- *wire_inout= wire;
- return Success;
-}
-
-static Status
-_CheckSetShapes( XkbGeometryPtr geom,
- xkbSetGeometryReq * req,
- char ** wire_inout,
- ClientPtr client)
-{
-register int i;
-char * wire;
-
- wire= *wire_inout;
- if (req->nShapes<1) {
- client->errorValue= _XkbErrCode2(0x06,req->nShapes);
- return BadValue;
- }
- else {
- xkbShapeWireDesc * shapeWire;
- XkbShapePtr shape;
- register int o;
- shapeWire= (xkbShapeWireDesc *)wire;
- for (i=0;i<req->nShapes;i++) {
- xkbOutlineWireDesc * olWire;
- XkbOutlinePtr ol;
- shape= XkbAddGeomShape(geom,shapeWire->name,shapeWire->nOutlines);
- if (!shape)
- return BadAlloc;
- olWire= (xkbOutlineWireDesc *)(&shapeWire[1]);
- for (o=0;o<shapeWire->nOutlines;o++) {
- register int p;
- XkbPointPtr pt;
- xkbPointWireDesc * ptWire;
-
- ol= XkbAddGeomOutline(shape,olWire->nPoints);
- if (!ol)
- return BadAlloc;
- ol->corner_radius= olWire->cornerRadius;
- ptWire= (xkbPointWireDesc *)&olWire[1];
- for (p=0,pt=ol->points;p<olWire->nPoints;p++,pt++) {
- pt->x= ptWire[p].x;
- pt->y= ptWire[p].y;
- if (client->swapped) {
- register int n;
- swaps(&pt->x,n);
- swaps(&pt->y,n);
- }
- }
- ol->num_points= olWire->nPoints;
- olWire= (xkbOutlineWireDesc *)(&ptWire[olWire->nPoints]);
- }
- if (shapeWire->primaryNdx!=XkbNoShape)
- shape->primary= &shape->outlines[shapeWire->primaryNdx];
- if (shapeWire->approxNdx!=XkbNoShape)
- shape->approx= &shape->outlines[shapeWire->approxNdx];
- shapeWire= (xkbShapeWireDesc *)olWire;
- }
- wire= (char *)shapeWire;
- }
- if (geom->num_shapes!=req->nShapes) {
- client->errorValue= _XkbErrCode3(0x07,geom->num_shapes,req->nShapes);
- return BadMatch;
- }
-
- *wire_inout= wire;
- return Success;
-}
-
-static Status
-_CheckSetGeom( XkbGeometryPtr geom,
- xkbSetGeometryReq * req,
- ClientPtr client)
-{
-register int i;
-Status status;
-char * wire;
-
- wire= (char *)&req[1];
- geom->label_font= _GetCountedString(&wire,client->swapped);
-
- for (i=0;i<req->nProperties;i++) {
- char *name,*val;
- name= _GetCountedString(&wire,client->swapped);
- if (!name)
- return BadAlloc;
- val= _GetCountedString(&wire,client->swapped);
- if (!val) {
- free(name);
- return BadAlloc;
- }
- if (XkbAddGeomProperty(geom,name,val)==NULL) {
- free(name);
- free(val);
- return BadAlloc;
- }
- free(name);
- free(val);
- }
-
- if (req->nColors<2) {
- client->errorValue= _XkbErrCode3(0x01,2,req->nColors);
- return BadValue;
- }
- if (req->baseColorNdx>req->nColors) {
- client->errorValue=_XkbErrCode3(0x03,req->nColors,req->baseColorNdx);
- return BadMatch;
- }
- if (req->labelColorNdx>req->nColors) {
- client->errorValue= _XkbErrCode3(0x03,req->nColors,req->labelColorNdx);
- return BadMatch;
- }
- if (req->labelColorNdx==req->baseColorNdx) {
- client->errorValue= _XkbErrCode3(0x04,req->baseColorNdx,
- req->labelColorNdx);
- return BadMatch;
- }
-
- for (i=0;i<req->nColors;i++) {
- char *name;
- name= _GetCountedString(&wire,client->swapped);
- if (!name)
- return BadAlloc;
- if (!XkbAddGeomColor(geom,name,geom->num_colors)) {
- free(name);
- return BadAlloc;
- }
- free(name);
- }
- if (req->nColors!=geom->num_colors) {
- client->errorValue= _XkbErrCode3(0x05,req->nColors,geom->num_colors);
- return BadMatch;
- }
- geom->label_color= &geom->colors[req->labelColorNdx];
- geom->base_color= &geom->colors[req->baseColorNdx];
-
- if ((status=_CheckSetShapes(geom,req,&wire,client))!=Success)
- return status;
-
- if ((status=_CheckSetSections(geom,req,&wire,client))!=Success)
- return status;
-
- for (i=0;i<req->nDoodads;i++) {
- status=_CheckSetDoodad(&wire,geom,NULL,client);
- if (status!=Success)
- return status;
- }
-
- for (i=0;i<req->nKeyAliases;i++) {
- if (XkbAddGeomKeyAlias(geom,&wire[XkbKeyNameLength],wire)==NULL)
- return BadAlloc;
- wire+= 2*XkbKeyNameLength;
- }
- return Success;
-}
-
-static int
-_XkbSetGeometry(ClientPtr client, DeviceIntPtr dev, xkbSetGeometryReq *stuff)
-{
- XkbDescPtr xkb;
- Bool new_name;
- xkbNewKeyboardNotify nkn;
- XkbGeometryPtr geom,old;
- XkbGeometrySizesRec sizes;
- Status status;
-
- xkb= dev->key->xkbInfo->desc;
- old= xkb->geom;
- xkb->geom= NULL;
-
- sizes.which= XkbGeomAllMask;
- sizes.num_properties= stuff->nProperties;
- sizes.num_colors= stuff->nColors;
- sizes.num_shapes= stuff->nShapes;
- sizes.num_sections= stuff->nSections;
- sizes.num_doodads= stuff->nDoodads;
- sizes.num_key_aliases= stuff->nKeyAliases;
- if ((status= XkbAllocGeometry(xkb,&sizes))!=Success) {
- xkb->geom= old;
- return status;
- }
- geom= xkb->geom;
- geom->name= stuff->name;
- geom->width_mm= stuff->widthMM;
- geom->height_mm= stuff->heightMM;
- if ((status= _CheckSetGeom(geom,stuff,client))!=Success) {
- XkbFreeGeometry(geom,XkbGeomAllMask,TRUE);
- xkb->geom= old;
- return status;
- }
- new_name= (xkb->names->geometry!=geom->name);
- xkb->names->geometry= geom->name;
- if (old)
- XkbFreeGeometry(old,XkbGeomAllMask,TRUE);
- if (new_name) {
- xkbNamesNotify nn;
- memset(&nn, 0, sizeof(xkbNamesNotify));
- nn.changed= XkbGeometryNameMask;
- XkbSendNamesNotify(dev,&nn);
- }
- nkn.deviceID= nkn.oldDeviceID= dev->id;
- nkn.minKeyCode= nkn.oldMinKeyCode= xkb->min_key_code;
- nkn.maxKeyCode= nkn.oldMaxKeyCode= xkb->max_key_code;
- nkn.requestMajor= XkbReqCode;
- nkn.requestMinor= X_kbSetGeometry;
- nkn.changed= XkbNKN_GeometryMask;
- XkbSendNewKeyboardNotify(dev,&nkn);
- return Success;
-}
-
-int
-ProcXkbSetGeometry(ClientPtr client)
-{
- DeviceIntPtr dev;
- int rc;
-
- REQUEST(xkbSetGeometryReq);
- REQUEST_AT_LEAST_SIZE(xkbSetGeometryReq);
-
- if (!(client->xkbClientFlags&_XkbClientInitialized))
- return BadAccess;
-
- CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess);
- CHK_ATOM_OR_NONE(stuff->name);
-
- rc = _XkbSetGeometry(client, dev, stuff);
- if (rc != Success)
- return rc;
-
- if (stuff->deviceSpec == XkbUseCoreKbd)
- {
- DeviceIntPtr other;
- for (other = inputInfo.devices; other; other = other->next)
- {
- if ((other != dev) && other->key && !IsMaster(other) && GetMaster(other, MASTER_KEYBOARD) == dev)
- {
- rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixManageAccess);
- if (rc == Success)
- _XkbSetGeometry(client, other, stuff);
- }
- }
- }
-
- return Success;
-}
-
-/***====================================================================***/
-
-int
-ProcXkbPerClientFlags(ClientPtr client)
-{
- DeviceIntPtr dev;
- xkbPerClientFlagsReply rep;
- XkbInterestPtr interest;
- Mask access_mode = DixGetAttrAccess | DixSetAttrAccess;
-
- REQUEST(xkbPerClientFlagsReq);
- REQUEST_SIZE_MATCH(xkbPerClientFlagsReq);
-
- if (!(client->xkbClientFlags&_XkbClientInitialized))
- return BadAccess;
-
- CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, access_mode);
- CHK_MASK_LEGAL(0x01,stuff->change,XkbPCF_AllFlagsMask);
- CHK_MASK_MATCH(0x02,stuff->change,stuff->value);
-
- interest = XkbFindClientResource((DevicePtr)dev,client);
- memset(&rep, 0, sizeof(xkbPerClientFlagsReply));
- rep.type= X_Reply;
- rep.length = 0;
- rep.sequenceNumber = client->sequence;
- if (stuff->change) {
- client->xkbClientFlags&= ~stuff->change;
- client->xkbClientFlags|= stuff->value;
- }
- if (stuff->change&XkbPCF_AutoResetControlsMask) {
- Bool want;
- want= stuff->value&XkbPCF_AutoResetControlsMask;
- if (interest && !want) {
- interest->autoCtrls= interest->autoCtrlValues= 0;
- }
- else if (want && (!interest)) {
- XID id = FakeClientID(client->index);
- if (!AddResource(id,RT_XKBCLIENT,dev))
- return BadAlloc;
- interest= XkbAddClientResource((DevicePtr)dev,client,id);
- if (!interest)
- return BadAlloc;
- }
- if (interest && want ) {
- register unsigned affect;
- affect= stuff->ctrlsToChange;
-
- CHK_MASK_LEGAL(0x03,affect,XkbAllBooleanCtrlsMask);
- CHK_MASK_MATCH(0x04,affect,stuff->autoCtrls);
- CHK_MASK_MATCH(0x05,stuff->autoCtrls,stuff->autoCtrlValues);
-
- interest->autoCtrls&= ~affect;
- interest->autoCtrlValues&= ~affect;
- interest->autoCtrls|= stuff->autoCtrls&affect;
- interest->autoCtrlValues|= stuff->autoCtrlValues&affect;
- }
- }
- rep.supported = XkbPCF_AllFlagsMask;
- rep.value= client->xkbClientFlags&XkbPCF_AllFlagsMask;
- if (interest) {
- rep.autoCtrls= interest->autoCtrls;
- rep.autoCtrlValues= interest->autoCtrlValues;
- }
- else {
- rep.autoCtrls= rep.autoCtrlValues= 0;
- }
- if ( client->swapped ) {
- register int n;
- swaps(&rep.sequenceNumber, n);
- swapl(&rep.supported,n);
- swapl(&rep.value,n);
- swapl(&rep.autoCtrls,n);
- swapl(&rep.autoCtrlValues,n);
- }
- WriteToClient(client,SIZEOF(xkbPerClientFlagsReply), (char *)&rep);
- return Success;
-}
-
-/***====================================================================***/
-
-/* all latin-1 alphanumerics, plus parens, minus, underscore, slash */
-/* and wildcards */
-static unsigned char componentSpecLegal[] = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0xa7, 0xff, 0x87,
- 0xfe, 0xff, 0xff, 0x87, 0xfe, 0xff, 0xff, 0x07,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0x7f, 0xff
-};
-
-/* same as above but accepts percent, plus and bar too */
-static unsigned char componentExprLegal[] = {
- 0x00, 0x00, 0x00, 0x00, 0x20, 0xaf, 0xff, 0x87,
- 0xfe, 0xff, 0xff, 0x87, 0xfe, 0xff, 0xff, 0x17,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0x7f, 0xff
-};
-
-static char *
-GetComponentSpec(unsigned char **pWire,Bool allowExpr,int *errRtrn)
-{
-int len;
-register int i;
-unsigned char *wire,*str,*tmp,*legal;
-
- if (allowExpr) legal= &componentExprLegal[0];
- else legal= &componentSpecLegal[0];
-
- wire= *pWire;
- len= (*(unsigned char *)wire++);
- if (len>0) {
- str= calloc(1, len+1);
- if (str) {
- tmp= str;
- for (i=0;i<len;i++) {
- if (legal[(*wire)/8]&(1<<((*wire)%8)))
- *tmp++= *wire++;
- else wire++;
- }
- if (tmp!=str)
- *tmp++= '\0';
- else {
- free(str);
- str= NULL;
- }
- }
- else {
- *errRtrn= BadAlloc;
- }
- }
- else {
- str= NULL;
- }
- *pWire= wire;
- return (char *)str;
-}
-
-/***====================================================================***/
-
-int
-ProcXkbListComponents(ClientPtr client)
-{
- DeviceIntPtr dev;
- xkbListComponentsReply rep;
- unsigned len;
- int status;
- unsigned char * str;
- XkbSrvListInfoRec list;
-
- REQUEST(xkbListComponentsReq);
- REQUEST_AT_LEAST_SIZE(xkbListComponentsReq);
-
- if (!(client->xkbClientFlags&_XkbClientInitialized))
- return BadAccess;
-
- CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
-
- status= Success;
- str= (unsigned char *)&stuff[1];
- memset(&list, 0, sizeof(XkbSrvListInfoRec));
- list.maxRtrn= stuff->maxNames;
- list.pattern[_XkbListKeycodes]= GetComponentSpec(&str,FALSE,&status);
- list.pattern[_XkbListTypes]= GetComponentSpec(&str,FALSE,&status);
- list.pattern[_XkbListCompat]= GetComponentSpec(&str,FALSE,&status);
- list.pattern[_XkbListSymbols]= GetComponentSpec(&str,FALSE,&status);
- list.pattern[_XkbListGeometry]= GetComponentSpec(&str,FALSE,&status);
- if (status!=Success)
- return status;
- len= str-((unsigned char *)stuff);
- if ((XkbPaddedSize(len)/4)!=stuff->length)
- return BadLength;
- if ((status=XkbDDXList(dev,&list,client))!=Success) {
- free(list.pool);
- list.pool = NULL;
- return status;
- }
- memset(&rep, 0, sizeof(xkbListComponentsReply));
- rep.type= X_Reply;
- rep.deviceID = dev->id;
- rep.sequenceNumber = client->sequence;
- rep.length = XkbPaddedSize(list.nPool)/4;
- rep.nKeymaps = 0;
- rep.nKeycodes = list.nFound[_XkbListKeycodes];
- rep.nTypes = list.nFound[_XkbListTypes];
- rep.nCompatMaps = list.nFound[_XkbListCompat];
- rep.nSymbols = list.nFound[_XkbListSymbols];
- rep.nGeometries = list.nFound[_XkbListGeometry];
- rep.extra= 0;
- if (list.nTotal>list.maxRtrn)
- rep.extra = (list.nTotal-list.maxRtrn);
- if (client->swapped) {
- register int n;
- swaps(&rep.sequenceNumber,n);
- swapl(&rep.length,n);
- swaps(&rep.nKeymaps,n);
- swaps(&rep.nKeycodes,n);
- swaps(&rep.nTypes,n);
- swaps(&rep.nCompatMaps,n);
- swaps(&rep.nSymbols,n);
- swaps(&rep.nGeometries,n);
- swaps(&rep.extra,n);
- }
- WriteToClient(client,SIZEOF(xkbListComponentsReply),(char *)&rep);
- if (list.nPool && list.pool) {
- WriteToClient(client,XkbPaddedSize(list.nPool), (char *)list.pool);
- free(list.pool);
- list.pool= NULL;
- }
- return Success;
-}
-
-/***====================================================================***/
-
-int
-ProcXkbGetKbdByName(ClientPtr client)
-{
- DeviceIntPtr dev;
- DeviceIntPtr tmpd;
- xkbGetKbdByNameReply rep = {0};
- xkbGetMapReply mrep = {0};
- xkbGetCompatMapReply crep = {0};
- xkbGetIndicatorMapReply irep = {0};
- xkbGetNamesReply nrep = {0};
- xkbGetGeometryReply grep = {0};
- XkbComponentNamesRec names = {0};
- XkbDescPtr xkb, new;
- unsigned char * str;
- char mapFile[PATH_MAX];
- unsigned len;
- unsigned fwant,fneed,reported;
- int status;
- Bool geom_changed;
- XkbSrvLedInfoPtr old_sli;
- XkbSrvLedInfoPtr sli;
- Mask access_mode = DixGetAttrAccess | DixManageAccess;
-
- REQUEST(xkbGetKbdByNameReq);
- REQUEST_AT_LEAST_SIZE(xkbGetKbdByNameReq);
-
- if (!(client->xkbClientFlags&_XkbClientInitialized))
- return BadAccess;
-
- CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, access_mode);
-
- xkb = dev->key->xkbInfo->desc;
- status= Success;
- str= (unsigned char *)&stuff[1];
- if (GetComponentSpec(&str,TRUE,&status)) /* keymap, unsupported */
- return BadMatch;
- names.keycodes= GetComponentSpec(&str,TRUE,&status);
- names.types= GetComponentSpec(&str,TRUE,&status);
- names.compat= GetComponentSpec(&str,TRUE,&status);
- names.symbols= GetComponentSpec(&str,TRUE,&status);
- names.geometry= GetComponentSpec(&str,TRUE,&status);
- if (status!=Success)
- return status;
- len= str-((unsigned char *)stuff);
- if ((XkbPaddedSize(len)/4)!=stuff->length)
- return BadLength;
-
- CHK_MASK_LEGAL(0x01,stuff->want,XkbGBN_AllComponentsMask);
- CHK_MASK_LEGAL(0x02,stuff->need,XkbGBN_AllComponentsMask);
-
- if (stuff->load)
- fwant= XkbGBN_AllComponentsMask;
- else fwant= stuff->want|stuff->need;
- if ((!names.compat)&&
- (fwant&(XkbGBN_CompatMapMask|XkbGBN_IndicatorMapMask))) {
- names.compat= _XkbDupString("%");
- }
- if ((!names.types)&&(fwant&(XkbGBN_TypesMask))) {
- names.types= _XkbDupString("%");
- }
- if ((!names.symbols)&&(fwant&XkbGBN_SymbolsMask)) {
- names.symbols= _XkbDupString("%");
- }
- geom_changed= ((names.geometry!=NULL)&&(strcmp(names.geometry,"%")!=0));
- if ((!names.geometry)&&(fwant&XkbGBN_GeometryMask)) {
- names.geometry= _XkbDupString("%");
- geom_changed= FALSE;
- }
-
- memset(mapFile, 0, PATH_MAX);
- rep.type= X_Reply;
- rep.deviceID = dev->id;
- rep.sequenceNumber = client->sequence;
- rep.length = 0;
- rep.minKeyCode = xkb->min_key_code;
- rep.maxKeyCode = xkb->max_key_code;
- rep.loaded= FALSE;
- fwant= XkbConvertGetByNameComponents(TRUE,stuff->want)|XkmVirtualModsMask;
- fneed= XkbConvertGetByNameComponents(TRUE,stuff->need);
- rep.reported= XkbConvertGetByNameComponents(FALSE,fwant|fneed);
- if (stuff->load) {
- fneed|= XkmKeymapRequired;
- fwant|= XkmKeymapLegal;
- }
- if ((fwant|fneed)&XkmSymbolsMask) {
- fneed|= XkmKeyNamesIndex|XkmTypesIndex;
- fwant|= XkmIndicatorsIndex;
- }
-
- /* We pass dev in here so we can get the old names out if needed. */
- rep.found = XkbDDXLoadKeymapByNames(dev,&names,fwant,fneed,&new,
- mapFile,PATH_MAX);
- rep.newKeyboard= FALSE;
- rep.pad1= rep.pad2= rep.pad3= rep.pad4= 0;
-
- stuff->want|= stuff->need;
- if (new==NULL)
- rep.reported= 0;
- else {
- if (stuff->load)
- rep.loaded= TRUE;
- if (stuff->load ||
- ((rep.reported&XkbGBN_SymbolsMask) && (new->compat))) {
- XkbChangesRec changes;
- memset(&changes, 0, sizeof(changes));
- XkbUpdateDescActions(new,
- new->min_key_code,XkbNumKeys(new),
- &changes);
- }
-
- if (new->map==NULL)
- rep.reported&= ~(XkbGBN_SymbolsMask|XkbGBN_TypesMask);
- else if (rep.reported&(XkbGBN_SymbolsMask|XkbGBN_TypesMask)) {
- mrep.type= X_Reply;
- mrep.deviceID = dev->id;
- mrep.sequenceNumber= client->sequence;
- mrep.length = ((SIZEOF(xkbGetMapReply)-SIZEOF(xGenericReply))>>2);
- mrep.minKeyCode = new->min_key_code;
- mrep.maxKeyCode = new->max_key_code;
- mrep.present = 0;
- mrep.totalSyms = mrep.totalActs =
- mrep.totalKeyBehaviors= mrep.totalKeyExplicit=
- mrep.totalModMapKeys= mrep.totalVModMapKeys= 0;
- if (rep.reported&(XkbGBN_TypesMask|XkbGBN_ClientSymbolsMask)) {
- mrep.present|= XkbKeyTypesMask;
- mrep.firstType = 0;
- mrep.nTypes = mrep.totalTypes= new->map->num_types;
- }
- else {
- mrep.firstType = mrep.nTypes= 0;
- mrep.totalTypes= 0;
- }
- if (rep.reported&XkbGBN_ClientSymbolsMask) {
- mrep.present|= (XkbKeySymsMask|XkbModifierMapMask);
- mrep.firstKeySym = mrep.firstModMapKey= new->min_key_code;
- mrep.nKeySyms = mrep.nModMapKeys= XkbNumKeys(new);
- }
- else {
- mrep.firstKeySym= mrep.firstModMapKey= 0;
- mrep.nKeySyms= mrep.nModMapKeys= 0;
- }
- if (rep.reported&XkbGBN_ServerSymbolsMask) {
- mrep.present|= XkbAllServerInfoMask;
- mrep.virtualMods= ~0;
- mrep.firstKeyAct = mrep.firstKeyBehavior =
- mrep.firstKeyExplicit = new->min_key_code;
- mrep.nKeyActs = mrep.nKeyBehaviors =
- mrep.nKeyExplicit = XkbNumKeys(new);
- mrep.firstVModMapKey= new->min_key_code;
- mrep.nVModMapKeys= XkbNumKeys(new);
- }
- else {
- mrep.virtualMods= 0;
- mrep.firstKeyAct= mrep.firstKeyBehavior=
- mrep.firstKeyExplicit = 0;
- mrep.nKeyActs= mrep.nKeyBehaviors= mrep.nKeyExplicit= 0;
- }
- XkbComputeGetMapReplySize(new,&mrep);
- rep.length+= SIZEOF(xGenericReply)/4+mrep.length;
- }
- if (new->compat==NULL)
- rep.reported&= ~XkbGBN_CompatMapMask;
- else if (rep.reported&XkbGBN_CompatMapMask) {
- crep.type= X_Reply;
- crep.deviceID= dev->id;
- crep.sequenceNumber= client->sequence;
- crep.length= 0;
- crep.groups= XkbAllGroupsMask;
- crep.firstSI= 0;
- crep.nSI= crep.nTotalSI= new->compat->num_si;
- XkbComputeGetCompatMapReplySize(new->compat,&crep);
- rep.length+= SIZEOF(xGenericReply)/4+crep.length;
- }
- if (new->indicators==NULL)
- rep.reported&= ~XkbGBN_IndicatorMapMask;
- else if (rep.reported&XkbGBN_IndicatorMapMask) {
- irep.type= X_Reply;
- irep.deviceID= dev->id;
- irep.sequenceNumber= client->sequence;
- irep.length= 0;
- irep.which= XkbAllIndicatorsMask;
- XkbComputeGetIndicatorMapReplySize(new->indicators,&irep);
- rep.length+= SIZEOF(xGenericReply)/4+irep.length;
- }
- if (new->names==NULL)
- rep.reported&= ~(XkbGBN_OtherNamesMask|XkbGBN_KeyNamesMask);
- else if (rep.reported&(XkbGBN_OtherNamesMask|XkbGBN_KeyNamesMask)) {
- nrep.type= X_Reply;
- nrep.deviceID= dev->id;
- nrep.sequenceNumber= client->sequence;
- nrep.length= 0;
- nrep.minKeyCode= new->min_key_code;
- nrep.maxKeyCode= new->max_key_code;
- if (rep.reported&XkbGBN_OtherNamesMask) {
- nrep.which= XkbAllNamesMask;
- if (new->map!=NULL)
- nrep.nTypes= new->map->num_types;
- else nrep.nTypes= 0;
- nrep.nKTLevels= 0;
- nrep.groupNames= XkbAllGroupsMask;
- nrep.virtualMods= XkbAllVirtualModsMask;
- nrep.indicators= XkbAllIndicatorsMask;
- nrep.nRadioGroups= new->names->num_rg;
- }
- else {
- nrep.which= 0;
- nrep.nTypes= 0;
- nrep.nKTLevels= 0;
- nrep.groupNames= 0;
- nrep.virtualMods= 0;
- nrep.indicators= 0;
- nrep.nRadioGroups= 0;
- }
- if (rep.reported&XkbGBN_KeyNamesMask) {
- nrep.which|= XkbKeyNamesMask;
- nrep.firstKey= new->min_key_code;
- nrep.nKeys= XkbNumKeys(new);
- nrep.nKeyAliases= new->names->num_key_aliases;
- if (nrep.nKeyAliases)
- nrep.which|= XkbKeyAliasesMask;
- }
- else {
- nrep.which&= ~(XkbKeyNamesMask|XkbKeyAliasesMask);
- nrep.firstKey= nrep.nKeys= 0;
- nrep.nKeyAliases= 0;
- }
- XkbComputeGetNamesReplySize(new,&nrep);
- rep.length+= SIZEOF(xGenericReply)/4+nrep.length;
- }
- if (new->geom==NULL)
- rep.reported&= ~XkbGBN_GeometryMask;
- else if (rep.reported&XkbGBN_GeometryMask) {
- grep.type= X_Reply;
- grep.deviceID= dev->id;
- grep.sequenceNumber= client->sequence;
- grep.length= 0;
- grep.found= TRUE;
- grep.pad= 0;
- grep.widthMM= grep.heightMM= 0;
- grep.nProperties= grep.nColors= grep.nShapes= 0;
- grep.nSections= grep.nDoodads= 0;
- grep.baseColorNdx= grep.labelColorNdx= 0;
- XkbComputeGetGeometryReplySize(new->geom,&grep,None);
- rep.length+= SIZEOF(xGenericReply)/4+grep.length;
- }
- }
-
- reported= rep.reported;
- if ( client->swapped ) {
- register int n;
- swaps(&rep.sequenceNumber,n);
- swapl(&rep.length,n);
- swaps(&rep.found,n);
- swaps(&rep.reported,n);
- }
- WriteToClient(client,SIZEOF(xkbGetKbdByNameReply), (char *)&rep);
- if (reported&(XkbGBN_SymbolsMask|XkbGBN_TypesMask))
- XkbSendMap(client,new,&mrep);
- if (reported&XkbGBN_CompatMapMask)
- XkbSendCompatMap(client,new->compat,&crep);
- if (reported&XkbGBN_IndicatorMapMask)
- XkbSendIndicatorMap(client,new->indicators,&irep);
- if (reported&(XkbGBN_KeyNamesMask|XkbGBN_OtherNamesMask))
- XkbSendNames(client,new,&nrep);
- if (reported&XkbGBN_GeometryMask)
- XkbSendGeometry(client,new->geom,&grep,FALSE);
- if (rep.loaded) {
- XkbDescPtr old_xkb;
- xkbNewKeyboardNotify nkn;
- int i,nG,nTG;
- old_xkb= xkb;
- xkb= new;
- dev->key->xkbInfo->desc= xkb;
- new= old_xkb; /* so it'll get freed automatically */
-
- *xkb->ctrls= *old_xkb->ctrls;
- for (nG=nTG=0,i=xkb->min_key_code;i<=xkb->max_key_code;i++) {
- nG= XkbKeyNumGroups(xkb,i);
- if (nG>=XkbNumKbdGroups) {
- nTG= XkbNumKbdGroups;
- break;
- }
- if (nG>nTG) {
- nTG= nG;
- }
- }
- xkb->ctrls->num_groups= nTG;
-
- for (tmpd = inputInfo.devices; tmpd; tmpd = tmpd->next) {
- if ((tmpd == dev) || (!IsMaster(tmpd) && GetMaster(tmpd, MASTER_KEYBOARD) == dev)) {
- if (tmpd != dev)
- XkbCopyDeviceKeymap(tmpd, dev);
-
- if (tmpd->kbdfeed && tmpd->kbdfeed->xkb_sli) {
- old_sli = tmpd->kbdfeed->xkb_sli;
- tmpd->kbdfeed->xkb_sli = NULL;
- sli = XkbAllocSrvLedInfo(tmpd, tmpd->kbdfeed, NULL, 0);
- if (sli) {
- sli->explicitState = old_sli->explicitState;
- sli->effectiveState = old_sli->effectiveState;
- }
- tmpd->kbdfeed->xkb_sli = sli;
- XkbFreeSrvLedInfo(old_sli);
- }
- }
- }
-
- nkn.deviceID= nkn.oldDeviceID= dev->id;
- nkn.minKeyCode= new->min_key_code;
- nkn.maxKeyCode= new->max_key_code;
- nkn.oldMinKeyCode= xkb->min_key_code;
- nkn.oldMaxKeyCode= xkb->max_key_code;
- nkn.requestMajor= XkbReqCode;
- nkn.requestMinor= X_kbGetKbdByName;
- nkn.changed= XkbNKN_KeycodesMask;
- if (geom_changed)
- nkn.changed|= XkbNKN_GeometryMask;
- XkbSendNewKeyboardNotify(dev,&nkn);
-
- if (!IsMaster(dev) && dev->u.master)
- {
- DeviceIntPtr master = dev->u.master;
- if (master->u.lastSlave == dev)
- {
- XkbCopyDeviceKeymap(dev->u.master, dev);
- XkbSendNewKeyboardNotify(dev,&nkn);
- }
- }
- }
- if ((new!=NULL)&&(new!=xkb)) {
- XkbFreeKeyboard(new,XkbAllComponentsMask,TRUE);
- new= NULL;
- }
- free(names.keycodes);
- names.keycodes = NULL;
- free(names.types);
- names.types = NULL;
- free(names.compat);
- names.compat = NULL;
- free(names.symbols);
- names.symbols = NULL;
- free(names.geometry);
- names.geometry = NULL;
- return Success;
-}
-
-/***====================================================================***/
-
-static int
-ComputeDeviceLedInfoSize( DeviceIntPtr dev,
- unsigned int what,
- XkbSrvLedInfoPtr sli)
-{
-int nNames,nMaps;
-register unsigned n,bit;
-
- if (sli==NULL)
- return 0;
- nNames= nMaps= 0;
- if ((what&XkbXI_IndicatorNamesMask)==0)
- sli->namesPresent= 0;
- if ((what&XkbXI_IndicatorMapsMask)==0)
- sli->mapsPresent= 0;
-
- for (n=0,bit=1;n<XkbNumIndicators;n++,bit<<=1) {
- if (sli->names && sli->names[n]!=None) {
- sli->namesPresent|= bit;
- nNames++;
- }
- if (sli->maps && XkbIM_InUse(&sli->maps[n])) {
- sli->mapsPresent|= bit;
- nMaps++;
- }
- }
- return (nNames*4)+(nMaps*SIZEOF(xkbIndicatorMapWireDesc));
-}
-
-static int
-CheckDeviceLedFBs( DeviceIntPtr dev,
- int class,
- int id,
- xkbGetDeviceInfoReply * rep,
- ClientPtr client)
-{
-int nFBs= 0;
-int length= 0;
-Bool classOk;
-
- if (class==XkbDfltXIClass) {
- if (dev->kbdfeed) class= KbdFeedbackClass;
- else if (dev->leds) class= LedFeedbackClass;
- else {
- client->errorValue= _XkbErrCode2(XkbErr_BadClass,class);
- return XkbKeyboardErrorCode;
- }
- }
- classOk= FALSE;
- if ((dev->kbdfeed)&&((class==KbdFeedbackClass)||(class==XkbAllXIClasses))) {
- KbdFeedbackPtr kf;
- classOk= TRUE;
- for (kf= dev->kbdfeed;(kf);kf=kf->next) {
- if ((id!=XkbAllXIIds)&&(id!=XkbDfltXIId)&&(id!=kf->ctrl.id))
- continue;
- nFBs++;
- length+= SIZEOF(xkbDeviceLedsWireDesc);
- if (!kf->xkb_sli)
- kf->xkb_sli= XkbAllocSrvLedInfo(dev,kf,NULL,0);
- length+= ComputeDeviceLedInfoSize(dev,rep->present,kf->xkb_sli);
- if (id!=XkbAllXIIds)
- break;
- }
- }
- if ((dev->leds)&&((class==LedFeedbackClass)||(class==XkbAllXIClasses))) {
- LedFeedbackPtr lf;
- classOk= TRUE;
- for (lf= dev->leds;(lf);lf=lf->next) {
- if ((id!=XkbAllXIIds)&&(id!=XkbDfltXIId)&&(id!=lf->ctrl.id))
- continue;
- nFBs++;
- length+= SIZEOF(xkbDeviceLedsWireDesc);
- if (!lf->xkb_sli)
- lf->xkb_sli= XkbAllocSrvLedInfo(dev,NULL,lf,0);
- length+= ComputeDeviceLedInfoSize(dev,rep->present,lf->xkb_sli);
- if (id!=XkbAllXIIds)
- break;
- }
- }
- if (nFBs>0) {
- rep->nDeviceLedFBs= nFBs;
- rep->length+= (length/4);
- return Success;
- }
- if (classOk) client->errorValue= _XkbErrCode2(XkbErr_BadId,id);
- else client->errorValue= _XkbErrCode2(XkbErr_BadClass,class);
- return XkbKeyboardErrorCode;
-}
-
-static int
-SendDeviceLedInfo( XkbSrvLedInfoPtr sli,
- ClientPtr client)
-{
-xkbDeviceLedsWireDesc wire;
-int length;
-
- length= 0;
- wire.ledClass= sli->class;
- wire.ledID= sli->id;
- wire.namesPresent= sli->namesPresent;
- wire.mapsPresent= sli->mapsPresent;
- wire.physIndicators= sli->physIndicators;
- wire.state= sli->effectiveState;
- if (client->swapped) {
- register int n;
- swaps(&wire.ledClass,n);
- swaps(&wire.ledID,n);
- swapl(&wire.namesPresent,n);
- swapl(&wire.mapsPresent,n);
- swapl(&wire.physIndicators,n);
- swapl(&wire.state,n);
- }
- WriteToClient(client,SIZEOF(xkbDeviceLedsWireDesc),(char *)&wire);
- length+= SIZEOF(xkbDeviceLedsWireDesc);
- if (sli->namesPresent|sli->mapsPresent) {
- register unsigned i,bit;
- if (sli->namesPresent) {
- CARD32 awire;
- for (i=0,bit=1;i<XkbNumIndicators;i++,bit<<=1) {
- if (sli->namesPresent&bit) {
- awire= (CARD32)sli->names[i];
- if (client->swapped) {
- register int n;
- swapl(&awire,n);
- }
- WriteToClient(client,4,(char *)&awire);
- length+= 4;
- }
- }
- }
- if (sli->mapsPresent) {
- for (i=0,bit=1;i<XkbNumIndicators;i++,bit<<=1) {
- xkbIndicatorMapWireDesc iwire;
- if (sli->mapsPresent&bit) {
- iwire.flags= sli->maps[i].flags;
- iwire.whichGroups= sli->maps[i].which_groups;
- iwire.groups= sli->maps[i].groups;
- iwire.whichMods= sli->maps[i].which_mods;
- iwire.mods= sli->maps[i].mods.mask;
- iwire.realMods= sli->maps[i].mods.real_mods;
- iwire.virtualMods= sli->maps[i].mods.vmods;
- iwire.ctrls= sli->maps[i].ctrls;
- if (client->swapped) {
- register int n;
- swaps(&iwire.virtualMods,n);
- swapl(&iwire.ctrls,n);
- }
- WriteToClient(client,SIZEOF(xkbIndicatorMapWireDesc),
- (char *)&iwire);
- length+= SIZEOF(xkbIndicatorMapWireDesc);
- }
- }
- }
- }
- return length;
-}
-
-static int
-SendDeviceLedFBs( DeviceIntPtr dev,
- int class,
- int id,
- unsigned wantLength,
- ClientPtr client)
-{
-int length= 0;
-
- if (class==XkbDfltXIClass) {
- if (dev->kbdfeed) class= KbdFeedbackClass;
- else if (dev->leds) class= LedFeedbackClass;
- }
- if ((dev->kbdfeed)&&
- ((class==KbdFeedbackClass)||(class==XkbAllXIClasses))) {
- KbdFeedbackPtr kf;
- for (kf= dev->kbdfeed;(kf);kf=kf->next) {
- if ((id==XkbAllXIIds)||(id==XkbDfltXIId)||(id==kf->ctrl.id)) {
- length+= SendDeviceLedInfo(kf->xkb_sli,client);
- if (id!=XkbAllXIIds)
- break;
- }
- }
- }
- if ((dev->leds)&&
- ((class==LedFeedbackClass)||(class==XkbAllXIClasses))) {
- LedFeedbackPtr lf;
- for (lf= dev->leds;(lf);lf=lf->next) {
- if ((id==XkbAllXIIds)||(id==XkbDfltXIId)||(id==lf->ctrl.id)) {
- length+= SendDeviceLedInfo(lf->xkb_sli,client);
- if (id!=XkbAllXIIds)
- break;
- }
- }
- }
- if (length==wantLength)
- return Success;
- else return BadLength;
-}
-
-int
-ProcXkbGetDeviceInfo(ClientPtr client)
-{
-DeviceIntPtr dev;
-xkbGetDeviceInfoReply rep;
-int status,nDeviceLedFBs;
-unsigned length,nameLen;
-CARD16 ledClass,ledID;
-unsigned wanted;
-char * str;
-
- REQUEST(xkbGetDeviceInfoReq);
- REQUEST_SIZE_MATCH(xkbGetDeviceInfoReq);
-
- if (!(client->xkbClientFlags&_XkbClientInitialized))
- return BadAccess;
-
- wanted= stuff->wanted;
-
- CHK_ANY_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
- CHK_MASK_LEGAL(0x01,wanted,XkbXI_AllDeviceFeaturesMask);
-
- if ((!dev->button)||((stuff->nBtns<1)&&(!stuff->allBtns)))
- wanted&= ~XkbXI_ButtonActionsMask;
- if ((!dev->kbdfeed)&&(!dev->leds))
- wanted&= ~XkbXI_IndicatorsMask;
-
- nameLen= XkbSizeCountedString(dev->name);
- memset((char *)&rep, 0, SIZEOF(xkbGetDeviceInfoReply));
- rep.type = X_Reply;
- rep.deviceID= dev->id;
- rep.sequenceNumber = client->sequence;
- rep.length = nameLen/4;
- rep.present = wanted;
- rep.supported = XkbXI_AllDeviceFeaturesMask;
- rep.unsupported = 0;
- rep.firstBtnWanted = rep.nBtnsWanted = 0;
- rep.firstBtnRtrn = rep.nBtnsRtrn = 0;
- if (dev->button)
- rep.totalBtns= dev->button->numButtons;
- else rep.totalBtns= 0;
- rep.devType= dev->xinput_type;
- rep.hasOwnState= (dev->key && dev->key->xkbInfo);
- rep.nDeviceLedFBs = 0;
- if (dev->kbdfeed) rep.dfltKbdFB= dev->kbdfeed->ctrl.id;
- else rep.dfltKbdFB= XkbXINone;
- if (dev->leds) rep.dfltLedFB= dev->leds->ctrl.id;
- else rep.dfltLedFB= XkbXINone;
-
- ledClass= stuff->ledClass;
- ledID= stuff->ledID;
-
- rep.firstBtnWanted= rep.nBtnsWanted= 0;
- rep.firstBtnRtrn= rep.nBtnsRtrn= 0;
- if (wanted&XkbXI_ButtonActionsMask) {
- if (stuff->allBtns) {
- stuff->firstBtn= 0;
- stuff->nBtns= dev->button->numButtons;
- }
-
- if ((stuff->firstBtn+stuff->nBtns)>dev->button->numButtons) {
- client->errorValue = _XkbErrCode4(0x02,dev->button->numButtons,
- stuff->firstBtn,
- stuff->nBtns);
- return BadValue;
- }
- else {
- rep.firstBtnWanted= stuff->firstBtn;
- rep.nBtnsWanted= stuff->nBtns;
- if (dev->button->xkb_acts!=NULL) {
- XkbAction *act;
- register int i;
-
- rep.firstBtnRtrn= stuff->firstBtn;
- rep.nBtnsRtrn= stuff->nBtns;
- act= &dev->button->xkb_acts[rep.firstBtnWanted];
- for (i=0;i<rep.nBtnsRtrn;i++,act++) {
- if (act->type!=XkbSA_NoAction)
- break;
- }
- rep.firstBtnRtrn+= i;
- rep.nBtnsRtrn-= i;
- act= &dev->button->xkb_acts[rep.firstBtnRtrn+rep.nBtnsRtrn-1];
- for (i=0;i<rep.nBtnsRtrn;i++,act--) {
- if (act->type!=XkbSA_NoAction)
- break;
- }
- rep.nBtnsRtrn-= i;
- }
- rep.length+= (rep.nBtnsRtrn*SIZEOF(xkbActionWireDesc))/4;
- }
- }
-
- if (wanted&XkbXI_IndicatorsMask) {
- status= CheckDeviceLedFBs(dev,ledClass,ledID,&rep,client);
- if (status!=Success)
- return status;
- }
- length= rep.length*4;
- nDeviceLedFBs = rep.nDeviceLedFBs;
- if (client->swapped) {
- register int n;
- swaps(&rep.sequenceNumber,n);
- swapl(&rep.length,n);
- swaps(&rep.present,n);
- swaps(&rep.supported,n);
- swaps(&rep.unsupported,n);
- swaps(&rep.nDeviceLedFBs,n);
- swapl(&rep.type,n);
- }
- WriteToClient(client,SIZEOF(xkbGetDeviceInfoReply), (char *)&rep);
-
- str= malloc(nameLen);
- if (!str)
- return BadAlloc;
- XkbWriteCountedString(str,dev->name,client->swapped);
- WriteToClient(client,nameLen,str);
- free(str);
- length-= nameLen;
-
- if (rep.nBtnsRtrn>0) {
- int sz;
- xkbActionWireDesc * awire;
- sz= rep.nBtnsRtrn*SIZEOF(xkbActionWireDesc);
- awire= (xkbActionWireDesc *)&dev->button->xkb_acts[rep.firstBtnRtrn];
- WriteToClient(client,sz,(char *)awire);
- length-= sz;
- }
- if (nDeviceLedFBs>0) {
- status= SendDeviceLedFBs(dev,ledClass,ledID,length,client);
- if (status!=Success)
- return status;
- }
- else if (length!=0) {
- ErrorF("[xkb] Internal Error! BadLength in ProcXkbGetDeviceInfo\n");
- ErrorF("[xkb] Wrote %d fewer bytes than expected\n",length);
- return BadLength;
- }
- return Success;
-}
-
-static char *
-CheckSetDeviceIndicators( char * wire,
- DeviceIntPtr dev,
- int num,
- int * status_rtrn,
- ClientPtr client)
-{
-xkbDeviceLedsWireDesc * ledWire;
-int i;
-XkbSrvLedInfoPtr sli;
-
- ledWire= (xkbDeviceLedsWireDesc *)wire;
- for (i=0;i<num;i++) {
- if (client->swapped) {
- register int n;
- swaps(&ledWire->ledClass,n);
- swaps(&ledWire->ledID,n);
- swapl(&ledWire->namesPresent,n);
- swapl(&ledWire->mapsPresent,n);
- swapl(&ledWire->physIndicators,n);
- }
-
- sli= XkbFindSrvLedInfo(dev,ledWire->ledClass,ledWire->ledID,
- XkbXI_IndicatorsMask);
- if (sli!=NULL) {
- register int n;
- register unsigned bit;
- int nMaps,nNames;
- CARD32 *atomWire;
- xkbIndicatorMapWireDesc *mapWire;
-
- nMaps= nNames= 0;
- for (n=0,bit=1;n<XkbNumIndicators;n++,bit<<=1) {
- if (ledWire->namesPresent&bit)
- nNames++;
- if (ledWire->mapsPresent&bit)
- nMaps++;
- }
- atomWire= (CARD32 *)&ledWire[1];
- if (nNames>0) {
- for (n=0;n<nNames;n++) {
- if (client->swapped) {
- register int t;
- swapl(atomWire,t);
- }
- CHK_ATOM_OR_NONE3(((Atom)(*atomWire)),client->errorValue,
- *status_rtrn,NULL);
- atomWire++;
- }
- }
- mapWire= (xkbIndicatorMapWireDesc *)atomWire;
- if (nMaps>0) {
- for (n=0;n<nMaps;n++) {
- if (client->swapped) {
- register int t;
- swaps(&mapWire->virtualMods,t);
- swapl(&mapWire->ctrls,t);
- }
- CHK_MASK_LEGAL3(0x21,mapWire->whichGroups,
- XkbIM_UseAnyGroup,
- client->errorValue,
- *status_rtrn,NULL);
- CHK_MASK_LEGAL3(0x22,mapWire->whichMods,XkbIM_UseAnyMods,
- client->errorValue,
- *status_rtrn,NULL);
- mapWire++;
- }
- }
- ledWire= (xkbDeviceLedsWireDesc *)mapWire;
- }
- else {
- /* SHOULD NEVER HAPPEN */
- return (char *)ledWire;
- }
- }
- return (char *)ledWire;
-}
-
-static char *
-SetDeviceIndicators( char * wire,
- DeviceIntPtr dev,
- unsigned changed,
- int num,
- int * status_rtrn,
- ClientPtr client,
- xkbExtensionDeviceNotify *ev)
-{
-xkbDeviceLedsWireDesc * ledWire;
-int i;
-XkbEventCauseRec cause;
-unsigned namec,mapc,statec;
-xkbExtensionDeviceNotify ed;
-XkbChangesRec changes;
-DeviceIntPtr kbd;
-
- memset((char *)&ed, 0, sizeof(xkbExtensionDeviceNotify));
- memset((char *)&changes, 0, sizeof(XkbChangesRec));
- XkbSetCauseXkbReq(&cause,X_kbSetDeviceInfo,client);
- ledWire= (xkbDeviceLedsWireDesc *)wire;
- for (i=0;i<num;i++) {
- register int n;
- register unsigned bit;
- CARD32 * atomWire;
- xkbIndicatorMapWireDesc * mapWire;
- XkbSrvLedInfoPtr sli;
-
- namec= mapc= statec= 0;
- sli= XkbFindSrvLedInfo(dev,ledWire->ledClass,ledWire->ledID,
- XkbXI_IndicatorMapsMask);
- if (!sli) {
- /* SHOULD NEVER HAPPEN!! */
- return (char *)ledWire;
- }
-
- atomWire= (CARD32 *)&ledWire[1];
- if (changed&XkbXI_IndicatorNamesMask) {
- namec= sli->namesPresent|ledWire->namesPresent;
- memset((char *)sli->names, 0, XkbNumIndicators*sizeof(Atom));
- }
- if (ledWire->namesPresent) {
- sli->namesPresent= ledWire->namesPresent;
- memset((char *)sli->names, 0, XkbNumIndicators*sizeof(Atom));
- for (n=0,bit=1;n<XkbNumIndicators;n++,bit<<=1) {
- if (ledWire->namesPresent&bit) {
- sli->names[n]= (Atom)*atomWire;
- if (sli->names[n]==None)
- ledWire->namesPresent&= ~bit;
- atomWire++;
- }
- }
- }
- mapWire= (xkbIndicatorMapWireDesc *)atomWire;
- if (changed&XkbXI_IndicatorMapsMask) {
- mapc= sli->mapsPresent|ledWire->mapsPresent;
- sli->mapsPresent= ledWire->mapsPresent;
- memset((char*)sli->maps, 0, XkbNumIndicators*sizeof(XkbIndicatorMapRec));
- }
- if (ledWire->mapsPresent) {
- for (n=0,bit=1;n<XkbNumIndicators;n++,bit<<=1) {
- if (ledWire->mapsPresent&bit) {
- sli->maps[n].flags= mapWire->flags;
- sli->maps[n].which_groups= mapWire->whichGroups;
- sli->maps[n].groups= mapWire->groups;
- sli->maps[n].which_mods= mapWire->whichMods;
- sli->maps[n].mods.mask= mapWire->mods;
- sli->maps[n].mods.real_mods=mapWire->realMods;
- sli->maps[n].mods.vmods= mapWire->virtualMods;
- sli->maps[n].ctrls= mapWire->ctrls;
- mapWire++;
- }
- }
- }
- if (changed&XkbXI_IndicatorStateMask) {
- statec= sli->effectiveState^ledWire->state;
- sli->explicitState&= ~statec;
- sli->explicitState|= (ledWire->state&statec);
- }
- if (namec)
- XkbApplyLedNameChanges(dev,sli,namec,&ed,&changes,&cause);
- if (mapc)
- XkbApplyLedMapChanges(dev,sli,mapc,&ed,&changes,&cause);
- if (statec)
- XkbApplyLedStateChanges(dev,sli,statec,&ed,&changes,&cause);
-
- kbd= dev;
- if ((sli->flags&XkbSLI_HasOwnState)==0)
- kbd = inputInfo.keyboard;
-
- XkbFlushLedEvents(dev,kbd,sli,&ed,&changes,&cause);
- ledWire= (xkbDeviceLedsWireDesc *)mapWire;
- }
- return (char *)ledWire;
-}
-
-
-static int
-_XkbSetDeviceInfo(ClientPtr client, DeviceIntPtr dev,
- xkbSetDeviceInfoReq *stuff)
-{
- char *wire;
-
- wire= (char *)&stuff[1];
- if (stuff->change&XkbXI_ButtonActionsMask) {
- if (!dev->button) {
- client->errorValue = _XkbErrCode2(XkbErr_BadClass,ButtonClass);
- return XkbKeyboardErrorCode;
- }
- if ((stuff->firstBtn+stuff->nBtns)>dev->button->numButtons) {
- client->errorValue= _XkbErrCode4(0x02,stuff->firstBtn,stuff->nBtns,
- dev->button->numButtons);
- return BadMatch;
- }
- wire+= (stuff->nBtns*SIZEOF(xkbActionWireDesc));
- }
- if (stuff->change&XkbXI_IndicatorsMask) {
- int status= Success;
- wire= CheckSetDeviceIndicators(wire,dev,stuff->nDeviceLedFBs,
- &status,client);
- if (status!=Success)
- return status;
- }
- if (((wire-((char *)stuff))/4)!=stuff->length)
- return BadLength;
-
- return Success;
-}
-
-static int
-_XkbSetDeviceInfoCheck(ClientPtr client, DeviceIntPtr dev,
- xkbSetDeviceInfoReq *stuff)
-{
- char *wire;
- xkbExtensionDeviceNotify ed;
-
- memset((char *)&ed, 0, SIZEOF(xkbExtensionDeviceNotify));
- ed.deviceID= dev->id;
- wire= (char *)&stuff[1];
- if (stuff->change&XkbXI_ButtonActionsMask) {
- int nBtns,sz,i;
- XkbAction * acts;
- DeviceIntPtr kbd;
-
- nBtns= dev->button->numButtons;
- acts= dev->button->xkb_acts;
- if (acts==NULL) {
- acts= calloc(nBtns, sizeof(XkbAction));
- if (!acts)
- return BadAlloc;
- dev->button->xkb_acts= acts;
- }
- sz= stuff->nBtns*SIZEOF(xkbActionWireDesc);
- memcpy((char *)&acts[stuff->firstBtn],(char *)wire,sz);
- wire+= sz;
- ed.reason|= XkbXI_ButtonActionsMask;
- ed.firstBtn= stuff->firstBtn;
- ed.nBtns= stuff->nBtns;
-
- if (dev->key) kbd= dev;
- else kbd= inputInfo.keyboard;
- acts= &dev->button->xkb_acts[stuff->firstBtn];
- for (i=0;i<stuff->nBtns;i++,acts++) {
- if (acts->type!=XkbSA_NoAction)
- XkbSetActionKeyMods(kbd->key->xkbInfo->desc,acts,0);
- }
- }
- if (stuff->change&XkbXI_IndicatorsMask) {
- int status= Success;
- wire= SetDeviceIndicators(wire,dev,stuff->change,
- stuff->nDeviceLedFBs, &status,client,&ed);
- if (status!=Success)
- return status;
- }
- if ((stuff->change)&&(ed.reason))
- XkbSendExtensionDeviceNotify(dev,client,&ed);
- return Success;
-}
-
-int
-ProcXkbSetDeviceInfo(ClientPtr client)
-{
- DeviceIntPtr dev;
- int rc;
-
- REQUEST(xkbSetDeviceInfoReq);
- REQUEST_AT_LEAST_SIZE(xkbSetDeviceInfoReq);
-
- if (!(client->xkbClientFlags&_XkbClientInitialized))
- return BadAccess;
-
- CHK_ANY_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess);
- CHK_MASK_LEGAL(0x01,stuff->change,XkbXI_AllFeaturesMask);
-
- rc = _XkbSetDeviceInfoCheck(client, dev, stuff);
-
- if (rc != Success)
- return rc;
-
- if (stuff->deviceSpec == XkbUseCoreKbd || stuff->deviceSpec == XkbUseCorePtr)
- {
- DeviceIntPtr other;
- for (other = inputInfo.devices; other; other = other->next)
- {
- if (((other != dev) && !IsMaster(other) && GetMaster(other, MASTER_KEYBOARD) == dev) &&
- ((stuff->deviceSpec == XkbUseCoreKbd && other->key) ||
- (stuff->deviceSpec == XkbUseCorePtr && other->button)))
- {
- rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixManageAccess);
- if (rc == Success)
- {
- rc = _XkbSetDeviceInfoCheck(client, other, stuff);
- if (rc != Success)
- return rc;
- }
- }
- }
- }
-
- /* checks done, apply */
- rc = _XkbSetDeviceInfo(client, dev, stuff);
- if (rc != Success)
- return rc;
-
- if (stuff->deviceSpec == XkbUseCoreKbd || stuff->deviceSpec == XkbUseCorePtr)
- {
- DeviceIntPtr other;
- for (other = inputInfo.devices; other; other = other->next)
- {
- if (((other != dev) && !IsMaster(other) && GetMaster(other, MASTER_KEYBOARD) == dev) &&
- ((stuff->deviceSpec == XkbUseCoreKbd && other->key) ||
- (stuff->deviceSpec == XkbUseCorePtr && other->button)))
- {
- rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixManageAccess);
- if (rc == Success)
- {
- rc = _XkbSetDeviceInfo(client, other, stuff);
- if (rc != Success)
- return rc;
- }
- }
- }
- }
-
- return Success;
-}
-
-/***====================================================================***/
-
-int
-ProcXkbSetDebuggingFlags(ClientPtr client)
-{
-CARD32 newFlags,newCtrls,extraLength;
-xkbSetDebuggingFlagsReply rep;
-int rc;
-
- REQUEST(xkbSetDebuggingFlagsReq);
- REQUEST_AT_LEAST_SIZE(xkbSetDebuggingFlagsReq);
-
- rc = XaceHook(XACE_SERVER_ACCESS, client, DixDebugAccess);
- if (rc != Success)
- return rc;
-
- newFlags= xkbDebugFlags&(~stuff->affectFlags);
- newFlags|= (stuff->flags&stuff->affectFlags);
- newCtrls= xkbDebugCtrls&(~stuff->affectCtrls);
- newCtrls|= (stuff->ctrls&stuff->affectCtrls);
- if (xkbDebugFlags || newFlags || stuff->msgLength) {
- ErrorF("[xkb] XkbDebug: Setting debug flags to 0x%lx\n",(long)newFlags);
- if (newCtrls!=xkbDebugCtrls)
- ErrorF("[xkb] XkbDebug: Setting debug controls to 0x%lx\n",(long)newCtrls);
- }
- extraLength= (stuff->length<<2)-sz_xkbSetDebuggingFlagsReq;
- if (stuff->msgLength>0) {
- char *msg;
- if (extraLength<XkbPaddedSize(stuff->msgLength)) {
- ErrorF("[xkb] XkbDebug: msgLength= %d, length= %ld (should be %d)\n",
- stuff->msgLength,(long)extraLength,
- XkbPaddedSize(stuff->msgLength));
- return BadLength;
- }
- msg= (char *)&stuff[1];
- if (msg[stuff->msgLength-1]!='\0') {
- ErrorF("[xkb] XkbDebug: message not null-terminated\n");
- return BadValue;
- }
- ErrorF("[xkb] XkbDebug: %s\n",msg);
- }
- xkbDebugFlags = newFlags;
- xkbDebugCtrls = newCtrls;
-
- rep.type= X_Reply;
- rep.length = 0;
- rep.sequenceNumber = client->sequence;
- rep.currentFlags = newFlags;
- rep.currentCtrls = newCtrls;
- rep.supportedFlags = ~0;
- rep.supportedCtrls = ~0;
- if ( client->swapped ) {
- register int n;
- swaps(&rep.sequenceNumber, n);
- swapl(&rep.currentFlags, n);
- swapl(&rep.currentCtrls, n);
- swapl(&rep.supportedFlags, n);
- swapl(&rep.supportedCtrls, n);
- }
- WriteToClient(client,SIZEOF(xkbSetDebuggingFlagsReply), (char *)&rep);
- return Success;
-}
-
-/***====================================================================***/
-
-static int
-ProcXkbDispatch (ClientPtr client)
-{
- REQUEST(xReq);
- switch (stuff->data)
- {
- case X_kbUseExtension:
- return ProcXkbUseExtension(client);
- case X_kbSelectEvents:
- return ProcXkbSelectEvents(client);
- case X_kbBell:
- return ProcXkbBell(client);
- case X_kbGetState:
- return ProcXkbGetState(client);
- case X_kbLatchLockState:
- return ProcXkbLatchLockState(client);
- case X_kbGetControls:
- return ProcXkbGetControls(client);
- case X_kbSetControls:
- return ProcXkbSetControls(client);
- case X_kbGetMap:
- return ProcXkbGetMap(client);
- case X_kbSetMap:
- return ProcXkbSetMap(client);
- case X_kbGetCompatMap:
- return ProcXkbGetCompatMap(client);
- case X_kbSetCompatMap:
- return ProcXkbSetCompatMap(client);
- case X_kbGetIndicatorState:
- return ProcXkbGetIndicatorState(client);
- case X_kbGetIndicatorMap:
- return ProcXkbGetIndicatorMap(client);
- case X_kbSetIndicatorMap:
- return ProcXkbSetIndicatorMap(client);
- case X_kbGetNamedIndicator:
- return ProcXkbGetNamedIndicator(client);
- case X_kbSetNamedIndicator:
- return ProcXkbSetNamedIndicator(client);
- case X_kbGetNames:
- return ProcXkbGetNames(client);
- case X_kbSetNames:
- return ProcXkbSetNames(client);
- case X_kbGetGeometry:
- return ProcXkbGetGeometry(client);
- case X_kbSetGeometry:
- return ProcXkbSetGeometry(client);
- case X_kbPerClientFlags:
- return ProcXkbPerClientFlags(client);
- case X_kbListComponents:
- return ProcXkbListComponents(client);
- case X_kbGetKbdByName:
- return ProcXkbGetKbdByName(client);
- case X_kbGetDeviceInfo:
- return ProcXkbGetDeviceInfo(client);
- case X_kbSetDeviceInfo:
- return ProcXkbSetDeviceInfo(client);
- case X_kbSetDebuggingFlags:
- return ProcXkbSetDebuggingFlags(client);
- default:
- return BadRequest;
- }
-}
-
-static int
-XkbClientGone(pointer data,XID id)
-{
- DevicePtr pXDev = (DevicePtr)data;
-
- if (!XkbRemoveResourceClient(pXDev,id)) {
- ErrorF("[xkb] Internal Error! bad RemoveResourceClient in XkbClientGone\n");
- }
- return 1;
-}
-
-void
-XkbExtensionInit(void)
-{
- ExtensionEntry *extEntry;
-
- RT_XKBCLIENT = CreateNewResourceType(XkbClientGone, "XkbClient");
- if (!RT_XKBCLIENT)
- return;
-
- if (!XkbInitPrivates())
- return;
-
- if ((extEntry = AddExtension(XkbName, XkbNumberEvents, XkbNumberErrors,
- ProcXkbDispatch, SProcXkbDispatch,
- NULL, StandardMinorOpcode))) {
- XkbReqCode = (unsigned char)extEntry->base;
- XkbEventBase = (unsigned char)extEntry->eventBase;
- XkbErrorBase = (unsigned char)extEntry->errorBase;
- XkbKeyboardErrorCode = XkbErrorBase+XkbKeyboard;
- }
- return;
-}
-
-
+/************************************************************ +Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc. + +Permission 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 that both that copyright +notice and this permission notice appear in supporting +documentation, and that the name of Silicon Graphics not be +used in advertising or publicity pertaining to distribution +of the software without specific prior written permission. +Silicon Graphics makes no representation about the suitability +of this software for any purpose. It is provided "as is" +without any express or implied warranty. + +SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS +SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON +GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL +DAMAGES OR ANY 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 THIS SOFTWARE. + +********************************************************/ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include <stdio.h> +#include <X11/X.h> +#include <X11/Xproto.h> +#include "misc.h" +#include "inputstr.h" +#define XKBSRV_NEED_FILE_FUNCS +#include <xkbsrv.h> +#include "extnsionst.h" +#include "xace.h" +#include "xkb.h" +#include "protocol-versions.h" + +#include <X11/extensions/XI.h> +#include <X11/extensions/XKMformat.h> + +int XkbEventBase; +static int XkbErrorBase; +int XkbReqCode; +int XkbKeyboardErrorCode; +CARD32 xkbDebugFlags = 0; +static CARD32 xkbDebugCtrls = 0; + +static RESTYPE RT_XKBCLIENT; + +/***====================================================================***/ + +#define CHK_DEVICE(dev, id, client, access_mode, lf) {\ + int why;\ + int rc = lf(&(dev), id, client, access_mode, &why);\ + if (rc != Success) {\ + client->errorValue = _XkbErrCode2(why, id);\ + return rc;\ + }\ +} + +#define CHK_KBD_DEVICE(dev, id, client, mode) \ + CHK_DEVICE(dev, id, client, mode, _XkbLookupKeyboard) +#define CHK_LED_DEVICE(dev, id, client, mode) \ + CHK_DEVICE(dev, id, client, mode, _XkbLookupLedDevice) +#define CHK_BELL_DEVICE(dev, id, client, mode) \ + CHK_DEVICE(dev, id, client, mode, _XkbLookupBellDevice) +#define CHK_ANY_DEVICE(dev, id, client, mode) \ + CHK_DEVICE(dev, id, client, mode, _XkbLookupAnyDevice) + +#define CHK_ATOM_ONLY2(a,ev,er) {\ + if (((a)==None)||(!ValidAtom((a)))) {\ + (ev)= (XID)(a);\ + return er;\ + }\ +} +#define CHK_ATOM_ONLY(a) \ + CHK_ATOM_ONLY2(a,client->errorValue,BadAtom) + +#define CHK_ATOM_OR_NONE3(a,ev,er,ret) {\ + if (((a)!=None)&&(!ValidAtom((a)))) {\ + (ev)= (XID)(a);\ + (er)= BadAtom;\ + return ret;\ + }\ +} +#define CHK_ATOM_OR_NONE2(a,ev,er) {\ + if (((a)!=None)&&(!ValidAtom((a)))) {\ + (ev)= (XID)(a);\ + return er;\ + }\ +} +#define CHK_ATOM_OR_NONE(a) \ + CHK_ATOM_OR_NONE2(a,client->errorValue,BadAtom) + +#define CHK_MASK_LEGAL3(err,mask,legal,ev,er,ret) {\ + if ((mask)&(~(legal))) { \ + (ev)= _XkbErrCode2((err),((mask)&(~(legal))));\ + (er)= BadValue;\ + return ret;\ + }\ +} +#define CHK_MASK_LEGAL2(err,mask,legal,ev,er) {\ + if ((mask)&(~(legal))) { \ + (ev)= _XkbErrCode2((err),((mask)&(~(legal))));\ + return er;\ + }\ +} +#define CHK_MASK_LEGAL(err,mask,legal) \ + CHK_MASK_LEGAL2(err,mask,legal,client->errorValue,BadValue) + +#define CHK_MASK_MATCH(err,affect,value) {\ + if ((value)&(~(affect))) { \ + client->errorValue= _XkbErrCode2((err),((value)&(~(affect))));\ + return BadMatch;\ + }\ +} +#define CHK_MASK_OVERLAP(err,m1,m2) {\ + if ((m1)&(m2)) { \ + client->errorValue= _XkbErrCode2((err),((m1)&(m2)));\ + return BadMatch;\ + }\ +} +#define CHK_KEY_RANGE2(err,first,num,x,ev,er) {\ + if (((unsigned)(first)+(num)-1)>(x)->max_key_code) {\ + (ev)=_XkbErrCode4(err,(first),(num),(x)->max_key_code);\ + return er;\ + }\ + else if ( (first)<(x)->min_key_code ) {\ + (ev)=_XkbErrCode3(err+1,(first),xkb->min_key_code);\ + return er;\ + }\ +} +#define CHK_KEY_RANGE(err,first,num,x) \ + CHK_KEY_RANGE2(err,first,num,x,client->errorValue,BadValue) + +#define CHK_REQ_KEY_RANGE2(err,first,num,r,ev,er) {\ + if (((unsigned)(first)+(num)-1)>(r)->maxKeyCode) {\ + (ev)=_XkbErrCode4(err,(first),(num),(r)->maxKeyCode);\ + return er;\ + }\ + else if ( (first)<(r)->minKeyCode ) {\ + (ev)=_XkbErrCode3(err+1,(first),(r)->minKeyCode);\ + return er;\ + }\ +} +#define CHK_REQ_KEY_RANGE(err,first,num,r) \ + CHK_REQ_KEY_RANGE2(err,first,num,r,client->errorValue,BadValue) + +/***====================================================================***/ + +int +ProcXkbUseExtension(ClientPtr client) +{ + REQUEST(xkbUseExtensionReq); + xkbUseExtensionReply rep; + register int n; + int supported; + + REQUEST_SIZE_MATCH(xkbUseExtensionReq); + if (stuff->wantedMajor != SERVER_XKB_MAJOR_VERSION) { + /* pre-release version 0.65 is compatible with 1.00 */ + supported= ((SERVER_XKB_MAJOR_VERSION==1)&& + (stuff->wantedMajor==0)&&(stuff->wantedMinor==65)); + } + else supported = 1; + + if ((supported) && (!(client->xkbClientFlags&_XkbClientInitialized))) { + client->xkbClientFlags= _XkbClientInitialized; + client->vMajor= stuff->wantedMajor; + client->vMinor= stuff->wantedMinor; + } + else if (xkbDebugFlags&0x1) { + ErrorF("[xkb] Rejecting client %d (0x%lx) (wants %d.%02d, have %d.%02d)\n", + client->index, + (long)client->clientAsMask, + stuff->wantedMajor,stuff->wantedMinor, + SERVER_XKB_MAJOR_VERSION,SERVER_XKB_MINOR_VERSION); + } + memset(&rep, 0, sizeof(xkbUseExtensionReply)); + rep.type = X_Reply; + rep.supported = supported; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.serverMajor = SERVER_XKB_MAJOR_VERSION; + rep.serverMinor = SERVER_XKB_MINOR_VERSION; + if ( client->swapped ) { + swaps(&rep.sequenceNumber, n); + swaps(&rep.serverMajor, n); + swaps(&rep.serverMinor, n); + } + WriteToClient(client,SIZEOF(xkbUseExtensionReply), (char *)&rep); + return Success; +} + +/***====================================================================***/ + +int +ProcXkbSelectEvents(ClientPtr client) +{ + unsigned legal; + DeviceIntPtr dev; + XkbInterestPtr masks; + REQUEST(xkbSelectEventsReq); + + REQUEST_AT_LEAST_SIZE(xkbSelectEventsReq); + + if (!(client->xkbClientFlags&_XkbClientInitialized)) + return BadAccess; + + CHK_ANY_DEVICE(dev, stuff->deviceSpec, client, DixUseAccess); + + if (((stuff->affectWhich&XkbMapNotifyMask)!=0)&&(stuff->affectMap)) { + client->mapNotifyMask&= ~stuff->affectMap; + client->mapNotifyMask|= (stuff->affectMap&stuff->map); + } + if ((stuff->affectWhich&(~XkbMapNotifyMask))==0) + return Success; + + masks = XkbFindClientResource((DevicePtr)dev,client); + if (!masks){ + XID id = FakeClientID(client->index); + if (!AddResource(id,RT_XKBCLIENT,dev)) + return BadAlloc; + masks= XkbAddClientResource((DevicePtr)dev,client,id); + } + if (masks) { + union { + CARD8 *c8; + CARD16 *c16; + CARD32 *c32; + } from,to; + register unsigned bit,ndx,maskLeft,dataLeft,size; + + from.c8= (CARD8 *)&stuff[1]; + dataLeft= (stuff->length*4)-SIZEOF(xkbSelectEventsReq); + maskLeft= (stuff->affectWhich&(~XkbMapNotifyMask)); + for (ndx=0,bit=1; (maskLeft!=0); ndx++, bit<<=1) { + if ((bit&maskLeft)==0) + continue; + maskLeft&= ~bit; + switch (ndx) { + case XkbNewKeyboardNotify: + to.c16= &client->newKeyboardNotifyMask; + legal= XkbAllNewKeyboardEventsMask; + size= 2; + break; + case XkbStateNotify: + to.c16= &masks->stateNotifyMask; + legal= XkbAllStateEventsMask; + size= 2; + break; + case XkbControlsNotify: + to.c32= &masks->ctrlsNotifyMask; + legal= XkbAllControlEventsMask; + size= 4; + break; + case XkbIndicatorStateNotify: + to.c32= &masks->iStateNotifyMask; + legal= XkbAllIndicatorEventsMask; + size= 4; + break; + case XkbIndicatorMapNotify: + to.c32= &masks->iMapNotifyMask; + legal= XkbAllIndicatorEventsMask; + size= 4; + break; + case XkbNamesNotify: + to.c16= &masks->namesNotifyMask; + legal= XkbAllNameEventsMask; + size= 2; + break; + case XkbCompatMapNotify: + to.c8= &masks->compatNotifyMask; + legal= XkbAllCompatMapEventsMask; + size= 1; + break; + case XkbBellNotify: + to.c8= &masks->bellNotifyMask; + legal= XkbAllBellEventsMask; + size= 1; + break; + case XkbActionMessage: + to.c8= &masks->actionMessageMask; + legal= XkbAllActionMessagesMask; + size= 1; + break; + case XkbAccessXNotify: + to.c16= &masks->accessXNotifyMask; + legal= XkbAllAccessXEventsMask; + size= 2; + break; + case XkbExtensionDeviceNotify: + to.c16= &masks->extDevNotifyMask; + legal= XkbAllExtensionDeviceEventsMask; + size= 2; + break; + default: + client->errorValue = _XkbErrCode2(33,bit); + return BadValue; + } + + if (stuff->clear&bit) { + if (size==2) to.c16[0]= 0; + else if (size==4) to.c32[0]= 0; + else to.c8[0]= 0; + } + else if (stuff->selectAll&bit) { + if (size==2) to.c16[0]= ~0; + else if (size==4) to.c32[0]= ~0; + else to.c8[0]= ~0; + } + else { + if (dataLeft<(size*2)) + return BadLength; + if (size==2) { + CHK_MASK_MATCH(ndx,from.c16[0],from.c16[1]); + CHK_MASK_LEGAL(ndx,from.c16[0],legal); + to.c16[0]&= ~from.c16[0]; + to.c16[0]|= (from.c16[0]&from.c16[1]); + } + else if (size==4) { + CHK_MASK_MATCH(ndx,from.c32[0],from.c32[1]); + CHK_MASK_LEGAL(ndx,from.c32[0],legal); + to.c32[0]&= ~from.c32[0]; + to.c32[0]|= (from.c32[0]&from.c32[1]); + } + else { + CHK_MASK_MATCH(ndx,from.c8[0],from.c8[1]); + CHK_MASK_LEGAL(ndx,from.c8[0],legal); + to.c8[0]&= ~from.c8[0]; + to.c8[0]|= (from.c8[0]&from.c8[1]); + size= 2; + } + from.c8+= (size*2); + dataLeft-= (size*2); + } + } + if (dataLeft>2) { + ErrorF("[xkb] Extra data (%d bytes) after SelectEvents\n",dataLeft); + return BadLength; + } + return Success; + } + return BadAlloc; +} + +/***====================================================================***/ +/** + * Ring a bell on the given device for the given client. + */ +static int +_XkbBell(ClientPtr client, DeviceIntPtr dev, WindowPtr pWin, + int bellClass, int bellID, int pitch, int duration, + int percent, int forceSound, int eventOnly, Atom name) +{ + int base; + pointer ctrl; + int oldPitch, oldDuration; + int newPercent; + + if (bellClass == KbdFeedbackClass) { + KbdFeedbackPtr k; + if (bellID==XkbDfltXIId) + k= dev->kbdfeed; + else { + for (k=dev->kbdfeed; k; k=k->next) { + if (k->ctrl.id == bellID) + break; + } + } + if (!k) { + client->errorValue = _XkbErrCode2(0x5,bellID); + return BadValue; + } + base = k->ctrl.bell; + ctrl = (pointer) &(k->ctrl); + oldPitch= k->ctrl.bell_pitch; + oldDuration= k->ctrl.bell_duration; + if (pitch!=0) { + if (pitch==-1) + k->ctrl.bell_pitch= defaultKeyboardControl.bell_pitch; + else k->ctrl.bell_pitch= pitch; + } + if (duration!=0) { + if (duration==-1) + k->ctrl.bell_duration= defaultKeyboardControl.bell_duration; + else k->ctrl.bell_duration= duration; + } + } + else if (bellClass == BellFeedbackClass) { + BellFeedbackPtr b; + if (bellID==XkbDfltXIId) + b= dev->bell; + else { + for (b=dev->bell; b; b=b->next) { + if (b->ctrl.id == bellID) + break; + } + } + if (!b) { + client->errorValue = _XkbErrCode2(0x6,bellID); + return BadValue; + } + base = b->ctrl.percent; + ctrl = (pointer) &(b->ctrl); + oldPitch= b->ctrl.pitch; + oldDuration= b->ctrl.duration; + if (pitch!=0) { + if (pitch==-1) + b->ctrl.pitch= defaultKeyboardControl.bell_pitch; + else b->ctrl.pitch= pitch; + } + if (duration!=0) { + if (duration==-1) + b->ctrl.duration= defaultKeyboardControl.bell_duration; + else b->ctrl.duration= duration; + } + } + else { + client->errorValue = _XkbErrCode2(0x7, bellClass); + return BadValue; + } + + newPercent = (base * percent)/100; + if (percent < 0) + newPercent = base + newPercent; + else newPercent = base - newPercent + percent; + + XkbHandleBell(forceSound, eventOnly, + dev, newPercent, ctrl, bellClass, + name, pWin, client); + if ((pitch!=0)||(duration!=0)) { + if (bellClass == KbdFeedbackClass) { + KbdFeedbackPtr k; + k= (KbdFeedbackPtr)ctrl; + if (pitch!=0) + k->ctrl.bell_pitch= oldPitch; + if (duration!=0) + k->ctrl.bell_duration= oldDuration; + } + else { + BellFeedbackPtr b; + b= (BellFeedbackPtr)ctrl; + if (pitch!=0) + b->ctrl.pitch= oldPitch; + if (duration!=0) + b->ctrl.duration= oldDuration; + } + } + + return Success; +} + +int +ProcXkbBell(ClientPtr client) +{ + REQUEST(xkbBellReq); + DeviceIntPtr dev; + WindowPtr pWin; + int rc; + + REQUEST_SIZE_MATCH(xkbBellReq); + + if (!(client->xkbClientFlags&_XkbClientInitialized)) + return BadAccess; + + CHK_BELL_DEVICE(dev, stuff->deviceSpec, client, DixBellAccess); + CHK_ATOM_OR_NONE(stuff->name); + + /* device-independent checks request for sane values */ + if ((stuff->forceSound)&&(stuff->eventOnly)) { + client->errorValue=_XkbErrCode3(0x1,stuff->forceSound,stuff->eventOnly); + return BadMatch; + } + if (stuff->percent < -100 || stuff->percent > 100) { + client->errorValue = _XkbErrCode2(0x2,stuff->percent); + return BadValue; + } + if (stuff->duration<-1) { + client->errorValue = _XkbErrCode2(0x3,stuff->duration); + return BadValue; + } + if (stuff->pitch<-1) { + client->errorValue = _XkbErrCode2(0x4,stuff->pitch); + return BadValue; + } + + if (stuff->bellClass == XkbDfltXIClass) { + if (dev->kbdfeed!=NULL) + stuff->bellClass= KbdFeedbackClass; + else stuff->bellClass= BellFeedbackClass; + } + + if (stuff->window!=None) { + rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); + if (rc != Success) { + client->errorValue= stuff->window; + return rc; + } + } + else pWin= NULL; + + /* Client wants to ring a bell on the core keyboard? + Ring the bell on the core keyboard (which does nothing, but if that + fails the client is screwed anyway), and then on all extension devices. + Fail if the core keyboard fails but not the extension devices. this + may cause some keyboards to ding and others to stay silent. Fix + your client to use explicit keyboards to avoid this. + + dev is the device the client requested. + */ + rc = _XkbBell(client, dev, pWin, stuff->bellClass, stuff->bellID, + stuff->pitch, stuff->duration, stuff->percent, + stuff->forceSound, stuff->eventOnly, stuff->name); + + if ((rc == Success) && ((stuff->deviceSpec == XkbUseCoreKbd) || + (stuff->deviceSpec == XkbUseCorePtr))) + { + DeviceIntPtr other; + for (other = inputInfo.devices; other; other = other->next) + { + if ((other != dev) && other->key && !IsMaster(other) && GetMaster(other, MASTER_KEYBOARD) == dev) + { + rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixBellAccess); + if (rc == Success) + _XkbBell(client, other, pWin, stuff->bellClass, + stuff->bellID, stuff->pitch, stuff->duration, + stuff->percent, stuff->forceSound, + stuff->eventOnly, stuff->name); + } + } + rc = Success; /* reset to success, that's what we got for the VCK */ + } + + return rc; +} + +/***====================================================================***/ + +int +ProcXkbGetState(ClientPtr client) +{ + REQUEST(xkbGetStateReq); + DeviceIntPtr dev; + xkbGetStateReply rep; + XkbStateRec *xkb; + + REQUEST_SIZE_MATCH(xkbGetStateReq); + + if (!(client->xkbClientFlags&_XkbClientInitialized)) + return BadAccess; + + CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess); + + xkb= &dev->key->xkbInfo->state; + memset(&rep, 0, sizeof(xkbGetStateReply)); + rep.type= X_Reply; + rep.sequenceNumber= client->sequence; + rep.length = 0; + rep.deviceID = dev->id; + rep.mods = XkbStateFieldFromRec(xkb) & 0xff; + rep.baseMods = xkb->base_mods; + rep.lockedMods = xkb->locked_mods; + rep.latchedMods = xkb->latched_mods; + rep.group = xkb->group; + rep.baseGroup = xkb->base_group; + rep.latchedGroup = xkb->latched_group; + rep.lockedGroup = xkb->locked_group; + rep.compatState = xkb->compat_state; + rep.ptrBtnState = xkb->ptr_buttons; + if (client->swapped) { + register int n; + swaps(&rep.sequenceNumber,n); + swaps(&rep.ptrBtnState,n); + } + WriteToClient(client, SIZEOF(xkbGetStateReply), (char *)&rep); + return Success; +} + +/***====================================================================***/ + +int +ProcXkbLatchLockState(ClientPtr client) +{ + int status; + DeviceIntPtr dev, tmpd; + XkbStateRec oldState,*newState; + CARD16 changed; + xkbStateNotify sn; + XkbEventCauseRec cause; + + REQUEST(xkbLatchLockStateReq); + REQUEST_SIZE_MATCH(xkbLatchLockStateReq); + + if (!(client->xkbClientFlags & _XkbClientInitialized)) + return BadAccess; + + CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixSetAttrAccess); + CHK_MASK_MATCH(0x01, stuff->affectModLocks, stuff->modLocks); + CHK_MASK_MATCH(0x01, stuff->affectModLatches, stuff->modLatches); + + status = Success; + + for (tmpd = inputInfo.devices; tmpd; tmpd = tmpd->next) { + if ((tmpd == dev) || (!IsMaster(tmpd) && GetMaster(tmpd, MASTER_KEYBOARD) == dev)) { + if (!tmpd->key || !tmpd->key->xkbInfo) + continue; + + oldState = tmpd->key->xkbInfo->state; + newState = &tmpd->key->xkbInfo->state; + if (stuff->affectModLocks) { + newState->locked_mods &= ~stuff->affectModLocks; + newState->locked_mods |= (stuff->affectModLocks & stuff->modLocks); + } + if (status == Success && stuff->lockGroup) + newState->locked_group = stuff->groupLock; + if (status == Success && stuff->affectModLatches) + status = XkbLatchModifiers(tmpd, stuff->affectModLatches, + stuff->modLatches); + if (status == Success && stuff->latchGroup) + status = XkbLatchGroup(tmpd, stuff->groupLatch); + + if (status != Success) + return status; + + XkbComputeDerivedState(tmpd->key->xkbInfo); + + changed = XkbStateChangedFlags(&oldState, newState); + if (changed) { + sn.keycode = 0; + sn.eventType = 0; + sn.requestMajor = XkbReqCode; + sn.requestMinor = X_kbLatchLockState; + sn.changed = changed; + XkbSendStateNotify(tmpd, &sn); + changed = XkbIndicatorsToUpdate(tmpd, changed, FALSE); + if (changed) { + XkbSetCauseXkbReq(&cause, X_kbLatchLockState, client); + XkbUpdateIndicators(tmpd, changed, TRUE, NULL, &cause); + } + } + } + } + + return Success; +} + +/***====================================================================***/ + +int +ProcXkbGetControls(ClientPtr client) +{ + xkbGetControlsReply rep; + XkbControlsPtr xkb; + DeviceIntPtr dev; + register int n; + + REQUEST(xkbGetControlsReq); + REQUEST_SIZE_MATCH(xkbGetControlsReq); + + if (!(client->xkbClientFlags&_XkbClientInitialized)) + return BadAccess; + + CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess); + + xkb = dev->key->xkbInfo->desc->ctrls; + rep.type = X_Reply; + rep.length = bytes_to_int32(SIZEOF(xkbGetControlsReply)- + SIZEOF(xGenericReply)); + rep.sequenceNumber = client->sequence; + rep.deviceID = ((DeviceIntPtr)dev)->id; + rep.numGroups = xkb->num_groups; + rep.groupsWrap = xkb->groups_wrap; + rep.internalMods = xkb->internal.mask; + rep.ignoreLockMods = xkb->ignore_lock.mask; + rep.internalRealMods = xkb->internal.real_mods; + rep.ignoreLockRealMods = xkb->ignore_lock.real_mods; + rep.internalVMods = xkb->internal.vmods; + rep.ignoreLockVMods = xkb->ignore_lock.vmods; + rep.enabledCtrls = xkb->enabled_ctrls; + rep.repeatDelay = xkb->repeat_delay; + rep.repeatInterval = xkb->repeat_interval; + rep.slowKeysDelay = xkb->slow_keys_delay; + rep.debounceDelay = xkb->debounce_delay; + rep.mkDelay = xkb->mk_delay; + rep.mkInterval = xkb->mk_interval; + rep.mkTimeToMax = xkb->mk_time_to_max; + rep.mkMaxSpeed = xkb->mk_max_speed; + rep.mkCurve = xkb->mk_curve; + rep.mkDfltBtn = xkb->mk_dflt_btn; + rep.axTimeout = xkb->ax_timeout; + rep.axtCtrlsMask = xkb->axt_ctrls_mask; + rep.axtCtrlsValues = xkb->axt_ctrls_values; + rep.axtOptsMask = xkb->axt_opts_mask; + rep.axtOptsValues = xkb->axt_opts_values; + rep.axOptions = xkb->ax_options; + memcpy(rep.perKeyRepeat,xkb->per_key_repeat,XkbPerKeyBitArraySize); + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length,n); + swaps(&rep.internalVMods, n); + swaps(&rep.ignoreLockVMods, n); + swapl(&rep.enabledCtrls, n); + swaps(&rep.repeatDelay, n); + swaps(&rep.repeatInterval, n); + swaps(&rep.slowKeysDelay, n); + swaps(&rep.debounceDelay, n); + swaps(&rep.mkDelay, n); + swaps(&rep.mkInterval, n); + swaps(&rep.mkTimeToMax, n); + swaps(&rep.mkMaxSpeed, n); + swaps(&rep.mkCurve, n); + swaps(&rep.axTimeout, n); + swapl(&rep.axtCtrlsMask, n); + swapl(&rep.axtCtrlsValues, n); + swaps(&rep.axtOptsMask, n); + swaps(&rep.axtOptsValues, n); + swaps(&rep.axOptions, n); + } + WriteToClient(client, SIZEOF(xkbGetControlsReply), (char *)&rep); + return Success; +} + +int +ProcXkbSetControls(ClientPtr client) +{ + DeviceIntPtr dev, tmpd; + XkbSrvInfoPtr xkbi; + XkbControlsPtr ctrl; + XkbControlsRec new,old; + xkbControlsNotify cn; + XkbEventCauseRec cause; + XkbSrvLedInfoPtr sli; + + REQUEST(xkbSetControlsReq); + REQUEST_SIZE_MATCH(xkbSetControlsReq); + + if (!(client->xkbClientFlags & _XkbClientInitialized)) + return BadAccess; + + CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess); + CHK_MASK_LEGAL(0x01, stuff->changeCtrls, XkbAllControlsMask); + + for (tmpd = inputInfo.devices; tmpd; tmpd = tmpd->next) { + if (!tmpd->key || !tmpd->key->xkbInfo) + continue; + if ((tmpd == dev) || (!IsMaster(tmpd) && GetMaster(tmpd, MASTER_KEYBOARD) == dev)) { + xkbi = tmpd->key->xkbInfo; + ctrl = xkbi->desc->ctrls; + new = *ctrl; + XkbSetCauseXkbReq(&cause, X_kbSetControls, client); + + if (stuff->changeCtrls & XkbInternalModsMask) { + CHK_MASK_MATCH(0x02, stuff->affectInternalMods, + stuff->internalMods); + CHK_MASK_MATCH(0x03, stuff->affectInternalVMods, + stuff->internalVMods); + + new.internal.real_mods &= ~(stuff->affectInternalMods); + new.internal.real_mods |= (stuff->affectInternalMods & + stuff->internalMods); + new.internal.vmods &= ~(stuff->affectInternalVMods); + new.internal.vmods |= (stuff->affectInternalVMods & + stuff->internalVMods); + new.internal.mask = new.internal.real_mods | + XkbMaskForVMask(xkbi->desc, + new.internal.vmods); + } + + if (stuff->changeCtrls & XkbIgnoreLockModsMask) { + CHK_MASK_MATCH(0x4, stuff->affectIgnoreLockMods, + stuff->ignoreLockMods); + CHK_MASK_MATCH(0x5, stuff->affectIgnoreLockVMods, + stuff->ignoreLockVMods); + + new.ignore_lock.real_mods &= ~(stuff->affectIgnoreLockMods); + new.ignore_lock.real_mods |= (stuff->affectIgnoreLockMods & + stuff->ignoreLockMods); + new.ignore_lock.vmods &= ~(stuff->affectIgnoreLockVMods); + new.ignore_lock.vmods |= (stuff->affectIgnoreLockVMods & + stuff->ignoreLockVMods); + new.ignore_lock.mask = new.ignore_lock.real_mods | + XkbMaskForVMask(xkbi->desc, + new.ignore_lock.vmods); + } + + CHK_MASK_MATCH(0x06, stuff->affectEnabledCtrls, + stuff->enabledCtrls); + if (stuff->affectEnabledCtrls) { + CHK_MASK_LEGAL(0x07, stuff->affectEnabledCtrls, + XkbAllBooleanCtrlsMask); + + new.enabled_ctrls &= ~(stuff->affectEnabledCtrls); + new.enabled_ctrls |= (stuff->affectEnabledCtrls & + stuff->enabledCtrls); + } + + if (stuff->changeCtrls & XkbRepeatKeysMask) { + if (stuff->repeatDelay < 1 || stuff->repeatInterval < 1) { + client->errorValue = _XkbErrCode3(0x08, stuff->repeatDelay, + stuff->repeatInterval); + return BadValue; + } + + new.repeat_delay = stuff->repeatDelay; + new.repeat_interval = stuff->repeatInterval; + } + + if (stuff->changeCtrls & XkbSlowKeysMask) { + if (stuff->slowKeysDelay < 1) { + client->errorValue = _XkbErrCode2(0x09, + stuff->slowKeysDelay); + return BadValue; + } + + new.slow_keys_delay = stuff->slowKeysDelay; + } + + if (stuff->changeCtrls & XkbBounceKeysMask) { + if (stuff->debounceDelay < 1) { + client->errorValue = _XkbErrCode2(0x0A, + stuff->debounceDelay); + return BadValue; + } + + new.debounce_delay = stuff->debounceDelay; + } + + if (stuff->changeCtrls & XkbMouseKeysMask) { + if (stuff->mkDfltBtn > XkbMaxMouseKeysBtn) { + client->errorValue = _XkbErrCode2(0x0B, stuff->mkDfltBtn); + return BadValue; + } + + new.mk_dflt_btn = stuff->mkDfltBtn; + } + + if (stuff->changeCtrls & XkbMouseKeysAccelMask) { + if (stuff->mkDelay < 1 || stuff->mkInterval < 1 || + stuff->mkTimeToMax < 1 || stuff->mkMaxSpeed < 1 || + stuff->mkCurve < -1000) { + client->errorValue = _XkbErrCode2(0x0C,0); + return BadValue; + } + + new.mk_delay = stuff->mkDelay; + new.mk_interval = stuff->mkInterval; + new.mk_time_to_max = stuff->mkTimeToMax; + new.mk_max_speed = stuff->mkMaxSpeed; + new.mk_curve = stuff->mkCurve; + AccessXComputeCurveFactor(xkbi, &new); + } + + if (stuff->changeCtrls & XkbGroupsWrapMask) { + unsigned act, num; + + act = XkbOutOfRangeGroupAction(stuff->groupsWrap); + switch (act) { + case XkbRedirectIntoRange: + num = XkbOutOfRangeGroupNumber(stuff->groupsWrap); + if (num >= new.num_groups) { + client->errorValue = _XkbErrCode3(0x0D, new.num_groups, + num); + return BadValue; + } + case XkbWrapIntoRange: + case XkbClampIntoRange: + break; + default: + client->errorValue = _XkbErrCode2(0x0E, act); + return BadValue; + } + + new.groups_wrap= stuff->groupsWrap; + } + + CHK_MASK_LEGAL(0x0F, stuff->axOptions, XkbAX_AllOptionsMask); + if (stuff->changeCtrls & XkbAccessXKeysMask) { + new.ax_options = stuff->axOptions & XkbAX_AllOptionsMask; + } + else { + if (stuff->changeCtrls & XkbStickyKeysMask) { + new.ax_options &= ~(XkbAX_SKOptionsMask); + new.ax_options |= (stuff->axOptions & XkbAX_SKOptionsMask); + } + + if (stuff->changeCtrls & XkbAccessXFeedbackMask) { + new.ax_options &= ~(XkbAX_FBOptionsMask); + new.ax_options |= (stuff->axOptions & XkbAX_FBOptionsMask); + } + } + + if (stuff->changeCtrls & XkbAccessXTimeoutMask) { + if (stuff->axTimeout < 1) { + client->errorValue = _XkbErrCode2(0x10, stuff->axTimeout); + return BadValue; + } + CHK_MASK_MATCH(0x11, stuff->axtCtrlsMask, + stuff->axtCtrlsValues); + CHK_MASK_LEGAL(0x12, stuff->axtCtrlsMask, + XkbAllBooleanCtrlsMask); + CHK_MASK_MATCH(0x13, stuff->axtOptsMask, stuff->axtOptsValues); + CHK_MASK_LEGAL(0x14, stuff->axtOptsMask, XkbAX_AllOptionsMask); + new.ax_timeout = stuff->axTimeout; + new.axt_ctrls_mask = stuff->axtCtrlsMask; + new.axt_ctrls_values = (stuff->axtCtrlsValues & + stuff->axtCtrlsMask); + new.axt_opts_mask = stuff->axtOptsMask; + new.axt_opts_values = (stuff->axtOptsValues & + stuff->axtOptsMask); + } + + if (stuff->changeCtrls & XkbPerKeyRepeatMask) { + memcpy(new.per_key_repeat, stuff->perKeyRepeat, + XkbPerKeyBitArraySize); + if (xkbi->repeatKey && + !BitIsOn(new.per_key_repeat, xkbi->repeatKey)) { + AccessXCancelRepeatKey(xkbi, xkbi->repeatKey); + } + } + + old= *ctrl; + *ctrl= new; + XkbDDXChangeControls(tmpd, &old, ctrl); + + if (XkbComputeControlsNotify(tmpd, &old, ctrl, &cn, FALSE)) { + cn.keycode = 0; + cn.eventType = 0; + cn.requestMajor = XkbReqCode; + cn.requestMinor = X_kbSetControls; + XkbSendControlsNotify(tmpd, &cn); + } + + sli = XkbFindSrvLedInfo(tmpd, XkbDfltXIClass, XkbDfltXIId, 0); + if (sli) + XkbUpdateIndicators(tmpd, sli->usesControls, TRUE, NULL, + &cause); + + /* If sticky keys were disabled, clear all locks and latches */ + if ((old.enabled_ctrls & XkbStickyKeysMask) && + !(ctrl->enabled_ctrls & XkbStickyKeysMask)) + XkbClearAllLatchesAndLocks(tmpd, xkbi, TRUE, &cause); + } + } + + return Success; +} + +/***====================================================================***/ + +static int +XkbSizeKeyTypes(XkbDescPtr xkb,xkbGetMapReply *rep) +{ + XkbKeyTypeRec *type; + unsigned i,len; + + len= 0; + if (((rep->present&XkbKeyTypesMask)==0)||(rep->nTypes<1)|| + (!xkb)||(!xkb->map)||(!xkb->map->types)) { + rep->present&= ~XkbKeyTypesMask; + rep->firstType= rep->nTypes= 0; + return 0; + } + type= &xkb->map->types[rep->firstType]; + for (i=0;i<rep->nTypes;i++,type++){ + len+= SIZEOF(xkbKeyTypeWireDesc); + if (type->map_count>0) { + len+= (type->map_count*SIZEOF(xkbKTMapEntryWireDesc)); + if (type->preserve) + len+= (type->map_count*SIZEOF(xkbModsWireDesc)); + } + } + return len; +} + +static char * +XkbWriteKeyTypes( XkbDescPtr xkb, + xkbGetMapReply * rep, + char * buf, + ClientPtr client) +{ + XkbKeyTypePtr type; + unsigned i; + xkbKeyTypeWireDesc *wire; + + type= &xkb->map->types[rep->firstType]; + for (i=0;i<rep->nTypes;i++,type++) { + register unsigned n; + wire= (xkbKeyTypeWireDesc *)buf; + wire->mask = type->mods.mask; + wire->realMods = type->mods.real_mods; + wire->virtualMods = type->mods.vmods; + wire->numLevels = type->num_levels; + wire->nMapEntries = type->map_count; + wire->preserve = (type->preserve!=NULL); + if (client->swapped) { + register int n; + swaps(&wire->virtualMods,n); + } + + buf= (char *)&wire[1]; + if (wire->nMapEntries>0) { + xkbKTMapEntryWireDesc * wire; + XkbKTMapEntryPtr entry; + wire= (xkbKTMapEntryWireDesc *)buf; + entry= type->map; + for (n=0;n<type->map_count;n++,wire++,entry++) { + wire->active= entry->active; + wire->mask= entry->mods.mask; + wire->level= entry->level; + wire->realMods= entry->mods.real_mods; + wire->virtualMods= entry->mods.vmods; + if (client->swapped) { + register int n; + swaps(&wire->virtualMods,n); + } + } + buf= (char *)wire; + if (type->preserve!=NULL) { + xkbModsWireDesc * pwire; + XkbModsPtr preserve; + pwire= (xkbModsWireDesc *)buf; + preserve= type->preserve; + for (n=0;n<type->map_count;n++,pwire++,preserve++) { + pwire->mask= preserve->mask; + pwire->realMods= preserve->real_mods; + pwire->virtualMods= preserve->vmods; + if (client->swapped) { + register int n; + swaps(&pwire->virtualMods,n); + } + } + buf= (char *)pwire; + } + } + } + return buf; +} + +static int +XkbSizeKeySyms(XkbDescPtr xkb,xkbGetMapReply *rep) +{ + XkbSymMapPtr symMap; + unsigned i,len; + unsigned nSyms,nSymsThisKey; + + if (((rep->present&XkbKeySymsMask)==0)||(rep->nKeySyms<1)|| + (!xkb)||(!xkb->map)||(!xkb->map->key_sym_map)) { + rep->present&= ~XkbKeySymsMask; + rep->firstKeySym= rep->nKeySyms= 0; + rep->totalSyms= 0; + return 0; + } + len= rep->nKeySyms*SIZEOF(xkbSymMapWireDesc); + symMap = &xkb->map->key_sym_map[rep->firstKeySym]; + for (i=nSyms=0;i<rep->nKeySyms;i++,symMap++) { + if (symMap->offset!=0) { + nSymsThisKey= XkbNumGroups(symMap->group_info)*symMap->width; + nSyms+= nSymsThisKey; + } + } + len+= nSyms*4; + rep->totalSyms= nSyms; + return len; +} + +static int +XkbSizeVirtualMods(XkbDescPtr xkb,xkbGetMapReply *rep) +{ +register unsigned i,nMods,bit; + + if (((rep->present&XkbVirtualModsMask)==0)||(rep->virtualMods==0)|| + (!xkb)||(!xkb->server)) { + rep->present&= ~XkbVirtualModsMask; + rep->virtualMods= 0; + return 0; + } + for (i=nMods=0,bit=1;i<XkbNumVirtualMods;i++,bit<<=1) { + if (rep->virtualMods&bit) + nMods++; + } + return XkbPaddedSize(nMods); +} + +static char * +XkbWriteKeySyms(XkbDescPtr xkb,xkbGetMapReply *rep,char *buf,ClientPtr client) +{ +register KeySym * pSym; +XkbSymMapPtr symMap; +xkbSymMapWireDesc * outMap; +register unsigned i; + + symMap = &xkb->map->key_sym_map[rep->firstKeySym]; + for (i=0;i<rep->nKeySyms;i++,symMap++) { + outMap = (xkbSymMapWireDesc *)buf; + outMap->ktIndex[0] = symMap->kt_index[0]; + outMap->ktIndex[1] = symMap->kt_index[1]; + outMap->ktIndex[2] = symMap->kt_index[2]; + outMap->ktIndex[3] = symMap->kt_index[3]; + outMap->groupInfo = symMap->group_info; + outMap->width= symMap->width; + outMap->nSyms = symMap->width*XkbNumGroups(symMap->group_info); + buf= (char *)&outMap[1]; + if (outMap->nSyms==0) + continue; + + pSym = &xkb->map->syms[symMap->offset]; + memcpy((char *)buf,(char *)pSym,outMap->nSyms*4); + if (client->swapped) { + register int n,nSyms= outMap->nSyms; + swaps(&outMap->nSyms,n); + while (nSyms-->0) { + swapl(buf,n); + buf+= 4; + } + } + else buf+= outMap->nSyms*4; + } + return buf; +} + +static int +XkbSizeKeyActions(XkbDescPtr xkb,xkbGetMapReply *rep) +{ + unsigned i,len,nActs; + register KeyCode firstKey; + + if (((rep->present&XkbKeyActionsMask)==0)||(rep->nKeyActs<1)|| + (!xkb)||(!xkb->server)||(!xkb->server->key_acts)) { + rep->present&= ~XkbKeyActionsMask; + rep->firstKeyAct= rep->nKeyActs= 0; + rep->totalActs= 0; + return 0; + } + firstKey= rep->firstKeyAct; + for (nActs=i=0;i<rep->nKeyActs;i++) { + if (xkb->server->key_acts[i+firstKey]!=0) + nActs+= XkbKeyNumActions(xkb,i+firstKey); + } + len= XkbPaddedSize(rep->nKeyActs)+(nActs*SIZEOF(xkbActionWireDesc)); + rep->totalActs= nActs; + return len; +} + +static char * +XkbWriteKeyActions(XkbDescPtr xkb,xkbGetMapReply *rep,char *buf, + ClientPtr client) +{ + unsigned i; + CARD8 * numDesc; + XkbAnyAction * actDesc; + + numDesc = (CARD8 *)buf; + for (i=0;i<rep->nKeyActs;i++) { + if (xkb->server->key_acts[i+rep->firstKeyAct]==0) + numDesc[i] = 0; + else numDesc[i] = XkbKeyNumActions(xkb,(i+rep->firstKeyAct)); + } + buf+= XkbPaddedSize(rep->nKeyActs); + + actDesc = (XkbAnyAction *)buf; + for (i=0;i<rep->nKeyActs;i++) { + if (xkb->server->key_acts[i+rep->firstKeyAct]!=0) { + unsigned int num; + num = XkbKeyNumActions(xkb,(i+rep->firstKeyAct)); + memcpy((char *)actDesc, + (char*)XkbKeyActionsPtr(xkb,(i+rep->firstKeyAct)), + num*SIZEOF(xkbActionWireDesc)); + actDesc+= num; + } + } + buf = (char *)actDesc; + return buf; +} + +static int +XkbSizeKeyBehaviors(XkbDescPtr xkb,xkbGetMapReply *rep) +{ + unsigned i,len,nBhvr; + XkbBehavior * bhv; + + if (((rep->present&XkbKeyBehaviorsMask)==0)||(rep->nKeyBehaviors<1)|| + (!xkb)||(!xkb->server)||(!xkb->server->behaviors)) { + rep->present&= ~XkbKeyBehaviorsMask; + rep->firstKeyBehavior= rep->nKeyBehaviors= 0; + rep->totalKeyBehaviors= 0; + return 0; + } + bhv= &xkb->server->behaviors[rep->firstKeyBehavior]; + for (nBhvr=i=0;i<rep->nKeyBehaviors;i++,bhv++) { + if (bhv->type!=XkbKB_Default) + nBhvr++; + } + len= nBhvr*SIZEOF(xkbBehaviorWireDesc); + rep->totalKeyBehaviors= nBhvr; + return len; +} + +static char * +XkbWriteKeyBehaviors(XkbDescPtr xkb,xkbGetMapReply *rep,char *buf, + ClientPtr client) +{ + unsigned i; + xkbBehaviorWireDesc *wire; + XkbBehavior *pBhvr; + + wire = (xkbBehaviorWireDesc *)buf; + pBhvr= &xkb->server->behaviors[rep->firstKeyBehavior]; + for (i=0;i<rep->nKeyBehaviors;i++,pBhvr++) { + if (pBhvr->type!=XkbKB_Default) { + wire->key= i+rep->firstKeyBehavior; + wire->type= pBhvr->type; + wire->data= pBhvr->data; + wire++; + } + } + buf = (char *)wire; + return buf; +} + +static int +XkbSizeExplicit(XkbDescPtr xkb,xkbGetMapReply *rep) +{ + unsigned i,len,nRtrn; + + if (((rep->present&XkbExplicitComponentsMask)==0)||(rep->nKeyExplicit<1)|| + (!xkb)||(!xkb->server)||(!xkb->server->explicit)) { + rep->present&= ~XkbExplicitComponentsMask; + rep->firstKeyExplicit= rep->nKeyExplicit= 0; + rep->totalKeyExplicit= 0; + return 0; + } + for (nRtrn=i=0;i<rep->nKeyExplicit;i++) { + if (xkb->server->explicit[i+rep->firstKeyExplicit]!=0) + nRtrn++; + } + rep->totalKeyExplicit= nRtrn; + len= XkbPaddedSize(nRtrn*2); /* two bytes per non-zero explicit component */ + return len; +} + +static char * +XkbWriteExplicit(XkbDescPtr xkb,xkbGetMapReply *rep,char *buf,ClientPtr client) +{ +unsigned i; +char * start; +unsigned char * pExp; + + start= buf; + pExp= &xkb->server->explicit[rep->firstKeyExplicit]; + for (i=0;i<rep->nKeyExplicit;i++,pExp++) { + if (*pExp!=0) { + *buf++= i+rep->firstKeyExplicit; + *buf++= *pExp; + } + } + i= XkbPaddedSize(buf-start)-(buf-start); /* pad to word boundary */ + return buf+i; +} + +static int +XkbSizeModifierMap(XkbDescPtr xkb,xkbGetMapReply *rep) +{ + unsigned i,len,nRtrn; + + if (((rep->present&XkbModifierMapMask)==0)||(rep->nModMapKeys<1)|| + (!xkb)||(!xkb->map)||(!xkb->map->modmap)) { + rep->present&= ~XkbModifierMapMask; + rep->firstModMapKey= rep->nModMapKeys= 0; + rep->totalModMapKeys= 0; + return 0; + } + for (nRtrn=i=0;i<rep->nModMapKeys;i++) { + if (xkb->map->modmap[i+rep->firstModMapKey]!=0) + nRtrn++; + } + rep->totalModMapKeys= nRtrn; + len= XkbPaddedSize(nRtrn*2); /* two bytes per non-zero modmap component */ + return len; +} + +static char * +XkbWriteModifierMap(XkbDescPtr xkb,xkbGetMapReply *rep,char *buf, + ClientPtr client) +{ +unsigned i; +char * start; +unsigned char * pMap; + + start= buf; + pMap= &xkb->map->modmap[rep->firstModMapKey]; + for (i=0;i<rep->nModMapKeys;i++,pMap++) { + if (*pMap!=0) { + *buf++= i+rep->firstModMapKey; + *buf++= *pMap; + } + } + i= XkbPaddedSize(buf-start)-(buf-start); /* pad to word boundary */ + return buf+i; +} + +static int +XkbSizeVirtualModMap(XkbDescPtr xkb,xkbGetMapReply *rep) +{ + unsigned i,len,nRtrn; + + if (((rep->present&XkbVirtualModMapMask)==0)||(rep->nVModMapKeys<1)|| + (!xkb)||(!xkb->server)||(!xkb->server->vmodmap)) { + rep->present&= ~XkbVirtualModMapMask; + rep->firstVModMapKey= rep->nVModMapKeys= 0; + rep->totalVModMapKeys= 0; + return 0; + } + for (nRtrn=i=0;i<rep->nVModMapKeys;i++) { + if (xkb->server->vmodmap[i+rep->firstVModMapKey]!=0) + nRtrn++; + } + rep->totalVModMapKeys= nRtrn; + len= nRtrn*SIZEOF(xkbVModMapWireDesc); + return len; +} + +static char * +XkbWriteVirtualModMap(XkbDescPtr xkb,xkbGetMapReply *rep,char *buf, + ClientPtr client) +{ +unsigned i; +xkbVModMapWireDesc * wire; +unsigned short * pMap; + + wire= (xkbVModMapWireDesc *)buf; + pMap= &xkb->server->vmodmap[rep->firstVModMapKey]; + for (i=0;i<rep->nVModMapKeys;i++,pMap++) { + if (*pMap!=0) { + wire->key= i+rep->firstVModMapKey; + wire->vmods= *pMap; + wire++; + } + } + return (char *)wire; +} + +static Status +XkbComputeGetMapReplySize(XkbDescPtr xkb,xkbGetMapReply *rep) +{ +int len; + + rep->minKeyCode= xkb->min_key_code; + rep->maxKeyCode= xkb->max_key_code; + len= XkbSizeKeyTypes(xkb,rep); + len+= XkbSizeKeySyms(xkb,rep); + len+= XkbSizeKeyActions(xkb,rep); + len+= XkbSizeKeyBehaviors(xkb,rep); + len+= XkbSizeVirtualMods(xkb,rep); + len+= XkbSizeExplicit(xkb,rep); + len+= XkbSizeModifierMap(xkb,rep); + len+= XkbSizeVirtualModMap(xkb,rep); + rep->length+= (len/4); + return Success; +} + +static int +XkbSendMap(ClientPtr client,XkbDescPtr xkb,xkbGetMapReply *rep) +{ +unsigned i,len; +char *desc,*start; + + len= (rep->length*4)-(SIZEOF(xkbGetMapReply)-SIZEOF(xGenericReply)); + start= desc= calloc(1, len); + if (!start) + return BadAlloc; + if ( rep->nTypes>0 ) + desc = XkbWriteKeyTypes(xkb,rep,desc,client); + if ( rep->nKeySyms>0 ) + desc = XkbWriteKeySyms(xkb,rep,desc,client); + if ( rep->nKeyActs>0 ) + desc = XkbWriteKeyActions(xkb,rep,desc,client); + if ( rep->totalKeyBehaviors>0 ) + desc = XkbWriteKeyBehaviors(xkb,rep,desc,client); + if ( rep->virtualMods ) { + register int sz,bit; + for (i=sz=0,bit=1;i<XkbNumVirtualMods;i++,bit<<=1) { + if (rep->virtualMods&bit) { + desc[sz++]= xkb->server->vmods[i]; + } + } + desc+= XkbPaddedSize(sz); + } + if ( rep->totalKeyExplicit>0 ) + desc= XkbWriteExplicit(xkb,rep,desc,client); + if ( rep->totalModMapKeys>0 ) + desc= XkbWriteModifierMap(xkb,rep,desc,client); + if ( rep->totalVModMapKeys>0 ) + desc= XkbWriteVirtualModMap(xkb,rep,desc,client); + if ((desc-start)!=(len)) { + ErrorF("[xkb] BOGUS LENGTH in write keyboard desc, expected %d, got %ld\n", + len, (unsigned long)(desc-start)); + } + if (client->swapped) { + register int n; + swaps(&rep->sequenceNumber,n); + swapl(&rep->length,n); + swaps(&rep->present,n); + swaps(&rep->totalSyms,n); + swaps(&rep->totalActs,n); + } + WriteToClient(client, (i=SIZEOF(xkbGetMapReply)), (char *)rep); + WriteToClient(client, len, start); + free((char *)start); + return Success; +} + +int +ProcXkbGetMap(ClientPtr client) +{ + DeviceIntPtr dev; + xkbGetMapReply rep; + XkbDescRec *xkb; + int n,status; + + REQUEST(xkbGetMapReq); + REQUEST_SIZE_MATCH(xkbGetMapReq); + + if (!(client->xkbClientFlags&_XkbClientInitialized)) + return BadAccess; + + CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess); + CHK_MASK_OVERLAP(0x01,stuff->full,stuff->partial); + CHK_MASK_LEGAL(0x02,stuff->full,XkbAllMapComponentsMask); + CHK_MASK_LEGAL(0x03,stuff->partial,XkbAllMapComponentsMask); + + xkb= dev->key->xkbInfo->desc; + memset(&rep, 0, sizeof(xkbGetMapReply)); + rep.type= X_Reply; + rep.sequenceNumber= client->sequence; + rep.length = (SIZEOF(xkbGetMapReply)-SIZEOF(xGenericReply))>>2; + rep.deviceID = dev->id; + rep.present = stuff->partial|stuff->full; + rep.minKeyCode = xkb->min_key_code; + rep.maxKeyCode = xkb->max_key_code; + if ( stuff->full&XkbKeyTypesMask ) { + rep.firstType = 0; + rep.nTypes = xkb->map->num_types; + } + else if (stuff->partial&XkbKeyTypesMask) { + if (((unsigned)stuff->firstType+stuff->nTypes)>xkb->map->num_types) { + client->errorValue = _XkbErrCode4(0x04,xkb->map->num_types, + stuff->firstType,stuff->nTypes); + return BadValue; + } + rep.firstType = stuff->firstType; + rep.nTypes = stuff->nTypes; + } + else rep.nTypes = 0; + rep.totalTypes = xkb->map->num_types; + + n= XkbNumKeys(xkb); + if ( stuff->full&XkbKeySymsMask ) { + rep.firstKeySym = xkb->min_key_code; + rep.nKeySyms = n; + } + else if (stuff->partial&XkbKeySymsMask) { + CHK_KEY_RANGE(0x05,stuff->firstKeySym,stuff->nKeySyms,xkb); + rep.firstKeySym = stuff->firstKeySym; + rep.nKeySyms = stuff->nKeySyms; + } + else rep.nKeySyms = 0; + rep.totalSyms= 0; + + if ( stuff->full&XkbKeyActionsMask ) { + rep.firstKeyAct= xkb->min_key_code; + rep.nKeyActs= n; + } + else if (stuff->partial&XkbKeyActionsMask) { + CHK_KEY_RANGE(0x07,stuff->firstKeyAct,stuff->nKeyActs,xkb); + rep.firstKeyAct= stuff->firstKeyAct; + rep.nKeyActs= stuff->nKeyActs; + } + else rep.nKeyActs= 0; + rep.totalActs= 0; + + if ( stuff->full&XkbKeyBehaviorsMask ) { + rep.firstKeyBehavior = xkb->min_key_code; + rep.nKeyBehaviors = n; + } + else if (stuff->partial&XkbKeyBehaviorsMask) { + CHK_KEY_RANGE(0x09,stuff->firstKeyBehavior,stuff->nKeyBehaviors,xkb); + rep.firstKeyBehavior= stuff->firstKeyBehavior; + rep.nKeyBehaviors= stuff->nKeyBehaviors; + } + else rep.nKeyBehaviors = 0; + rep.totalKeyBehaviors= 0; + + if (stuff->full&XkbVirtualModsMask) + rep.virtualMods= ~0; + else if (stuff->partial&XkbVirtualModsMask) + rep.virtualMods= stuff->virtualMods; + + if (stuff->full&XkbExplicitComponentsMask) { + rep.firstKeyExplicit= xkb->min_key_code; + rep.nKeyExplicit= n; + } + else if (stuff->partial&XkbExplicitComponentsMask) { + CHK_KEY_RANGE(0x0B,stuff->firstKeyExplicit,stuff->nKeyExplicit,xkb); + rep.firstKeyExplicit= stuff->firstKeyExplicit; + rep.nKeyExplicit= stuff->nKeyExplicit; + } + else rep.nKeyExplicit = 0; + rep.totalKeyExplicit= 0; + + if (stuff->full&XkbModifierMapMask) { + rep.firstModMapKey= xkb->min_key_code; + rep.nModMapKeys= n; + } + else if (stuff->partial&XkbModifierMapMask) { + CHK_KEY_RANGE(0x0D,stuff->firstModMapKey,stuff->nModMapKeys,xkb); + rep.firstModMapKey= stuff->firstModMapKey; + rep.nModMapKeys= stuff->nModMapKeys; + } + else rep.nModMapKeys = 0; + rep.totalModMapKeys= 0; + + if (stuff->full&XkbVirtualModMapMask) { + rep.firstVModMapKey= xkb->min_key_code; + rep.nVModMapKeys= n; + } + else if (stuff->partial&XkbVirtualModMapMask) { + CHK_KEY_RANGE(0x0F,stuff->firstVModMapKey,stuff->nVModMapKeys,xkb); + rep.firstVModMapKey= stuff->firstVModMapKey; + rep.nVModMapKeys= stuff->nVModMapKeys; + } + else rep.nVModMapKeys = 0; + rep.totalVModMapKeys= 0; + + if ((status=XkbComputeGetMapReplySize(xkb,&rep))!=Success) + return status; + return XkbSendMap(client,xkb,&rep); +} + +/***====================================================================***/ + +static int +CheckKeyTypes( ClientPtr client, + XkbDescPtr xkb, + xkbSetMapReq * req, + xkbKeyTypeWireDesc **wireRtrn, + int * nMapsRtrn, + CARD8 * mapWidthRtrn) +{ +unsigned nMaps; +register unsigned i,n; +register CARD8 * map; +register xkbKeyTypeWireDesc *wire = *wireRtrn; + + if (req->firstType>((unsigned)xkb->map->num_types)) { + *nMapsRtrn = _XkbErrCode3(0x01,req->firstType,xkb->map->num_types); + return 0; + } + if (req->flags&XkbSetMapResizeTypes) { + nMaps = req->firstType+req->nTypes; + if (nMaps<XkbNumRequiredTypes) { /* canonical types must be there */ + *nMapsRtrn= _XkbErrCode4(0x02,req->firstType,req->nTypes,4); + return 0; + } + } + else if (req->present&XkbKeyTypesMask) { + nMaps = xkb->map->num_types; + if ((req->firstType+req->nTypes)>nMaps) { + *nMapsRtrn = req->firstType+req->nTypes; + return 0; + } + } + else { + *nMapsRtrn = xkb->map->num_types; + for (i=0;i<xkb->map->num_types;i++) { + mapWidthRtrn[i] = xkb->map->types[i].num_levels; + } + return 1; + } + + for (i=0;i<req->firstType;i++) { + mapWidthRtrn[i] = xkb->map->types[i].num_levels; + } + for (i=0;i<req->nTypes;i++) { + unsigned width; + if (client->swapped) { + register int s; + swaps(&wire->virtualMods,s); + } + n= i+req->firstType; + width= wire->numLevels; + if (width<1) { + *nMapsRtrn= _XkbErrCode3(0x04,n,width); + return 0; + } + else if ((n==XkbOneLevelIndex)&&(width!=1)) { /* must be width 1 */ + *nMapsRtrn= _XkbErrCode3(0x05,n,width); + return 0; + } + else if ((width!=2)&& + ((n==XkbTwoLevelIndex)||(n==XkbKeypadIndex)|| + (n==XkbAlphabeticIndex))) { + /* TWO_LEVEL, ALPHABETIC and KEYPAD must be width 2 */ + *nMapsRtrn= _XkbErrCode3(0x05,n,width); + return 0; + } + if (wire->nMapEntries>0) { + xkbKTSetMapEntryWireDesc * mapWire; + xkbModsWireDesc * preWire; + mapWire= (xkbKTSetMapEntryWireDesc *)&wire[1]; + preWire= (xkbModsWireDesc *)&mapWire[wire->nMapEntries]; + for (n=0;n<wire->nMapEntries;n++) { + if (client->swapped) { + register int s; + swaps(&mapWire[n].virtualMods,s); + } + if (mapWire[n].realMods&(~wire->realMods)) { + *nMapsRtrn= _XkbErrCode4(0x06,n,mapWire[n].realMods, + wire->realMods); + return 0; + } + if (mapWire[n].virtualMods&(~wire->virtualMods)) { + *nMapsRtrn= _XkbErrCode3(0x07,n,mapWire[n].virtualMods); + return 0; + } + if (mapWire[n].level>=wire->numLevels) { + *nMapsRtrn= _XkbErrCode4(0x08,n,wire->numLevels, + mapWire[n].level); + return 0; + } + if (wire->preserve) { + if (client->swapped) { + register int s; + swaps(&preWire[n].virtualMods,s); + } + if (preWire[n].realMods&(~mapWire[n].realMods)) { + *nMapsRtrn= _XkbErrCode4(0x09,n,preWire[n].realMods, + mapWire[n].realMods); + return 0; + } + if (preWire[n].virtualMods&(~mapWire[n].virtualMods)) { + *nMapsRtrn=_XkbErrCode3(0x0a,n,preWire[n].virtualMods); + return 0; + } + } + } + if (wire->preserve) + map= (CARD8 *)&preWire[wire->nMapEntries]; + else map= (CARD8 *)&mapWire[wire->nMapEntries]; + } + else map= (CARD8 *)&wire[1]; + mapWidthRtrn[i+req->firstType] = wire->numLevels; + wire= (xkbKeyTypeWireDesc *)map; + } + for (i=req->firstType+req->nTypes;i<nMaps;i++) { + mapWidthRtrn[i] = xkb->map->types[i].num_levels; + } + *nMapsRtrn = nMaps; + *wireRtrn = wire; + return 1; +} + +static int +CheckKeySyms( ClientPtr client, + XkbDescPtr xkb, + xkbSetMapReq * req, + int nTypes, + CARD8 * mapWidths, + CARD16 * symsPerKey, + xkbSymMapWireDesc ** wireRtrn, + int * errorRtrn) +{ +register unsigned i; +XkbSymMapPtr map; +xkbSymMapWireDesc* wire = *wireRtrn; + + if (!(XkbKeySymsMask&req->present)) + return 1; + CHK_REQ_KEY_RANGE2(0x11,req->firstKeySym,req->nKeySyms,req,(*errorRtrn),0); + for (i=0;i<req->nKeySyms;i++) { + KeySym *pSyms; + register unsigned nG; + if (client->swapped) { + swaps(&wire->nSyms,nG); + } + nG = XkbNumGroups(wire->groupInfo); + if (nG>XkbNumKbdGroups) { + *errorRtrn = _XkbErrCode3(0x14,i+req->firstKeySym,nG); + return 0; + } + if (nG>0) { + register int g,w; + for (g=w=0;g<nG;g++) { + if (wire->ktIndex[g]>=(unsigned)nTypes) { + *errorRtrn= _XkbErrCode4(0x15,i+req->firstKeySym,g, + wire->ktIndex[g]); + return 0; + } + if (mapWidths[wire->ktIndex[g]]>w) + w= mapWidths[wire->ktIndex[g]]; + } + if (wire->width!=w) { + *errorRtrn= _XkbErrCode3(0x16,i+req->firstKeySym,wire->width); + return 0; + } + w*= nG; + symsPerKey[i+req->firstKeySym] = w; + if (w!=wire->nSyms) { + *errorRtrn=_XkbErrCode4(0x16,i+req->firstKeySym,wire->nSyms,w); + return 0; + } + } + else if (wire->nSyms!=0) { + *errorRtrn = _XkbErrCode3(0x17,i+req->firstKeySym,wire->nSyms); + return 0; + } + pSyms = (KeySym *)&wire[1]; + wire = (xkbSymMapWireDesc *)&pSyms[wire->nSyms]; + } + + map = &xkb->map->key_sym_map[i]; + for (;i<=(unsigned)xkb->max_key_code;i++,map++) { + register int g,nG,w; + nG= XkbKeyNumGroups(xkb,i); + for (w=g=0;g<nG;g++) { + if (map->kt_index[g]>=(unsigned)nTypes) { + *errorRtrn = _XkbErrCode4(0x18,i,g,map->kt_index[g]); + return 0; + } + if (mapWidths[map->kt_index[g]]>w) + w= mapWidths[map->kt_index[g]]; + } + symsPerKey[i] = w*nG; + } + *wireRtrn = wire; + return 1; +} + +static int +CheckKeyActions( XkbDescPtr xkb, + xkbSetMapReq * req, + int nTypes, + CARD8 * mapWidths, + CARD16 * symsPerKey, + CARD8 ** wireRtrn, + int * nActsRtrn) +{ +int nActs; +CARD8 * wire = *wireRtrn; +register unsigned i; + + if (!(XkbKeyActionsMask&req->present)) + return 1; + CHK_REQ_KEY_RANGE2(0x21,req->firstKeyAct,req->nKeyActs,req,(*nActsRtrn),0); + for (nActs=i=0;i<req->nKeyActs;i++) { + if (wire[0]!=0) { + if (wire[0]==symsPerKey[i+req->firstKeyAct]) + nActs+= wire[0]; + else { + *nActsRtrn= _XkbErrCode3(0x23,i+req->firstKeyAct,wire[0]); + return 0; + } + } + wire++; + } + if (req->nKeyActs%4) + wire+= 4-(req->nKeyActs%4); + *wireRtrn = (CARD8 *)(((XkbAnyAction *)wire)+nActs); + *nActsRtrn = nActs; + return 1; +} + +static int +CheckKeyBehaviors( XkbDescPtr xkb, + xkbSetMapReq * req, + xkbBehaviorWireDesc ** wireRtrn, + int * errorRtrn) +{ +register xkbBehaviorWireDesc * wire = *wireRtrn; +register XkbServerMapPtr server = xkb->server; +register unsigned i; +unsigned first,last; + + if (((req->present&XkbKeyBehaviorsMask)==0)||(req->nKeyBehaviors<1)) { + req->present&= ~XkbKeyBehaviorsMask; + req->nKeyBehaviors= 0; + return 1; + } + first= req->firstKeyBehavior; + last= req->firstKeyBehavior+req->nKeyBehaviors-1; + if (first<req->minKeyCode) { + *errorRtrn = _XkbErrCode3(0x31,first,req->minKeyCode); + return 0; + } + if (last>req->maxKeyCode) { + *errorRtrn = _XkbErrCode3(0x32,last,req->maxKeyCode); + return 0; + } + + for (i=0;i<req->totalKeyBehaviors;i++,wire++) { + if ((wire->key<first)||(wire->key>last)) { + *errorRtrn = _XkbErrCode4(0x33,first,last,wire->key); + return 0; + } + if ((wire->type&XkbKB_Permanent)&& + ((server->behaviors[wire->key].type!=wire->type)|| + (server->behaviors[wire->key].data!=wire->data))) { + *errorRtrn = _XkbErrCode3(0x33,wire->key,wire->type); + return 0; + } + if ((wire->type==XkbKB_RadioGroup)&& + ((wire->data&(~XkbKB_RGAllowNone))>XkbMaxRadioGroups)) { + *errorRtrn= _XkbErrCode4(0x34,wire->key,wire->data, + XkbMaxRadioGroups); + return 0; + } + if ((wire->type==XkbKB_Overlay1)||(wire->type==XkbKB_Overlay2)) { + CHK_KEY_RANGE2(0x35,wire->key,1,xkb,*errorRtrn,0); + } + } + *wireRtrn = wire; + return 1; +} + +static int +CheckVirtualMods( XkbDescRec * xkb, + xkbSetMapReq * req, + CARD8 ** wireRtrn, + int * errorRtrn) +{ +register CARD8 *wire = *wireRtrn; +register unsigned i,nMods,bit; + + if (((req->present&XkbVirtualModsMask)==0)||(req->virtualMods==0)) + return 1; + for (i=nMods=0,bit=1;i<XkbNumVirtualMods;i++,bit<<=1) { + if (req->virtualMods&bit) + nMods++; + } + *wireRtrn= (wire+XkbPaddedSize(nMods)); + return 1; +} + +static int +CheckKeyExplicit( XkbDescPtr xkb, + xkbSetMapReq * req, + CARD8 ** wireRtrn, + int * errorRtrn) +{ +register CARD8 * wire = *wireRtrn; +CARD8 * start; +register unsigned i; +int first,last; + + if (((req->present&XkbExplicitComponentsMask)==0)||(req->nKeyExplicit<1)) { + req->present&= ~XkbExplicitComponentsMask; + req->nKeyExplicit= 0; + return 1; + } + first= req->firstKeyExplicit; + last= first+req->nKeyExplicit-1; + if (first<req->minKeyCode) { + *errorRtrn = _XkbErrCode3(0x51,first,req->minKeyCode); + return 0; + } + if (last>req->maxKeyCode) { + *errorRtrn = _XkbErrCode3(0x52,last,req->maxKeyCode); + return 0; + } + start= wire; + for (i=0;i<req->totalKeyExplicit;i++,wire+=2) { + if ((wire[0]<first)||(wire[0]>last)) { + *errorRtrn = _XkbErrCode4(0x53,first,last,wire[0]); + return 0; + } + if (wire[1]&(~XkbAllExplicitMask)) { + *errorRtrn= _XkbErrCode3(0x52,~XkbAllExplicitMask,wire[1]); + return 0; + } + } + wire+= XkbPaddedSize(wire-start)-(wire-start); + *wireRtrn= wire; + return 1; +} + +static int +CheckModifierMap(XkbDescPtr xkb,xkbSetMapReq *req,CARD8 **wireRtrn,int *errRtrn) +{ +register CARD8 * wire = *wireRtrn; +CARD8 * start; +register unsigned i; +int first,last; + + if (((req->present&XkbModifierMapMask)==0)||(req->nModMapKeys<1)) { + req->present&= ~XkbModifierMapMask; + req->nModMapKeys= 0; + return 1; + } + first= req->firstModMapKey; + last= first+req->nModMapKeys-1; + if (first<req->minKeyCode) { + *errRtrn = _XkbErrCode3(0x61,first,req->minKeyCode); + return 0; + } + if (last>req->maxKeyCode) { + *errRtrn = _XkbErrCode3(0x62,last,req->maxKeyCode); + return 0; + } + start= wire; + for (i=0;i<req->totalModMapKeys;i++,wire+=2) { + if ((wire[0]<first)||(wire[0]>last)) { + *errRtrn = _XkbErrCode4(0x63,first,last,wire[0]); + return 0; + } + } + wire+= XkbPaddedSize(wire-start)-(wire-start); + *wireRtrn= wire; + return 1; +} + +static int +CheckVirtualModMap( XkbDescPtr xkb, + xkbSetMapReq *req, + xkbVModMapWireDesc **wireRtrn, + int *errRtrn) +{ +register xkbVModMapWireDesc * wire = *wireRtrn; +register unsigned i; +int first,last; + + if (((req->present&XkbVirtualModMapMask)==0)||(req->nVModMapKeys<1)) { + req->present&= ~XkbVirtualModMapMask; + req->nVModMapKeys= 0; + return 1; + } + first= req->firstVModMapKey; + last= first+req->nVModMapKeys-1; + if (first<req->minKeyCode) { + *errRtrn = _XkbErrCode3(0x71,first,req->minKeyCode); + return 0; + } + if (last>req->maxKeyCode) { + *errRtrn = _XkbErrCode3(0x72,last,req->maxKeyCode); + return 0; + } + for (i=0;i<req->totalVModMapKeys;i++,wire++) { + if ((wire->key<first)||(wire->key>last)) { + *errRtrn = _XkbErrCode4(0x73,first,last,wire->key); + return 0; + } + } + *wireRtrn= wire; + return 1; +} + +static char * +SetKeyTypes( XkbDescPtr xkb, + xkbSetMapReq * req, + xkbKeyTypeWireDesc * wire, + XkbChangesPtr changes) +{ +register unsigned i; +unsigned first,last; +CARD8 *map; + + if ((unsigned)(req->firstType+req->nTypes)>xkb->map->size_types) { + i= req->firstType+req->nTypes; + if (XkbAllocClientMap(xkb,XkbKeyTypesMask,i)!=Success) { + return NULL; + } + } + if ((unsigned)(req->firstType+req->nTypes)>xkb->map->num_types) + xkb->map->num_types= req->firstType+req->nTypes; + + for (i=0;i<req->nTypes;i++) { + XkbKeyTypePtr pOld; + register unsigned n; + + if (XkbResizeKeyType(xkb,i+req->firstType,wire->nMapEntries, + wire->preserve,wire->numLevels)!=Success) { + return NULL; + } + pOld = &xkb->map->types[i+req->firstType]; + map = (CARD8 *)&wire[1]; + + pOld->mods.real_mods = wire->realMods; + pOld->mods.vmods= wire->virtualMods; + pOld->num_levels = wire->numLevels; + pOld->map_count= wire->nMapEntries; + + pOld->mods.mask= pOld->mods.real_mods| + XkbMaskForVMask(xkb,pOld->mods.vmods); + + if (wire->nMapEntries) { + xkbKTSetMapEntryWireDesc *mapWire; + xkbModsWireDesc *preWire; + unsigned tmp; + mapWire= (xkbKTSetMapEntryWireDesc *)map; + preWire= (xkbModsWireDesc *)&mapWire[wire->nMapEntries]; + for (n=0;n<wire->nMapEntries;n++) { + pOld->map[n].active= 1; + pOld->map[n].mods.mask= mapWire[n].realMods; + pOld->map[n].mods.real_mods= mapWire[n].realMods; + pOld->map[n].mods.vmods= mapWire[n].virtualMods; + pOld->map[n].level= mapWire[n].level; + if (mapWire[n].virtualMods!=0) { + tmp= XkbMaskForVMask(xkb,mapWire[n].virtualMods); + pOld->map[n].active= (tmp!=0); + pOld->map[n].mods.mask|= tmp; + } + if (wire->preserve) { + pOld->preserve[n].real_mods= preWire[n].realMods; + pOld->preserve[n].vmods= preWire[n].virtualMods; + tmp= XkbMaskForVMask(xkb,preWire[n].virtualMods); + pOld->preserve[n].mask= preWire[n].realMods|tmp; + } + } + if (wire->preserve) + map= (CARD8 *)&preWire[wire->nMapEntries]; + else map= (CARD8 *)&mapWire[wire->nMapEntries]; + } + else map= (CARD8 *)&wire[1]; + wire = (xkbKeyTypeWireDesc *)map; + } + first= req->firstType; + last= first+req->nTypes-1; /* last changed type */ + if (changes->map.changed&XkbKeyTypesMask) { + int oldLast; + oldLast= changes->map.first_type+changes->map.num_types-1; + if (changes->map.first_type<first) + first= changes->map.first_type; + if (oldLast>last) + last= oldLast; + } + changes->map.changed|= XkbKeyTypesMask; + changes->map.first_type = first; + changes->map.num_types = (last-first)+1; + return (char *)wire; +} + +static char * +SetKeySyms( ClientPtr client, + XkbDescPtr xkb, + xkbSetMapReq * req, + xkbSymMapWireDesc * wire, + XkbChangesPtr changes, + DeviceIntPtr dev) +{ +register unsigned i,s; +XkbSymMapPtr oldMap; +KeySym * newSyms; +KeySym * pSyms; +unsigned first,last; + + oldMap = &xkb->map->key_sym_map[req->firstKeySym]; + for (i=0;i<req->nKeySyms;i++,oldMap++) { + pSyms = (KeySym *)&wire[1]; + if (wire->nSyms>0) { + newSyms = XkbResizeKeySyms(xkb,i+req->firstKeySym,wire->nSyms); + for (s=0;s<wire->nSyms;s++) { + newSyms[s]= pSyms[s]; + } + if (client->swapped) { + int n; + for (s=0;s<wire->nSyms;s++) { + swapl(&newSyms[s],n); + } + } + } + oldMap->kt_index[0] = wire->ktIndex[0]; + oldMap->kt_index[1] = wire->ktIndex[1]; + oldMap->kt_index[2] = wire->ktIndex[2]; + oldMap->kt_index[3] = wire->ktIndex[3]; + oldMap->group_info = wire->groupInfo; + oldMap->width = wire->width; + wire= (xkbSymMapWireDesc *)&pSyms[wire->nSyms]; + } + first= req->firstKeySym; + last= first+req->nKeySyms-1; + if (changes->map.changed&XkbKeySymsMask) { + int oldLast= (changes->map.first_key_sym+changes->map.num_key_syms-1); + if (changes->map.first_key_sym<first) + first= changes->map.first_key_sym; + if (oldLast>last) + last= oldLast; + } + changes->map.changed|= XkbKeySymsMask; + changes->map.first_key_sym = first; + changes->map.num_key_syms = (last-first+1); + + s= 0; + for (i=xkb->min_key_code;i<=xkb->max_key_code;i++) { + if (XkbKeyNumGroups(xkb,i)>s) + s= XkbKeyNumGroups(xkb,i); + } + if (s!=xkb->ctrls->num_groups) { + xkbControlsNotify cn; + XkbControlsRec old; + cn.keycode= 0; + cn.eventType= 0; + cn.requestMajor= XkbReqCode; + cn.requestMinor= X_kbSetMap; + old= *xkb->ctrls; + xkb->ctrls->num_groups= s; + if (XkbComputeControlsNotify(dev,&old,xkb->ctrls,&cn,FALSE)) + XkbSendControlsNotify(dev,&cn); + } + return (char *)wire; +} + +static char * +SetKeyActions( XkbDescPtr xkb, + xkbSetMapReq * req, + CARD8 * wire, + XkbChangesPtr changes) +{ +register unsigned i,first,last; +CARD8 * nActs = wire; +XkbAction * newActs; + + wire+= XkbPaddedSize(req->nKeyActs); + for (i=0;i<req->nKeyActs;i++) { + if (nActs[i]==0) + xkb->server->key_acts[i+req->firstKeyAct]= 0; + else { + newActs= XkbResizeKeyActions(xkb,i+req->firstKeyAct,nActs[i]); + memcpy((char *)newActs,(char *)wire, + nActs[i]*SIZEOF(xkbActionWireDesc)); + wire+= nActs[i]*SIZEOF(xkbActionWireDesc); + } + } + first= req->firstKeyAct; + last= (first+req->nKeyActs-1); + if (changes->map.changed&XkbKeyActionsMask) { + int oldLast; + oldLast= changes->map.first_key_act+changes->map.num_key_acts-1; + if (changes->map.first_key_act<first) + first= changes->map.first_key_act; + if (oldLast>last) + last= oldLast; + } + changes->map.changed|= XkbKeyActionsMask; + changes->map.first_key_act= first; + changes->map.num_key_acts= (last-first+1); + return (char *)wire; +} + +static char * +SetKeyBehaviors( XkbSrvInfoPtr xkbi, + xkbSetMapReq *req, + xkbBehaviorWireDesc *wire, + XkbChangesPtr changes) +{ +register unsigned i; +int maxRG = -1; +XkbDescPtr xkb = xkbi->desc; +XkbServerMapPtr server = xkb->server; +unsigned first,last; + + first= req->firstKeyBehavior; + last= req->firstKeyBehavior+req->nKeyBehaviors-1; + memset(&server->behaviors[first], 0, req->nKeyBehaviors*sizeof(XkbBehavior)); + for (i=0;i<req->totalKeyBehaviors;i++) { + if ((server->behaviors[wire->key].type&XkbKB_Permanent)==0) { + server->behaviors[wire->key].type= wire->type; + server->behaviors[wire->key].data= wire->data; + if ((wire->type==XkbKB_RadioGroup)&&(((int)wire->data)>maxRG)) + maxRG= wire->data + 1; + } + wire++; + } + + if (maxRG>(int)xkbi->nRadioGroups) { + int sz = maxRG*sizeof(XkbRadioGroupRec); + if (xkbi->radioGroups) + xkbi->radioGroups= realloc(xkbi->radioGroups,sz); + else xkbi->radioGroups= calloc(1, sz); + if (xkbi->radioGroups) { + if (xkbi->nRadioGroups) + memset(&xkbi->radioGroups[xkbi->nRadioGroups], 0, + (maxRG-xkbi->nRadioGroups)*sizeof(XkbRadioGroupRec)); + xkbi->nRadioGroups= maxRG; + } + else xkbi->nRadioGroups= 0; + /* should compute members here */ + } + if (changes->map.changed&XkbKeyBehaviorsMask) { + unsigned oldLast; + oldLast= changes->map.first_key_behavior+ + changes->map.num_key_behaviors-1; + if (changes->map.first_key_behavior<req->firstKeyBehavior) + first= changes->map.first_key_behavior; + if (oldLast>last) + last= oldLast; + } + changes->map.changed|= XkbKeyBehaviorsMask; + changes->map.first_key_behavior = first; + changes->map.num_key_behaviors = (last-first+1); + return (char *)wire; +} + +static char * +SetVirtualMods(XkbSrvInfoPtr xkbi,xkbSetMapReq *req,CARD8 *wire, + XkbChangesPtr changes) +{ +register int i,bit,nMods; +XkbServerMapPtr srv = xkbi->desc->server; + + if (((req->present&XkbVirtualModsMask)==0)||(req->virtualMods==0)) + return (char *)wire; + for (i=nMods=0,bit=1;i<XkbNumVirtualMods;i++,bit<<=1) { + if (req->virtualMods&bit) { + if (srv->vmods[i]!=wire[nMods]) { + changes->map.changed|= XkbVirtualModsMask; + changes->map.vmods|= bit; + srv->vmods[i]= wire[nMods]; + } + nMods++; + } + } + return (char *)(wire+XkbPaddedSize(nMods)); +} + +static char * +SetKeyExplicit(XkbSrvInfoPtr xkbi,xkbSetMapReq *req,CARD8 *wire, + XkbChangesPtr changes) +{ +register unsigned i,first,last; +XkbServerMapPtr xkb = xkbi->desc->server; +CARD8 * start; + + start= wire; + first= req->firstKeyExplicit; + last= req->firstKeyExplicit+req->nKeyExplicit-1; + memset(&xkb->explicit[first], 0, req->nKeyExplicit); + for (i=0;i<req->totalKeyExplicit;i++,wire+= 2) { + xkb->explicit[wire[0]]= wire[1]; + } + if (first>0) { + if (changes->map.changed&XkbExplicitComponentsMask) { + int oldLast; + oldLast= changes->map.first_key_explicit+ + changes->map.num_key_explicit-1; + if (changes->map.first_key_explicit<first) + first= changes->map.first_key_explicit; + if (oldLast>last) + last= oldLast; + } + changes->map.first_key_explicit= first; + changes->map.num_key_explicit= (last-first)+1; + } + wire+= XkbPaddedSize(wire-start)-(wire-start); + return (char *)wire; +} + +static char * +SetModifierMap( XkbSrvInfoPtr xkbi, + xkbSetMapReq * req, + CARD8 * wire, + XkbChangesPtr changes) +{ +register unsigned i,first,last; +XkbClientMapPtr xkb = xkbi->desc->map; +CARD8 * start; + + start= wire; + first= req->firstModMapKey; + last= req->firstModMapKey+req->nModMapKeys-1; + memset(&xkb->modmap[first], 0, req->nModMapKeys); + for (i=0;i<req->totalModMapKeys;i++,wire+= 2) { + xkb->modmap[wire[0]]= wire[1]; + } + if (first>0) { + if (changes->map.changed&XkbModifierMapMask) { + int oldLast; + oldLast= changes->map.first_modmap_key+ + changes->map.num_modmap_keys-1; + if (changes->map.first_modmap_key<first) + first= changes->map.first_modmap_key; + if (oldLast>last) + last= oldLast; + } + changes->map.first_modmap_key= first; + changes->map.num_modmap_keys= (last-first)+1; + } + wire+= XkbPaddedSize(wire-start)-(wire-start); + return (char *)wire; +} + +static char * +SetVirtualModMap( XkbSrvInfoPtr xkbi, + xkbSetMapReq * req, + xkbVModMapWireDesc * wire, + XkbChangesPtr changes) +{ +register unsigned i,first,last; +XkbServerMapPtr srv = xkbi->desc->server; + + first= req->firstVModMapKey; + last= req->firstVModMapKey+req->nVModMapKeys-1; + memset(&srv->vmodmap[first], 0, req->nVModMapKeys*sizeof(unsigned short)); + for (i=0;i<req->totalVModMapKeys;i++,wire++) { + srv->vmodmap[wire->key]= wire->vmods; + } + if (first>0) { + if (changes->map.changed&XkbVirtualModMapMask) { + int oldLast; + oldLast= changes->map.first_vmodmap_key+ + changes->map.num_vmodmap_keys-1; + if (changes->map.first_vmodmap_key<first) + first= changes->map.first_vmodmap_key; + if (oldLast>last) + last= oldLast; + } + changes->map.first_vmodmap_key= first; + changes->map.num_vmodmap_keys= (last-first)+1; + } + return (char *)wire; +} + +/** + * Check if the given request can be applied to the given device but don't + * actually do anything.. + */ +static int +_XkbSetMapChecks(ClientPtr client, DeviceIntPtr dev, xkbSetMapReq *req, char* values) +{ + XkbSrvInfoPtr xkbi; + XkbDescPtr xkb; + int error; + int nTypes = 0, nActions; + CARD8 mapWidths[XkbMaxLegalKeyCode + 1] = {0}; + CARD16 symsPerKey[XkbMaxLegalKeyCode + 1] = {0}; + XkbSymMapPtr map; + int i; + + xkbi= dev->key->xkbInfo; + xkb = xkbi->desc; + + if ((xkb->min_key_code != req->minKeyCode)|| + (xkb->max_key_code != req->maxKeyCode)) { + if (client->vMajor!=1) { /* pre 1.0 versions of Xlib have a bug */ + req->minKeyCode= xkb->min_key_code; + req->maxKeyCode= xkb->max_key_code; + } + else { + if (!XkbIsLegalKeycode(req->minKeyCode)) { + client->errorValue = _XkbErrCode3(2, req->minKeyCode, req->maxKeyCode); + return BadValue; + } + if (req->minKeyCode > req->maxKeyCode) { + client->errorValue = _XkbErrCode3(3, req->minKeyCode, req->maxKeyCode); + return BadMatch; + } + } + } + + if ((req->present & XkbKeyTypesMask) && + (!CheckKeyTypes(client,xkb,req,(xkbKeyTypeWireDesc **)&values, + &nTypes,mapWidths))) { + client->errorValue = nTypes; + return BadValue; + } + + /* symsPerKey/mapWidths must be filled regardless of client-side flags */ + map = &xkb->map->key_sym_map[xkb->min_key_code]; + for (i=xkb->min_key_code;i<xkb->max_key_code;i++,map++) { + register int g,ng,w; + ng= XkbNumGroups(map->group_info); + for (w=g=0;g<ng;g++) { + if (map->kt_index[g]>=(unsigned)nTypes) { + client->errorValue = _XkbErrCode4(0x13,i,g,map->kt_index[g]); + return 0; + } + if (mapWidths[map->kt_index[g]]>w) + w= mapWidths[map->kt_index[g]]; + } + symsPerKey[i] = w*ng; + } + + if ((req->present & XkbKeySymsMask) && + (!CheckKeySyms(client,xkb,req,nTypes,mapWidths,symsPerKey, + (xkbSymMapWireDesc **)&values,&error))) { + client->errorValue = error; + return BadValue; + } + + if ((req->present & XkbKeyActionsMask) && + (!CheckKeyActions(xkb,req,nTypes,mapWidths,symsPerKey, + (CARD8 **)&values,&nActions))) { + client->errorValue = nActions; + return BadValue; + } + + if ((req->present & XkbKeyBehaviorsMask) && + (!CheckKeyBehaviors(xkb,req,(xkbBehaviorWireDesc**)&values,&error))) { + client->errorValue = error; + return BadValue; + } + + if ((req->present & XkbVirtualModsMask) && + (!CheckVirtualMods(xkb,req,(CARD8 **)&values,&error))) { + client->errorValue= error; + return BadValue; + } + if ((req->present&XkbExplicitComponentsMask) && + (!CheckKeyExplicit(xkb,req,(CARD8 **)&values,&error))) { + client->errorValue= error; + return BadValue; + } + if ((req->present&XkbModifierMapMask) && + (!CheckModifierMap(xkb,req,(CARD8 **)&values,&error))) { + client->errorValue= error; + return BadValue; + } + if ((req->present&XkbVirtualModMapMask) && + (!CheckVirtualModMap(xkb,req,(xkbVModMapWireDesc **)&values,&error))) { + client->errorValue= error; + return BadValue; + } + + if (((values-((char *)req))/4)!= req->length) { + ErrorF("[xkb] Internal error! Bad length in XkbSetMap (after check)\n"); + client->errorValue = values-((char *)&req[1]); + return BadLength; + } + + return Success; +} + +/** + * Apply the given request on the given device. + */ +static int +_XkbSetMap(ClientPtr client, DeviceIntPtr dev, xkbSetMapReq *req, char *values) +{ + XkbEventCauseRec cause; + XkbChangesRec change; + Bool sentNKN; + XkbSrvInfoPtr xkbi; + XkbDescPtr xkb; + + xkbi= dev->key->xkbInfo; + xkb = xkbi->desc; + + XkbSetCauseXkbReq(&cause,X_kbSetMap,client); + memset(&change, 0, sizeof(change)); + sentNKN = FALSE; + if ((xkb->min_key_code!=req->minKeyCode)|| + (xkb->max_key_code!=req->maxKeyCode)) { + Status status; + xkbNewKeyboardNotify nkn; + nkn.deviceID = nkn.oldDeviceID = dev->id; + nkn.oldMinKeyCode = xkb->min_key_code; + nkn.oldMaxKeyCode = xkb->max_key_code; + status= XkbChangeKeycodeRange(xkb, req->minKeyCode, + req->maxKeyCode, &change); + if (status != Success) + return status; /* oh-oh. what about the other keyboards? */ + nkn.minKeyCode = xkb->min_key_code; + nkn.maxKeyCode = xkb->max_key_code; + nkn.requestMajor = XkbReqCode; + nkn.requestMinor = X_kbSetMap; + nkn.changed = XkbNKN_KeycodesMask; + XkbSendNewKeyboardNotify(dev,&nkn); + sentNKN = TRUE; + } + + if (req->present&XkbKeyTypesMask) { + values = SetKeyTypes(xkb,req,(xkbKeyTypeWireDesc *)values,&change); + if (!values) goto allocFailure; + } + if (req->present&XkbKeySymsMask) { + values = SetKeySyms(client,xkb,req,(xkbSymMapWireDesc *)values,&change,dev); + if (!values) goto allocFailure; + } + if (req->present&XkbKeyActionsMask) { + values = SetKeyActions(xkb,req,(CARD8 *)values,&change); + if (!values) goto allocFailure; + } + if (req->present&XkbKeyBehaviorsMask) { + values= SetKeyBehaviors(xkbi,req,(xkbBehaviorWireDesc *)values,&change); + if (!values) goto allocFailure; + } + if (req->present&XkbVirtualModsMask) + values= SetVirtualMods(xkbi,req,(CARD8 *)values,&change); + if (req->present&XkbExplicitComponentsMask) + values= SetKeyExplicit(xkbi,req,(CARD8 *)values,&change); + if (req->present&XkbModifierMapMask) + values= SetModifierMap(xkbi,req,(CARD8 *)values,&change); + if (req->present&XkbVirtualModMapMask) + values= SetVirtualModMap(xkbi,req,(xkbVModMapWireDesc *)values,&change); + if (((values-((char *)req))/4)!=req->length) { + ErrorF("[xkb] Internal error! Bad length in XkbSetMap (after set)\n"); + client->errorValue = values-((char *)&req[1]); + return BadLength; + } + if (req->flags&XkbSetMapRecomputeActions) { + KeyCode first,last,firstMM,lastMM; + if (change.map.num_key_syms>0) { + first= change.map.first_key_sym; + last= first+change.map.num_key_syms-1; + } + else first= last= 0; + if (change.map.num_modmap_keys>0) { + firstMM= change.map.first_modmap_key; + lastMM= first+change.map.num_modmap_keys-1; + } + else firstMM= lastMM= 0; + if ((last>0) && (lastMM>0)) { + if (firstMM<first) + first= firstMM; + if (lastMM>last) + last= lastMM; + } + else if (lastMM>0) { + first= firstMM; + last= lastMM; + } + if (last>0) { + unsigned check= 0; + XkbUpdateActions(dev,first,(last-first+1),&change,&check,&cause); + if (check) + XkbCheckSecondaryEffects(xkbi,check,&change,&cause); + } + } + if (!sentNKN) + XkbSendNotification(dev,&change,&cause); + + return Success; +allocFailure: + return BadAlloc; +} + + +int +ProcXkbSetMap(ClientPtr client) +{ + DeviceIntPtr dev; + char * tmp; + int rc; + + REQUEST(xkbSetMapReq); + REQUEST_AT_LEAST_SIZE(xkbSetMapReq); + + if (!(client->xkbClientFlags&_XkbClientInitialized)) + return BadAccess; + + CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess); + CHK_MASK_LEGAL(0x01,stuff->present,XkbAllMapComponentsMask); + + tmp = (char *)&stuff[1]; + + /* Check if we can to the SetMap on the requested device. If this + succeeds, do the same thing for all extension devices (if needed). + If any of them fails, fail. */ + rc = _XkbSetMapChecks(client, dev, stuff, tmp); + + if (rc != Success) + return rc; + + if (stuff->deviceSpec == XkbUseCoreKbd) + { + DeviceIntPtr other; + for (other = inputInfo.devices; other; other = other->next) + { + if ((other != dev) && other->key && !IsMaster(other) && GetMaster(other, MASTER_KEYBOARD) == dev) + { + rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixManageAccess); + if (rc == Success) + { + rc = _XkbSetMapChecks(client, other, stuff, tmp); + if (rc != Success) + return rc; + } + } + } + } + + /* We know now that we will succed with the SetMap. In theory anyway. */ + rc = _XkbSetMap(client, dev, stuff, tmp); + if (rc != Success) + return rc; + + if (stuff->deviceSpec == XkbUseCoreKbd) + { + DeviceIntPtr other; + for (other = inputInfo.devices; other; other = other->next) + { + if ((other != dev) && other->key && !IsMaster(other) && GetMaster(other, MASTER_KEYBOARD) == dev) + { + rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixManageAccess); + if (rc == Success) + _XkbSetMap(client, other, stuff, tmp); + /* ignore rc. if the SetMap failed although the check above + reported true there isn't much we can do. we still need to + set all other devices, hoping that at least they stay in + sync. */ + } + } + } + + return Success; +} + +/***====================================================================***/ + +static Status +XkbComputeGetCompatMapReplySize( XkbCompatMapPtr compat, + xkbGetCompatMapReply * rep) +{ +unsigned size,nGroups; + + nGroups= 0; + if (rep->groups!=0) { + register int i,bit; + for (i=0,bit=1;i<XkbNumKbdGroups;i++,bit<<=1) { + if (rep->groups&bit) + nGroups++; + } + } + size= nGroups*SIZEOF(xkbModsWireDesc); + size+= (rep->nSI*SIZEOF(xkbSymInterpretWireDesc)); + rep->length= size/4; + return Success; +} + +static int +XkbSendCompatMap( ClientPtr client, + XkbCompatMapPtr compat, + xkbGetCompatMapReply * rep) +{ +char * data; +int size; + + size= rep->length*4; + if (size>0) { + data = malloc(size); + if (data) { + register unsigned i,bit; + xkbModsWireDesc * grp; + XkbSymInterpretPtr sym= &compat->sym_interpret[rep->firstSI]; + xkbSymInterpretWireDesc *wire = (xkbSymInterpretWireDesc *)data; + for (i=0;i<rep->nSI;i++,sym++,wire++) { + wire->sym= sym->sym; + wire->mods= sym->mods; + wire->match= sym->match; + wire->virtualMod= sym->virtual_mod; + wire->flags= sym->flags; + memcpy((char*)&wire->act,(char*)&sym->act,sz_xkbActionWireDesc); + if (client->swapped) { + register int n; + swapl(&wire->sym,n); + } + } + if (rep->groups) { + grp = (xkbModsWireDesc *)wire; + for (i=0,bit=1;i<XkbNumKbdGroups;i++,bit<<=1) { + if (rep->groups&bit) { + grp->mask= compat->groups[i].mask; + grp->realMods= compat->groups[i].real_mods; + grp->virtualMods= compat->groups[i].vmods; + if (client->swapped) { + register int n; + swaps(&grp->virtualMods,n); + } + grp++; + } + } + wire= (xkbSymInterpretWireDesc*)grp; + } + } + else return BadAlloc; + } + else data= NULL; + + if (client->swapped) { + register int n; + swaps(&rep->sequenceNumber,n); + swapl(&rep->length,n); + swaps(&rep->firstSI,n); + swaps(&rep->nSI,n); + swaps(&rep->nTotalSI,n); + } + + WriteToClient(client, SIZEOF(xkbGetCompatMapReply), (char *)rep); + if (data) { + WriteToClient(client, size, data); + free((char *)data); + } + return Success; +} + +int +ProcXkbGetCompatMap(ClientPtr client) +{ + xkbGetCompatMapReply rep; + DeviceIntPtr dev; + XkbDescPtr xkb; + XkbCompatMapPtr compat; + + REQUEST(xkbGetCompatMapReq); + REQUEST_SIZE_MATCH(xkbGetCompatMapReq); + + if (!(client->xkbClientFlags&_XkbClientInitialized)) + return BadAccess; + + CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess); + + xkb = dev->key->xkbInfo->desc; + compat= xkb->compat; + + rep.type = X_Reply; + rep.deviceID = dev->id; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.firstSI = stuff->firstSI; + rep.nSI = stuff->nSI; + if (stuff->getAllSI) { + rep.firstSI = 0; + rep.nSI = compat->num_si; + } + else if ((((unsigned)stuff->nSI)>0)&& + ((unsigned)(stuff->firstSI+stuff->nSI-1)>=compat->num_si)) { + client->errorValue = _XkbErrCode2(0x05,compat->num_si); + return BadValue; + } + rep.nTotalSI = compat->num_si; + rep.groups= stuff->groups; + XkbComputeGetCompatMapReplySize(compat,&rep); + return XkbSendCompatMap(client,compat,&rep); +} + +/** + * Apply the given request on the given device. + * If dryRun is TRUE, then value checks are performed, but the device isn't + * modified. + */ +static int +_XkbSetCompatMap(ClientPtr client, DeviceIntPtr dev, + xkbSetCompatMapReq *req, char* data, BOOL dryRun) +{ + XkbSrvInfoPtr xkbi; + XkbDescPtr xkb; + XkbCompatMapPtr compat; + int nGroups; + unsigned i,bit; + + xkbi = dev->key->xkbInfo; + xkb = xkbi->desc; + compat = xkb->compat; + + if ((req->nSI>0)||(req->truncateSI)) { + xkbSymInterpretWireDesc *wire; + if (req->firstSI>compat->num_si) { + client->errorValue = _XkbErrCode2(0x02,compat->num_si); + return BadValue; + } + wire= (xkbSymInterpretWireDesc *)data; + wire+= req->nSI; + data = (char *)wire; + } + + nGroups= 0; + if (req->groups!=0) { + for (i=0,bit=1;i<XkbNumKbdGroups;i++,bit<<=1) { + if ( req->groups&bit ) + nGroups++; + } + } + data+= nGroups*SIZEOF(xkbModsWireDesc); + if (((data-((char *)req))/4)!=req->length) { + return BadLength; + } + + /* Done all the checks we can do */ + if (dryRun) + return Success; + + data = (char *)&req[1]; + if (req->nSI>0) { + xkbSymInterpretWireDesc *wire = (xkbSymInterpretWireDesc *)data; + XkbSymInterpretPtr sym; + if ((unsigned)(req->firstSI+req->nSI)>compat->num_si) { + compat->num_si= req->firstSI+req->nSI; + compat->sym_interpret= realloc(compat->sym_interpret, + compat->num_si * sizeof(XkbSymInterpretRec)); + if (!compat->sym_interpret) { + compat->num_si= 0; + return BadAlloc; + } + } + else if (req->truncateSI) { + compat->num_si = req->firstSI+req->nSI; + } + sym = &compat->sym_interpret[req->firstSI]; + for (i=0;i<req->nSI;i++,wire++,sym++) { + if (client->swapped) { + int n; + swapl(&wire->sym,n); + } + sym->sym= wire->sym; + sym->mods= wire->mods; + sym->match= wire->match; + sym->flags= wire->flags; + sym->virtual_mod= wire->virtualMod; + memcpy((char *)&sym->act,(char *)&wire->act, + SIZEOF(xkbActionWireDesc)); + } + data = (char *)wire; + } + else if (req->truncateSI) { + compat->num_si = req->firstSI; + } + + if (req->groups!=0) { + unsigned i, bit; + xkbModsWireDesc *wire = (xkbModsWireDesc *)data; + for (i = 0, bit = 1; i < XkbNumKbdGroups; i++, bit <<= 1) { + if (req->groups & bit) { + if (client->swapped) { + int n; + swaps(&wire->virtualMods,n); + } + compat->groups[i].mask= wire->realMods; + compat->groups[i].real_mods= wire->realMods; + compat->groups[i].vmods= wire->virtualMods; + if (wire->virtualMods!=0) { + unsigned tmp; + tmp= XkbMaskForVMask(xkb,wire->virtualMods); + compat->groups[i].mask|= tmp; + } + data+= SIZEOF(xkbModsWireDesc); + wire= (xkbModsWireDesc *)data; + } + } + } + i= XkbPaddedSize((data-((char *)req))); + if ((i/4)!=req->length) { + ErrorF("[xkb] Internal length error on read in _XkbSetCompatMap\n"); + return BadLength; + } + + if (dev->xkb_interest) { + xkbCompatMapNotify ev; + ev.deviceID = dev->id; + ev.changedGroups = req->groups; + ev.firstSI = req->firstSI; + ev.nSI = req->nSI; + ev.nTotalSI = compat->num_si; + XkbSendCompatMapNotify(dev,&ev); + } + + if (req->recomputeActions) { + XkbChangesRec change; + unsigned check; + XkbEventCauseRec cause; + + XkbSetCauseXkbReq(&cause,X_kbSetCompatMap,client); + memset(&change, 0, sizeof(XkbChangesRec)); + XkbUpdateActions(dev,xkb->min_key_code,XkbNumKeys(xkb),&change,&check, + &cause); + if (check) + XkbCheckSecondaryEffects(xkbi,check,&change,&cause); + XkbSendNotification(dev,&change,&cause); + } + return Success; +} + +int +ProcXkbSetCompatMap(ClientPtr client) +{ + DeviceIntPtr dev; + char *data; + int rc; + + REQUEST(xkbSetCompatMapReq); + REQUEST_AT_LEAST_SIZE(xkbSetCompatMapReq); + + if (!(client->xkbClientFlags&_XkbClientInitialized)) + return BadAccess; + + CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess); + + data = (char *)&stuff[1]; + + /* check first using a dry-run */ + rc = _XkbSetCompatMap(client, dev, stuff, data, TRUE); + if (rc != Success) + return rc; + if (stuff->deviceSpec == XkbUseCoreKbd) + { + DeviceIntPtr other; + for (other = inputInfo.devices; other; other = other->next) + { + if ((other != dev) && other->key && !IsMaster(other) && GetMaster(other, MASTER_KEYBOARD) == dev) + { + rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixManageAccess); + if (rc == Success) + { + /* dry-run */ + rc = _XkbSetCompatMap(client, other, stuff, data, TRUE); + if (rc != Success) + return rc; + } + } + } + } + + /* Yay, the dry-runs succeed. Let's apply */ + rc = _XkbSetCompatMap(client, dev, stuff, data, FALSE); + if (rc != Success) + return rc; + if (stuff->deviceSpec == XkbUseCoreKbd) + { + DeviceIntPtr other; + for (other = inputInfo.devices; other; other = other->next) + { + if ((other != dev) && other->key && !IsMaster(other) && GetMaster(other, MASTER_KEYBOARD) == dev) + { + rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixManageAccess); + if (rc == Success) + { + rc = _XkbSetCompatMap(client, other, stuff, data, FALSE); + if (rc != Success) + return rc; + } + } + } + } + + return Success; +} + +/***====================================================================***/ + +int +ProcXkbGetIndicatorState(ClientPtr client) +{ + xkbGetIndicatorStateReply rep; + XkbSrvLedInfoPtr sli; + DeviceIntPtr dev; + register int i; + + REQUEST(xkbGetIndicatorStateReq); + REQUEST_SIZE_MATCH(xkbGetIndicatorStateReq); + + if (!(client->xkbClientFlags&_XkbClientInitialized)) + return BadAccess; + + CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixReadAccess); + + sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId, + XkbXI_IndicatorStateMask); + if (!sli) + return BadAlloc; + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.deviceID = dev->id; + rep.state = sli->effectiveState; + + if (client->swapped) { + swaps(&rep.sequenceNumber,i); + swapl(&rep.state,i); + } + WriteToClient(client, SIZEOF(xkbGetIndicatorStateReply), (char *)&rep); + return Success; +} + +/***====================================================================***/ + +static Status +XkbComputeGetIndicatorMapReplySize( + XkbIndicatorPtr indicators, + xkbGetIndicatorMapReply *rep) +{ +register int i,bit; +int nIndicators; + + rep->realIndicators = indicators->phys_indicators; + for (i=nIndicators=0,bit=1;i<XkbNumIndicators;i++,bit<<=1) { + if (rep->which&bit) + nIndicators++; + } + rep->length = (nIndicators*SIZEOF(xkbIndicatorMapWireDesc))/4; + return Success; +} + +static int +XkbSendIndicatorMap( ClientPtr client, + XkbIndicatorPtr indicators, + xkbGetIndicatorMapReply * rep) +{ +int length; +CARD8 * map; +register int i; +register unsigned bit; + + length = rep->length*4; + if (length>0) { + CARD8 *to; + to= map= malloc(length); + if (map) { + xkbIndicatorMapWireDesc *wire = (xkbIndicatorMapWireDesc *)to; + for (i=0,bit=1;i<XkbNumIndicators;i++,bit<<=1) { + if (rep->which&bit) { + wire->flags= indicators->maps[i].flags; + wire->whichGroups= indicators->maps[i].which_groups; + wire->groups= indicators->maps[i].groups; + wire->whichMods= indicators->maps[i].which_mods; + wire->mods= indicators->maps[i].mods.mask; + wire->realMods= indicators->maps[i].mods.real_mods; + wire->virtualMods= indicators->maps[i].mods.vmods; + wire->ctrls= indicators->maps[i].ctrls; + if (client->swapped) { + register int n; + swaps(&wire->virtualMods,n); + swapl(&wire->ctrls,n); + } + wire++; + } + } + to = (CARD8 *)wire; + if ((to-map)!=length) { + client->errorValue = _XkbErrCode2(0xff,length); + free(map); + return BadLength; + } + } + else return BadAlloc; + } + else map = NULL; + if (client->swapped) { + swaps(&rep->sequenceNumber,i); + swapl(&rep->length,i); + swapl(&rep->which,i); + swapl(&rep->realIndicators,i); + } + WriteToClient(client, SIZEOF(xkbGetIndicatorMapReply), (char *)rep); + if (map) { + WriteToClient(client, length, (char *)map); + free((char *)map); + } + return Success; +} + +int +ProcXkbGetIndicatorMap(ClientPtr client) +{ +xkbGetIndicatorMapReply rep; +DeviceIntPtr dev; +XkbDescPtr xkb; +XkbIndicatorPtr leds; + + REQUEST(xkbGetIndicatorMapReq); + REQUEST_SIZE_MATCH(xkbGetIndicatorMapReq); + + if (!(client->xkbClientFlags&_XkbClientInitialized)) + return BadAccess; + + CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess); + + xkb= dev->key->xkbInfo->desc; + leds= xkb->indicators; + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.deviceID = dev->id; + rep.which = stuff->which; + XkbComputeGetIndicatorMapReplySize(leds,&rep); + return XkbSendIndicatorMap(client,leds,&rep); +} + +/** + * Apply the given map to the given device. Which specifies which components + * to apply. + */ +static int +_XkbSetIndicatorMap(ClientPtr client, DeviceIntPtr dev, + int which, xkbIndicatorMapWireDesc *desc) +{ + XkbSrvInfoPtr xkbi; + XkbSrvLedInfoPtr sli; + XkbEventCauseRec cause; + int i, bit; + + xkbi = dev->key->xkbInfo; + + sli= XkbFindSrvLedInfo(dev, XkbDfltXIClass, XkbDfltXIId, + XkbXI_IndicatorMapsMask); + if (!sli) + return BadAlloc; + + for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) { + if (which & bit) { + sli->maps[i].flags = desc->flags; + sli->maps[i].which_groups = desc->whichGroups; + sli->maps[i].groups = desc->groups; + sli->maps[i].which_mods = desc->whichMods; + sli->maps[i].mods.mask = desc->mods; + sli->maps[i].mods.real_mods = desc->mods; + sli->maps[i].mods.vmods= desc->virtualMods; + sli->maps[i].ctrls = desc->ctrls; + if (desc->virtualMods!=0) { + unsigned tmp; + tmp= XkbMaskForVMask(xkbi->desc,desc->virtualMods); + sli->maps[i].mods.mask= desc->mods|tmp; + } + desc++; + } + } + + XkbSetCauseXkbReq(&cause,X_kbSetIndicatorMap,client); + XkbApplyLedMapChanges(dev,sli,which,NULL,NULL,&cause); + + return Success; +} + +int +ProcXkbSetIndicatorMap(ClientPtr client) +{ + int i, bit; + int nIndicators; + DeviceIntPtr dev; + xkbIndicatorMapWireDesc *from; + int rc; + + REQUEST(xkbSetIndicatorMapReq); + REQUEST_AT_LEAST_SIZE(xkbSetIndicatorMapReq); + + if (!(client->xkbClientFlags&_XkbClientInitialized)) + return BadAccess; + + CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixSetAttrAccess); + + if (stuff->which==0) + return Success; + + for (nIndicators=i=0,bit=1;i<XkbNumIndicators;i++,bit<<=1) { + if (stuff->which&bit) + nIndicators++; + } + if (stuff->length!=((SIZEOF(xkbSetIndicatorMapReq)+ + (nIndicators*SIZEOF(xkbIndicatorMapWireDesc)))/4)) { + return BadLength; + } + + from = (xkbIndicatorMapWireDesc *)&stuff[1]; + for (i=0,bit=1;i<XkbNumIndicators;i++,bit<<=1) { + if (stuff->which&bit) { + if (client->swapped) { + int n; + swaps(&from->virtualMods,n); + swapl(&from->ctrls,n); + } + CHK_MASK_LEGAL(i,from->whichGroups,XkbIM_UseAnyGroup); + CHK_MASK_LEGAL(i,from->whichMods,XkbIM_UseAnyMods); + from++; + } + } + + from = (xkbIndicatorMapWireDesc *)&stuff[1]; + rc = _XkbSetIndicatorMap(client, dev, stuff->which, from); + if (rc != Success) + return rc; + + if (stuff->deviceSpec == XkbUseCoreKbd) + { + DeviceIntPtr other; + for (other = inputInfo.devices; other; other = other->next) + { + if ((other != dev) && other->key && !IsMaster(other) && GetMaster(other, MASTER_KEYBOARD) == dev) + { + rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixSetAttrAccess); + if (rc == Success) + _XkbSetIndicatorMap(client, other, stuff->which, from); + } + } + } + + return Success; +} + +/***====================================================================***/ + +int +ProcXkbGetNamedIndicator(ClientPtr client) +{ + DeviceIntPtr dev; + xkbGetNamedIndicatorReply rep; + register int i = 0; + XkbSrvLedInfoPtr sli; + XkbIndicatorMapPtr map = NULL; + + REQUEST(xkbGetNamedIndicatorReq); + REQUEST_SIZE_MATCH(xkbGetNamedIndicatorReq); + + if (!(client->xkbClientFlags&_XkbClientInitialized)) + return BadAccess; + + CHK_LED_DEVICE(dev, stuff->deviceSpec, client, DixReadAccess); + CHK_ATOM_ONLY(stuff->indicator); + + sli= XkbFindSrvLedInfo(dev,stuff->ledClass,stuff->ledID,0); + if (!sli) + return BadAlloc; + + i= 0; + map= NULL; + if ((sli->names)&&(sli->maps)) { + for (i=0;i<XkbNumIndicators;i++) { + if (stuff->indicator==sli->names[i]) { + map= &sli->maps[i]; + break; + } + } + } + + rep.type= X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.deviceID = dev->id; + rep.indicator= stuff->indicator; + if (map!=NULL) { + rep.found= TRUE; + rep.on= ((sli->effectiveState&(1<<i))!=0); + rep.realIndicator= ((sli->physIndicators&(1<<i))!=0); + rep.ndx= i; + rep.flags= map->flags; + rep.whichGroups= map->which_groups; + rep.groups= map->groups; + rep.whichMods= map->which_mods; + rep.mods= map->mods.mask; + rep.realMods= map->mods.real_mods; + rep.virtualMods= map->mods.vmods; + rep.ctrls= map->ctrls; + rep.supported= TRUE; + } + else { + rep.found= FALSE; + rep.on= FALSE; + rep.realIndicator= FALSE; + rep.ndx= XkbNoIndicator; + rep.flags= 0; + rep.whichGroups= 0; + rep.groups= 0; + rep.whichMods= 0; + rep.mods= 0; + rep.realMods= 0; + rep.virtualMods= 0; + rep.ctrls= 0; + rep.supported= TRUE; + } + if ( client->swapped ) { + register int n; + swapl(&rep.length,n); + swaps(&rep.sequenceNumber,n); + swapl(&rep.indicator,n); + swaps(&rep.virtualMods,n); + swapl(&rep.ctrls,n); + } + + WriteToClient(client,SIZEOF(xkbGetNamedIndicatorReply), (char *)&rep); + return Success; +} + + +/** + * Find the IM on the device. + * Returns the map, or NULL if the map doesn't exist. + * If the return value is NULL, led_return is undefined. Otherwise, led_return + * is set to the led index of the map. + */ +static XkbIndicatorMapPtr +_XkbFindNamedIndicatorMap(XkbSrvLedInfoPtr sli, Atom indicator, + int *led_return) +{ + XkbIndicatorMapPtr map; + + /* search for the right indicator */ + map = NULL; + if (sli->names && sli->maps) { + int led; + + for (led = 0; (led < XkbNumIndicators) && (map == NULL); led++) { + if (sli->names[led] == indicator) { + map= &sli->maps[led]; + *led_return = led; + break; + } + } + } + + return map; +} + +/** + * Creates an indicator map on the device. If dryRun is TRUE, it only checks + * if creation is possible, but doesn't actually create it. + */ +static int +_XkbCreateIndicatorMap(DeviceIntPtr dev, Atom indicator, + int ledClass, int ledID, + XkbIndicatorMapPtr *map_return, int *led_return, + Bool dryRun) +{ + XkbSrvLedInfoPtr sli; + XkbIndicatorMapPtr map; + int led; + + sli = XkbFindSrvLedInfo(dev, ledClass, ledID, XkbXI_IndicatorsMask); + if (!sli) + return BadAlloc; + + map = _XkbFindNamedIndicatorMap(sli, indicator, &led); + + if (!map) + { + /* find first unused indicator maps and assign the name to it */ + for (led = 0, map = NULL; (led < XkbNumIndicators) && (map == NULL); led++) { + if ((sli->names) && (sli->maps) && (sli->names[led] == None) && + (!XkbIM_InUse(&sli->maps[led]))) + { + map = &sli->maps[led]; + if (!dryRun) + sli->names[led] = indicator; + break; + } + } + } + + if (!map) + return BadAlloc; + + *led_return = led; + *map_return = map; + return Success; +} + +static int +_XkbSetNamedIndicator(ClientPtr client, DeviceIntPtr dev, + xkbSetNamedIndicatorReq *stuff) +{ + unsigned int extDevReason; + unsigned int statec, namec, mapc; + XkbSrvLedInfoPtr sli; + int led = 0; + XkbIndicatorMapPtr map; + DeviceIntPtr kbd; + XkbEventCauseRec cause; + xkbExtensionDeviceNotify ed; + XkbChangesRec changes; + int rc; + + rc = _XkbCreateIndicatorMap(dev, stuff->indicator, stuff->ledClass, + stuff->ledID, &map, &led, FALSE); + if (rc != Success || !map) /* oh-oh */ + return rc; + + sli = XkbFindSrvLedInfo(dev, stuff->ledClass, stuff->ledID, + XkbXI_IndicatorsMask); + if (!sli) + return BadAlloc; + + namec = mapc = statec = 0; + extDevReason = 0; + + namec |= (1<<led); + sli->namesPresent |= ((stuff->indicator != None) ? (1 << led) : 0); + extDevReason |= XkbXI_IndicatorNamesMask; + + if (stuff->setMap) { + map->flags = stuff->flags; + map->which_groups = stuff->whichGroups; + map->groups = stuff->groups; + map->which_mods = stuff->whichMods; + map->mods.mask = stuff->realMods; + map->mods.real_mods = stuff->realMods; + map->mods.vmods= stuff->virtualMods; + map->ctrls = stuff->ctrls; + mapc|= (1<<led); + } + + if ((stuff->setState) && ((map->flags & XkbIM_NoExplicit) == 0)) + { + if (stuff->on) sli->explicitState |= (1<<led); + else sli->explicitState &= ~(1<<led); + statec |= ((sli->effectiveState ^ sli->explicitState) & (1 << led)); + } + + memset((char *)&ed, 0, sizeof(xkbExtensionDeviceNotify)); + memset((char *)&changes, 0, sizeof(XkbChangesRec)); + XkbSetCauseXkbReq(&cause,X_kbSetNamedIndicator,client); + if (namec) + XkbApplyLedNameChanges(dev,sli,namec,&ed,&changes,&cause); + if (mapc) + XkbApplyLedMapChanges(dev,sli,mapc,&ed,&changes,&cause); + if (statec) + XkbApplyLedStateChanges(dev,sli,statec,&ed,&changes,&cause); + + kbd = dev; + if ((sli->flags&XkbSLI_HasOwnState)==0) + kbd = inputInfo.keyboard; + XkbFlushLedEvents(dev, kbd, sli, &ed, &changes, &cause); + + return Success; +} + +int +ProcXkbSetNamedIndicator(ClientPtr client) +{ + int rc; + DeviceIntPtr dev; + int led = 0; + XkbIndicatorMapPtr map; + + REQUEST(xkbSetNamedIndicatorReq); + REQUEST_SIZE_MATCH(xkbSetNamedIndicatorReq); + + if (!(client->xkbClientFlags&_XkbClientInitialized)) + return BadAccess; + + CHK_LED_DEVICE(dev, stuff->deviceSpec, client, DixSetAttrAccess); + CHK_ATOM_ONLY(stuff->indicator); + CHK_MASK_LEGAL(0x10,stuff->whichGroups,XkbIM_UseAnyGroup); + CHK_MASK_LEGAL(0x11,stuff->whichMods,XkbIM_UseAnyMods); + + /* Dry-run for checks */ + rc = _XkbCreateIndicatorMap(dev, stuff->indicator, + stuff->ledClass, stuff->ledID, + &map, &led, TRUE); + if (rc != Success || !map) /* couldn't be created or didn't exist */ + return rc; + + if (stuff->deviceSpec == XkbUseCoreKbd || + stuff->deviceSpec == XkbUseCorePtr) + { + DeviceIntPtr other; + for (other = inputInfo.devices; other; other = other->next) + { + if ((other != dev) && !IsMaster(other) && GetMaster(other, MASTER_KEYBOARD) == dev && + (other->kbdfeed || other->leds) && + (XaceHook(XACE_DEVICE_ACCESS, client, other, DixSetAttrAccess) == Success)) + { + rc = _XkbCreateIndicatorMap(other, stuff->indicator, + stuff->ledClass, stuff->ledID, + &map, &led, TRUE); + if (rc != Success || !map) + return rc; + } + } + } + + /* All checks passed, let's do it */ + rc = _XkbSetNamedIndicator(client, dev, stuff); + if (rc != Success) + return rc; + + if (stuff->deviceSpec == XkbUseCoreKbd || + stuff->deviceSpec == XkbUseCorePtr) + { + DeviceIntPtr other; + for (other = inputInfo.devices; other; other = other->next) + { + if ((other != dev) && !IsMaster(other) && GetMaster(other, MASTER_KEYBOARD) == dev && + (other->kbdfeed || other->leds) && + (XaceHook(XACE_DEVICE_ACCESS, client, other, DixSetAttrAccess) == Success)) + { + _XkbSetNamedIndicator(client, other, stuff); + } + } + } + + return Success; +} + +/***====================================================================***/ + +static CARD32 +_XkbCountAtoms(Atom *atoms,int maxAtoms,int *count) +{ +register unsigned int i,bit,nAtoms; +register CARD32 atomsPresent; + + for (i=nAtoms=atomsPresent=0,bit=1;i<maxAtoms;i++,bit<<=1) { + if (atoms[i]!=None) { + atomsPresent|= bit; + nAtoms++; + } + } + if (count) + *count= nAtoms; + return atomsPresent; +} + +static char * +_XkbWriteAtoms(char *wire,Atom *atoms,int maxAtoms,int swap) +{ +register unsigned int i; +Atom *atm; + + atm = (Atom *)wire; + for (i=0;i<maxAtoms;i++) { + if (atoms[i]!=None) { + *atm= atoms[i]; + if (swap) { + register int n; + swapl(atm,n); + } + atm++; + } + } + return (char *)atm; +} + +static Status +XkbComputeGetNamesReplySize(XkbDescPtr xkb,xkbGetNamesReply *rep) +{ +register unsigned which,length; +register int i; + + rep->minKeyCode= xkb->min_key_code; + rep->maxKeyCode= xkb->max_key_code; + which= rep->which; + length= 0; + if (xkb->names!=NULL) { + if (which&XkbKeycodesNameMask) length++; + if (which&XkbGeometryNameMask) length++; + if (which&XkbSymbolsNameMask) length++; + if (which&XkbPhysSymbolsNameMask) length++; + if (which&XkbTypesNameMask) length++; + if (which&XkbCompatNameMask) length++; + } + else which&= ~XkbComponentNamesMask; + + if (xkb->map!=NULL) { + if (which&XkbKeyTypeNamesMask) + length+= xkb->map->num_types; + rep->nTypes= xkb->map->num_types; + if (which&XkbKTLevelNamesMask) { + XkbKeyTypePtr pType = xkb->map->types; + int nKTLevels = 0; + + length+= XkbPaddedSize(xkb->map->num_types)/4; + for (i=0;i<xkb->map->num_types;i++,pType++) { + if (pType->level_names!=NULL) + nKTLevels+= pType->num_levels; + } + rep->nKTLevels= nKTLevels; + length+= nKTLevels; + } + } + else { + rep->nTypes= 0; + rep->nKTLevels= 0; + which&= ~(XkbKeyTypeNamesMask|XkbKTLevelNamesMask); + } + + rep->minKeyCode= xkb->min_key_code; + rep->maxKeyCode= xkb->max_key_code; + rep->indicators= 0; + rep->virtualMods= 0; + rep->groupNames= 0; + if (xkb->names!=NULL) { + if (which&XkbIndicatorNamesMask) { + int nLeds; + rep->indicators= + _XkbCountAtoms(xkb->names->indicators,XkbNumIndicators,&nLeds); + length+= nLeds; + if (nLeds==0) + which&= ~XkbIndicatorNamesMask; + } + + if (which&XkbVirtualModNamesMask) { + int nVMods; + rep->virtualMods= + _XkbCountAtoms(xkb->names->vmods,XkbNumVirtualMods,&nVMods); + length+= nVMods; + if (nVMods==0) + which&= ~XkbVirtualModNamesMask; + } + + if (which&XkbGroupNamesMask) { + int nGroups; + rep->groupNames= + _XkbCountAtoms(xkb->names->groups,XkbNumKbdGroups,&nGroups); + length+= nGroups; + if (nGroups==0) + which&= ~XkbGroupNamesMask; + } + + if ((which&XkbKeyNamesMask)&&(xkb->names->keys)) + length+= rep->nKeys; + else which&= ~XkbKeyNamesMask; + + if ((which&XkbKeyAliasesMask)&& + (xkb->names->key_aliases)&&(xkb->names->num_key_aliases>0)) { + rep->nKeyAliases= xkb->names->num_key_aliases; + length+= rep->nKeyAliases*2; + } + else { + which&= ~XkbKeyAliasesMask; + rep->nKeyAliases= 0; + } + + if ((which&XkbRGNamesMask)&&(xkb->names->num_rg>0)) + length+= xkb->names->num_rg; + else which&= ~XkbRGNamesMask; + } + else { + which&= ~(XkbIndicatorNamesMask|XkbVirtualModNamesMask); + which&= ~(XkbGroupNamesMask|XkbKeyNamesMask|XkbKeyAliasesMask); + which&= ~XkbRGNamesMask; + } + + rep->length= length; + rep->which= which; + return Success; +} + +static int +XkbSendNames(ClientPtr client,XkbDescPtr xkb,xkbGetNamesReply *rep) +{ +register unsigned i,length,which; +char * start; +char * desc; +register int n; + + length= rep->length*4; + which= rep->which; + if (client->swapped) { + swaps(&rep->sequenceNumber,n); + swapl(&rep->length,n); + swapl(&rep->which,n); + swaps(&rep->virtualMods,n); + swapl(&rep->indicators,n); + } + + start = desc = calloc(1, length); + if ( !start ) + return BadAlloc; + if (xkb->names) { + if (which&XkbKeycodesNameMask) { + *((CARD32 *)desc)= xkb->names->keycodes; + if (client->swapped) { + swapl(desc,n); + } + desc+= 4; + } + if (which&XkbGeometryNameMask) { + *((CARD32 *)desc)= xkb->names->geometry; + if (client->swapped) { + swapl(desc,n); + } + desc+= 4; + } + if (which&XkbSymbolsNameMask) { + *((CARD32 *)desc)= xkb->names->symbols; + if (client->swapped) { + swapl(desc,n); + } + desc+= 4; + } + if (which&XkbPhysSymbolsNameMask) { + register CARD32 *atm= (CARD32 *)desc; + atm[0]= (CARD32)xkb->names->phys_symbols; + if (client->swapped) { + swapl(&atm[0],n); + } + desc+= 4; + } + if (which&XkbTypesNameMask) { + *((CARD32 *)desc)= (CARD32)xkb->names->types; + if (client->swapped) { + swapl(desc,n); + } + desc+= 4; + } + if (which&XkbCompatNameMask) { + *((CARD32 *)desc)= (CARD32)xkb->names->compat; + if (client->swapped) { + swapl(desc,n); + } + desc+= 4; + } + if (which&XkbKeyTypeNamesMask) { + register CARD32 *atm= (CARD32 *)desc; + register XkbKeyTypePtr type= xkb->map->types; + + for (i=0;i<xkb->map->num_types;i++,atm++,type++) { + *atm= (CARD32)type->name; + if (client->swapped) { + swapl(atm,n); + } + } + desc= (char *)atm; + } + if (which&XkbKTLevelNamesMask && xkb->map) { + XkbKeyTypePtr type = xkb->map->types; + register CARD32 *atm; + for (i=0;i<rep->nTypes;i++,type++) { + *desc++ = type->num_levels; + } + desc+= XkbPaddedSize(rep->nTypes)-rep->nTypes; + + atm= (CARD32 *)desc; + type = xkb->map->types; + for (i=0;i<xkb->map->num_types;i++,type++) { + register unsigned l; + if (type->level_names) { + for (l=0;l<type->num_levels;l++,atm++) { + *atm= type->level_names[l]; + if (client->swapped) { + swapl(atm,n); + } + } + desc+= type->num_levels*4; + } + } + } + if (which&XkbIndicatorNamesMask) { + desc= _XkbWriteAtoms(desc,xkb->names->indicators,XkbNumIndicators, + client->swapped); + } + if (which&XkbVirtualModNamesMask) { + desc= _XkbWriteAtoms(desc,xkb->names->vmods,XkbNumVirtualMods, + client->swapped); + } + if (which&XkbGroupNamesMask) { + desc= _XkbWriteAtoms(desc,xkb->names->groups,XkbNumKbdGroups, + client->swapped); + } + if (which&XkbKeyNamesMask) { + for (i=0;i<rep->nKeys;i++,desc+= sizeof(XkbKeyNameRec)) { + *((XkbKeyNamePtr)desc)= xkb->names->keys[i+rep->firstKey]; + } + } + if (which&XkbKeyAliasesMask) { + XkbKeyAliasPtr pAl; + pAl= xkb->names->key_aliases; + for (i=0;i<rep->nKeyAliases;i++,pAl++,desc+=2*XkbKeyNameLength) { + *((XkbKeyAliasPtr)desc)= *pAl; + } + } + if ((which&XkbRGNamesMask)&&(rep->nRadioGroups>0)) { + register CARD32 *atm= (CARD32 *)desc; + for (i=0;i<rep->nRadioGroups;i++,atm++) { + *atm= (CARD32)xkb->names->radio_groups[i]; + if (client->swapped) { + swapl(atm,n); + } + } + desc+= rep->nRadioGroups*4; + } + } + + if ((desc-start)!=(length)) { + ErrorF("[xkb] BOGUS LENGTH in write names, expected %d, got %ld\n", + length, (unsigned long)(desc-start)); + } + WriteToClient(client, SIZEOF(xkbGetNamesReply), (char *)rep); + WriteToClient(client, length, start); + free((char *)start); + return Success; +} + +int +ProcXkbGetNames(ClientPtr client) +{ + DeviceIntPtr dev; + XkbDescPtr xkb; + xkbGetNamesReply rep; + + REQUEST(xkbGetNamesReq); + REQUEST_SIZE_MATCH(xkbGetNamesReq); + + if (!(client->xkbClientFlags&_XkbClientInitialized)) + return BadAccess; + + CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess); + CHK_MASK_LEGAL(0x01,stuff->which,XkbAllNamesMask); + + xkb = dev->key->xkbInfo->desc; + memset(&rep, 0, sizeof(xkbGetNamesReply)); + rep.type= X_Reply; + rep.sequenceNumber= client->sequence; + rep.length = 0; + rep.deviceID = dev->id; + rep.which = stuff->which; + rep.nTypes = xkb->map->num_types; + rep.firstKey = xkb->min_key_code; + rep.nKeys = XkbNumKeys(xkb); + if (xkb->names!=NULL) { + rep.nKeyAliases= xkb->names->num_key_aliases; + rep.nRadioGroups = xkb->names->num_rg; + } + else { + rep.nKeyAliases= rep.nRadioGroups= 0; + } + XkbComputeGetNamesReplySize(xkb,&rep); + return XkbSendNames(client,xkb,&rep); +} + +/***====================================================================***/ + +static CARD32 * +_XkbCheckAtoms(CARD32 *wire,int nAtoms,int swapped,Atom *pError) +{ +register int i; + + for (i=0;i<nAtoms;i++,wire++) { + if (swapped) { + register int n; + swapl(wire,n); + } + if ((((Atom)*wire)!=None)&&(!ValidAtom((Atom)*wire))) { + *pError= ((Atom)*wire); + return NULL; + } + } + return wire; +} + +static CARD32 * +_XkbCheckMaskedAtoms(CARD32 *wire,int nAtoms,CARD32 present,int swapped, + Atom *pError) +{ +register unsigned i,bit; + + for (i=0,bit=1;(i<nAtoms)&&(present);i++,bit<<=1) { + if ((present&bit)==0) + continue; + if (swapped) { + register int n; + swapl(wire,n); + } + if ((((Atom)*wire)!=None)&&(!ValidAtom(((Atom)*wire)))) { + *pError= (Atom)*wire; + return NULL; + } + wire++; + } + return wire; +} + +static Atom * +_XkbCopyMaskedAtoms( Atom *wire, + Atom *dest, + int nAtoms, + CARD32 present) +{ +register int i,bit; + + for (i=0,bit=1;(i<nAtoms)&&(present);i++,bit<<=1) { + if ((present&bit)==0) + continue; + dest[i]= *wire++; + } + return wire; +} + +static Bool +_XkbCheckTypeName(Atom name,int typeNdx) +{ +const char * str; + + str= NameForAtom(name); + if ((strcmp(str,"ONE_LEVEL")==0)||(strcmp(str,"TWO_LEVEL")==0)|| + (strcmp(str,"ALPHABETIC")==0)||(strcmp(str,"KEYPAD")==0)) + return FALSE; + return TRUE; +} + +/** + * Check the device-dependent data in the request against the device. Returns + * Success, or the appropriate error code. + */ +static int +_XkbSetNamesCheck(ClientPtr client, DeviceIntPtr dev, + xkbSetNamesReq *stuff, CARD32 *data) +{ + XkbDescRec *xkb; + XkbNamesRec *names; + CARD32 *tmp; + Atom bad; + + tmp = data; + xkb = dev->key->xkbInfo->desc; + names = xkb->names; + + + if (stuff->which & XkbKeyTypeNamesMask) { + int i; + CARD32 *old; + if ( stuff->nTypes<1 ) { + client->errorValue = _XkbErrCode2(0x02,stuff->nTypes); + return BadValue; + } + if ((unsigned)(stuff->firstType+stuff->nTypes-1)>=xkb->map->num_types) { + client->errorValue = _XkbErrCode4(0x03,stuff->firstType, + stuff->nTypes, + xkb->map->num_types); + return BadValue; + } + if (((unsigned)stuff->firstType)<=XkbLastRequiredType) { + client->errorValue = _XkbErrCode2(0x04,stuff->firstType); + return BadAccess; + } + old= tmp; + tmp= _XkbCheckAtoms(tmp,stuff->nTypes,client->swapped,&bad); + if (!tmp) { + client->errorValue= bad; + return BadAtom; + } + for (i=0;i<stuff->nTypes;i++,old++) { + if (!_XkbCheckTypeName((Atom)*old,stuff->firstType+i)) + client->errorValue= _XkbErrCode2(0x05,i); + } + } + if (stuff->which&XkbKTLevelNamesMask) { + unsigned i; + XkbKeyTypePtr type; + CARD8 * width; + if ( stuff->nKTLevels<1 ) { + client->errorValue = _XkbErrCode2(0x05,stuff->nKTLevels); + return BadValue; + } + if ((unsigned)(stuff->firstKTLevel+stuff->nKTLevels-1)>= + xkb->map->num_types) { + client->errorValue = _XkbErrCode4(0x06,stuff->firstKTLevel, + stuff->nKTLevels,xkb->map->num_types); + return BadValue; + } + width = (CARD8 *)tmp; + tmp= (CARD32 *)(((char *)tmp)+XkbPaddedSize(stuff->nKTLevels)); + type = &xkb->map->types[stuff->firstKTLevel]; + for (i=0;i<stuff->nKTLevels;i++,type++) { + if (width[i]==0) + continue; + else if (width[i]!=type->num_levels) { + client->errorValue= _XkbErrCode4(0x07,i+stuff->firstKTLevel, + type->num_levels,width[i]); + return BadMatch; + } + tmp= _XkbCheckAtoms(tmp,width[i],client->swapped,&bad); + if (!tmp) { + client->errorValue= bad; + return BadAtom; + } + } + } + if (stuff->which&XkbIndicatorNamesMask) { + if (stuff->indicators==0) { + client->errorValue= 0x08; + return BadMatch; + } + tmp= _XkbCheckMaskedAtoms(tmp,XkbNumIndicators,stuff->indicators, + client->swapped,&bad); + if (!tmp) { + client->errorValue= bad; + return BadAtom; + } + } + if (stuff->which&XkbVirtualModNamesMask) { + if (stuff->virtualMods==0) { + client->errorValue= 0x09; + return BadMatch; + } + tmp= _XkbCheckMaskedAtoms(tmp,XkbNumVirtualMods, + (CARD32)stuff->virtualMods, + client->swapped,&bad); + if (!tmp) { + client->errorValue = bad; + return BadAtom; + } + } + if (stuff->which&XkbGroupNamesMask) { + if (stuff->groupNames==0) { + client->errorValue= 0x0a; + return BadMatch; + } + tmp= _XkbCheckMaskedAtoms(tmp,XkbNumKbdGroups, + (CARD32)stuff->groupNames, + client->swapped,&bad); + if (!tmp) { + client->errorValue = bad; + return BadAtom; + } + } + if (stuff->which&XkbKeyNamesMask) { + if (stuff->firstKey<(unsigned)xkb->min_key_code) { + client->errorValue= _XkbErrCode3(0x0b,xkb->min_key_code, + stuff->firstKey); + return BadValue; + } + if (((unsigned)(stuff->firstKey+stuff->nKeys-1)>xkb->max_key_code)|| + (stuff->nKeys<1)) { + client->errorValue= _XkbErrCode4(0x0c,xkb->max_key_code, + stuff->firstKey,stuff->nKeys); + return BadValue; + } + tmp+= stuff->nKeys; + } + if ((stuff->which&XkbKeyAliasesMask)&&(stuff->nKeyAliases>0)) { + tmp+= stuff->nKeyAliases*2; + } + if (stuff->which&XkbRGNamesMask) { + if ( stuff->nRadioGroups<1 ) { + client->errorValue= _XkbErrCode2(0x0d,stuff->nRadioGroups); + return BadValue; + } + tmp= _XkbCheckAtoms(tmp,stuff->nRadioGroups,client->swapped,&bad); + if (!tmp) { + client->errorValue= bad; + return BadAtom; + } + } + if ((tmp-((CARD32 *)stuff))!=stuff->length) { + client->errorValue = stuff->length; + return BadLength; + } + + + + return Success; +} + +static int +_XkbSetNames(ClientPtr client, DeviceIntPtr dev, xkbSetNamesReq *stuff) +{ + XkbDescRec *xkb; + XkbNamesRec *names; + CARD32 *tmp; + xkbNamesNotify nn; + + tmp = (CARD32 *)&stuff[1]; + xkb = dev->key->xkbInfo->desc; + names = xkb->names; + + if (XkbAllocNames(xkb,stuff->which,stuff->nRadioGroups, + stuff->nKeyAliases)!=Success) { + return BadAlloc; + } + + memset(&nn, 0, sizeof(xkbNamesNotify)); + nn.changed= stuff->which; + tmp = (CARD32 *)&stuff[1]; + if (stuff->which&XkbKeycodesNameMask) + names->keycodes= *tmp++; + if (stuff->which&XkbGeometryNameMask) + names->geometry= *tmp++; + if (stuff->which&XkbSymbolsNameMask) + names->symbols= *tmp++; + if (stuff->which&XkbPhysSymbolsNameMask) + names->phys_symbols= *tmp++; + if (stuff->which&XkbTypesNameMask) + names->types= *tmp++; + if (stuff->which&XkbCompatNameMask) + names->compat= *tmp++; + if ((stuff->which&XkbKeyTypeNamesMask)&&(stuff->nTypes>0)) { + register unsigned i; + register XkbKeyTypePtr type; + + type= &xkb->map->types[stuff->firstType]; + for (i=0;i<stuff->nTypes;i++,type++) { + type->name= *tmp++; + } + nn.firstType= stuff->firstType; + nn.nTypes= stuff->nTypes; + } + if (stuff->which&XkbKTLevelNamesMask) { + register XkbKeyTypePtr type; + register unsigned i; + CARD8 *width; + + width = (CARD8 *)tmp; + tmp= (CARD32 *)(((char *)tmp)+XkbPaddedSize(stuff->nKTLevels)); + type= &xkb->map->types[stuff->firstKTLevel]; + for (i=0;i<stuff->nKTLevels;i++,type++) { + if (width[i]>0) { + if (type->level_names) { + register unsigned n; + for (n=0;n<width[i];n++) { + type->level_names[n]= tmp[n]; + } + } + tmp+= width[i]; + } + } + nn.firstLevelName= 0; + nn.nLevelNames= stuff->nTypes; + } + if (stuff->which&XkbIndicatorNamesMask) { + tmp= _XkbCopyMaskedAtoms(tmp,names->indicators,XkbNumIndicators, + stuff->indicators); + nn.changedIndicators= stuff->indicators; + } + if (stuff->which&XkbVirtualModNamesMask) { + tmp= _XkbCopyMaskedAtoms(tmp,names->vmods,XkbNumVirtualMods, + stuff->virtualMods); + nn.changedVirtualMods= stuff->virtualMods; + } + if (stuff->which&XkbGroupNamesMask) { + tmp= _XkbCopyMaskedAtoms(tmp,names->groups,XkbNumKbdGroups, + stuff->groupNames); + nn.changedVirtualMods= stuff->groupNames; + } + if (stuff->which&XkbKeyNamesMask) { + memcpy((char*)&names->keys[stuff->firstKey],(char *)tmp, + stuff->nKeys*XkbKeyNameLength); + tmp+= stuff->nKeys; + nn.firstKey= stuff->firstKey; + nn.nKeys= stuff->nKeys; + } + if (stuff->which&XkbKeyAliasesMask) { + if (stuff->nKeyAliases>0) { + register int na= stuff->nKeyAliases; + if (XkbAllocNames(xkb,XkbKeyAliasesMask,0,na)!=Success) + return BadAlloc; + memcpy((char *)names->key_aliases,(char *)tmp, + stuff->nKeyAliases*sizeof(XkbKeyAliasRec)); + tmp+= stuff->nKeyAliases*2; + } + else if (names->key_aliases!=NULL) { + free(names->key_aliases); + names->key_aliases= NULL; + names->num_key_aliases= 0; + } + nn.nAliases= names->num_key_aliases; + } + if (stuff->which&XkbRGNamesMask) { + if (stuff->nRadioGroups>0) { + register unsigned i,nrg; + nrg= stuff->nRadioGroups; + if (XkbAllocNames(xkb,XkbRGNamesMask,nrg,0)!=Success) + return BadAlloc; + + for (i=0;i<stuff->nRadioGroups;i++) { + names->radio_groups[i]= tmp[i]; + } + tmp+= stuff->nRadioGroups; + } + else if (names->radio_groups) { + free(names->radio_groups); + names->radio_groups= NULL; + names->num_rg= 0; + } + nn.nRadioGroups= names->num_rg; + } + if (nn.changed) { + Bool needExtEvent; + needExtEvent= (nn.changed&XkbIndicatorNamesMask)!=0; + XkbSendNamesNotify(dev,&nn); + if (needExtEvent) { + XkbSrvLedInfoPtr sli; + xkbExtensionDeviceNotify edev; + register int i; + register unsigned bit; + + sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId, + XkbXI_IndicatorsMask); + sli->namesPresent= 0; + for (i=0,bit=1;i<XkbNumIndicators;i++,bit<<=1) { + if (names->indicators[i]!=None) + sli->namesPresent|= bit; + } + memset(&edev, 0, sizeof(xkbExtensionDeviceNotify)); + edev.reason= XkbXI_IndicatorNamesMask; + edev.ledClass= KbdFeedbackClass; + edev.ledID= dev->kbdfeed->ctrl.id; + edev.ledsDefined= sli->namesPresent|sli->mapsPresent; + edev.ledState= sli->effectiveState; + edev.firstBtn= 0; + edev.nBtns= 0; + edev.supported= XkbXI_AllFeaturesMask; + edev.unsupported= 0; + XkbSendExtensionDeviceNotify(dev,client,&edev); + } + } + return Success; +} + +int +ProcXkbSetNames(ClientPtr client) +{ + DeviceIntPtr dev; + CARD32 *tmp; + Atom bad; + int rc; + + REQUEST(xkbSetNamesReq); + REQUEST_AT_LEAST_SIZE(xkbSetNamesReq); + + if (!(client->xkbClientFlags&_XkbClientInitialized)) + return BadAccess; + + CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess); + CHK_MASK_LEGAL(0x01,stuff->which,XkbAllNamesMask); + + /* check device-independent stuff */ + tmp = (CARD32 *)&stuff[1]; + + if (stuff->which&XkbKeycodesNameMask) { + tmp= _XkbCheckAtoms(tmp,1,client->swapped,&bad); + if (!tmp) { + client->errorValue = bad; + return BadAtom; + } + } + if (stuff->which&XkbGeometryNameMask) { + tmp= _XkbCheckAtoms(tmp,1,client->swapped,&bad); + if (!tmp) { + client->errorValue = bad; + return BadAtom; + } + } + if (stuff->which&XkbSymbolsNameMask) { + tmp= _XkbCheckAtoms(tmp,1,client->swapped,&bad); + if (!tmp) { + client->errorValue = bad; + return BadAtom; + } + } + if (stuff->which&XkbPhysSymbolsNameMask) { + tmp= _XkbCheckAtoms(tmp,1,client->swapped,&bad); + if (!tmp) { + client->errorValue= bad; + return BadAtom; + } + } + if (stuff->which&XkbTypesNameMask) { + tmp= _XkbCheckAtoms(tmp,1,client->swapped,&bad); + if (!tmp) { + client->errorValue = bad; + return BadAtom; + } + } + if (stuff->which&XkbCompatNameMask) { + tmp= _XkbCheckAtoms(tmp,1,client->swapped,&bad); + if (!tmp) { + client->errorValue = bad; + return BadAtom; + } + } + + /* start of device-dependent tests */ + rc = _XkbSetNamesCheck(client, dev, stuff, tmp); + if (rc != Success) + return rc; + + if (stuff->deviceSpec == XkbUseCoreKbd) + { + DeviceIntPtr other; + for (other = inputInfo.devices; other; other = other->next) + { + if ((other != dev) && other->key && !IsMaster(other) && GetMaster(other, MASTER_KEYBOARD) == dev) + { + + rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixManageAccess); + if (rc == Success) + { + rc = _XkbSetNamesCheck(client, other, stuff, tmp); + if (rc != Success) + return rc; + } + } + } + } + + /* everything is okay -- update names */ + + rc = _XkbSetNames(client, dev, stuff); + if (rc != Success) + return rc; + + if (stuff->deviceSpec == XkbUseCoreKbd) + { + DeviceIntPtr other; + for (other = inputInfo.devices; other; other = other->next) + { + if ((other != dev) && other->key && !IsMaster(other) && GetMaster(other, MASTER_KEYBOARD) == dev) + { + + rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixManageAccess); + if (rc == Success) + _XkbSetNames(client, other, stuff); + } + } + } + + /* everything is okay -- update names */ + + return Success; +} + +/***====================================================================***/ + +#include "xkbgeom.h" + +#define XkbSizeCountedString(s) ((s)?((((2+strlen(s))+3)/4)*4):4) + +static char * +XkbWriteCountedString(char *wire,char *str,Bool swap) +{ + CARD16 len,*pLen; + + if (!str) + return wire; + + len= strlen(str); + pLen= (CARD16 *)wire; + *pLen= len; + if (swap) { + register int n; + swaps(pLen,n); + } + memcpy(&wire[2],str,len); + wire+= ((2+len+3)/4)*4; + return wire; +} + +static int +XkbSizeGeomProperties(XkbGeometryPtr geom) +{ +register int i,size; +XkbPropertyPtr prop; + + for (size=i=0,prop=geom->properties;i<geom->num_properties;i++,prop++) { + size+= XkbSizeCountedString(prop->name); + size+= XkbSizeCountedString(prop->value); + } + return size; +} + +static char * +XkbWriteGeomProperties(char *wire,XkbGeometryPtr geom,Bool swap) +{ +register int i; +register XkbPropertyPtr prop; + + for (i=0,prop=geom->properties;i<geom->num_properties;i++,prop++) { + wire= XkbWriteCountedString(wire,prop->name,swap); + wire= XkbWriteCountedString(wire,prop->value,swap); + } + return wire; +} + +static int +XkbSizeGeomKeyAliases(XkbGeometryPtr geom) +{ + return geom->num_key_aliases*(2*XkbKeyNameLength); +} + +static char * +XkbWriteGeomKeyAliases(char *wire,XkbGeometryPtr geom,Bool swap) +{ +register int sz; + + sz= geom->num_key_aliases*(XkbKeyNameLength*2); + if (sz>0) { + memcpy(wire,(char *)geom->key_aliases,sz); + wire+= sz; + } + return wire; +} + +static int +XkbSizeGeomColors(XkbGeometryPtr geom) +{ +register int i,size; +register XkbColorPtr color; + + for (i=size=0,color=geom->colors;i<geom->num_colors;i++,color++) { + size+= XkbSizeCountedString(color->spec); + } + return size; +} + +static char * +XkbWriteGeomColors(char *wire,XkbGeometryPtr geom,Bool swap) +{ +register int i; +register XkbColorPtr color; + + for (i=0,color=geom->colors;i<geom->num_colors;i++,color++) { + wire= XkbWriteCountedString(wire,color->spec,swap); + } + return wire; +} + +static int +XkbSizeGeomShapes(XkbGeometryPtr geom) +{ +register int i,size; +register XkbShapePtr shape; + + for (i=size=0,shape=geom->shapes;i<geom->num_shapes;i++,shape++) { + register int n; + register XkbOutlinePtr ol; + size+= SIZEOF(xkbShapeWireDesc); + for (n=0,ol=shape->outlines;n<shape->num_outlines;n++,ol++) { + size+= SIZEOF(xkbOutlineWireDesc); + size+= ol->num_points*SIZEOF(xkbPointWireDesc); + } + } + return size; +} + +static char * +XkbWriteGeomShapes(char *wire,XkbGeometryPtr geom,Bool swap) +{ +int i; +XkbShapePtr shape; +xkbShapeWireDesc * shapeWire; + + for (i=0,shape=geom->shapes;i<geom->num_shapes;i++,shape++) { + register int o; + XkbOutlinePtr ol; + xkbOutlineWireDesc * olWire; + shapeWire= (xkbShapeWireDesc *)wire; + shapeWire->name= shape->name; + shapeWire->nOutlines= shape->num_outlines; + if (shape->primary!=NULL) + shapeWire->primaryNdx= XkbOutlineIndex(shape,shape->primary); + else shapeWire->primaryNdx= XkbNoShape; + if (shape->approx!=NULL) + shapeWire->approxNdx= XkbOutlineIndex(shape,shape->approx); + else shapeWire->approxNdx= XkbNoShape; + if (swap) { + register int n; + swapl(&shapeWire->name,n); + } + wire= (char *)&shapeWire[1]; + for (o=0,ol=shape->outlines;o<shape->num_outlines;o++,ol++) { + register int p; + XkbPointPtr pt; + xkbPointWireDesc * ptWire; + olWire= (xkbOutlineWireDesc *)wire; + olWire->nPoints= ol->num_points; + olWire->cornerRadius= ol->corner_radius; + wire= (char *)&olWire[1]; + ptWire= (xkbPointWireDesc *)wire; + for (p=0,pt=ol->points;p<ol->num_points;p++,pt++) { + ptWire[p].x= pt->x; + ptWire[p].y= pt->y; + if (swap) { + register int n; + swaps(&ptWire[p].x,n); + swaps(&ptWire[p].y,n); + } + } + wire= (char *)&ptWire[ol->num_points]; + } + } + return wire; +} + +static int +XkbSizeGeomDoodads(int num_doodads,XkbDoodadPtr doodad) +{ +register int i,size; + + for (i=size=0;i<num_doodads;i++,doodad++) { + size+= SIZEOF(xkbAnyDoodadWireDesc); + if (doodad->any.type==XkbTextDoodad) { + size+= XkbSizeCountedString(doodad->text.text); + size+= XkbSizeCountedString(doodad->text.font); + } + else if (doodad->any.type==XkbLogoDoodad) { + size+= XkbSizeCountedString(doodad->logo.logo_name); + } + } + return size; +} + +static char * +XkbWriteGeomDoodads(char *wire,int num_doodads,XkbDoodadPtr doodad,Bool swap) +{ +register int i; +xkbDoodadWireDesc * doodadWire; + + for (i=0;i<num_doodads;i++,doodad++) { + doodadWire= (xkbDoodadWireDesc *)wire; + wire= (char *)&doodadWire[1]; + memset(doodadWire, 0, SIZEOF(xkbDoodadWireDesc)); + doodadWire->any.name= doodad->any.name; + doodadWire->any.type= doodad->any.type; + doodadWire->any.priority= doodad->any.priority; + doodadWire->any.top= doodad->any.top; + doodadWire->any.left= doodad->any.left; + if (swap) { + register int n; + swapl(&doodadWire->any.name,n); + swaps(&doodadWire->any.top,n); + swaps(&doodadWire->any.left,n); + } + switch (doodad->any.type) { + case XkbOutlineDoodad: + case XkbSolidDoodad: + doodadWire->shape.angle= doodad->shape.angle; + doodadWire->shape.colorNdx= doodad->shape.color_ndx; + doodadWire->shape.shapeNdx= doodad->shape.shape_ndx; + if (swap) { + register int n; + swaps(&doodadWire->shape.angle,n); + } + break; + case XkbTextDoodad: + doodadWire->text.angle= doodad->text.angle; + doodadWire->text.width= doodad->text.width; + doodadWire->text.height= doodad->text.height; + doodadWire->text.colorNdx= doodad->text.color_ndx; + if (swap) { + register int n; + swaps(&doodadWire->text.angle,n); + swaps(&doodadWire->text.width,n); + swaps(&doodadWire->text.height,n); + } + wire= XkbWriteCountedString(wire,doodad->text.text,swap); + wire= XkbWriteCountedString(wire,doodad->text.font,swap); + break; + case XkbIndicatorDoodad: + doodadWire->indicator.shapeNdx= doodad->indicator.shape_ndx; + doodadWire->indicator.onColorNdx=doodad->indicator.on_color_ndx; + doodadWire->indicator.offColorNdx= + doodad->indicator.off_color_ndx; + break; + case XkbLogoDoodad: + doodadWire->logo.angle= doodad->logo.angle; + doodadWire->logo.colorNdx= doodad->logo.color_ndx; + doodadWire->logo.shapeNdx= doodad->logo.shape_ndx; + wire= XkbWriteCountedString(wire,doodad->logo.logo_name,swap); + break; + default: + ErrorF("[xkb] Unknown doodad type %d in XkbWriteGeomDoodads\n", + doodad->any.type); + ErrorF("[xkb] Ignored\n"); + break; + } + } + return wire; +} + +static char * +XkbWriteGeomOverlay(char *wire,XkbOverlayPtr ol,Bool swap) +{ +register int r; +XkbOverlayRowPtr row; +xkbOverlayWireDesc * olWire; + + olWire= (xkbOverlayWireDesc *)wire; + olWire->name= ol->name; + olWire->nRows= ol->num_rows; + if (swap) { + register int n; + swapl(&olWire->name,n); + } + wire= (char *)&olWire[1]; + for (r=0,row=ol->rows;r<ol->num_rows;r++,row++) { + unsigned int k; + XkbOverlayKeyPtr key; + xkbOverlayRowWireDesc * rowWire; + rowWire= (xkbOverlayRowWireDesc *)wire; + rowWire->rowUnder= row->row_under; + rowWire->nKeys= row->num_keys; + wire= (char *)&rowWire[1]; + for (k=0,key=row->keys;k<row->num_keys;k++,key++) { + xkbOverlayKeyWireDesc * keyWire; + keyWire= (xkbOverlayKeyWireDesc *)wire; + memcpy(keyWire->over,key->over.name,XkbKeyNameLength); + memcpy(keyWire->under,key->under.name,XkbKeyNameLength); + wire= (char *)&keyWire[1]; + } + } + return wire; +} + +static int +XkbSizeGeomSections(XkbGeometryPtr geom) +{ +register int i,size; +XkbSectionPtr section; + + for (i=size=0,section=geom->sections;i<geom->num_sections;i++,section++) { + size+= SIZEOF(xkbSectionWireDesc); + if (section->rows) { + int r; + XkbRowPtr row; + for (r=0,row=section->rows;r<section->num_rows;row++,r++) { + size+= SIZEOF(xkbRowWireDesc); + size+= row->num_keys*SIZEOF(xkbKeyWireDesc); + } + } + if (section->doodads) + size+= XkbSizeGeomDoodads(section->num_doodads,section->doodads); + if (section->overlays) { + int o; + XkbOverlayPtr ol; + for (o=0,ol=section->overlays;o<section->num_overlays;o++,ol++) { + int r; + XkbOverlayRowPtr row; + size+= SIZEOF(xkbOverlayWireDesc); + for (r=0,row=ol->rows;r<ol->num_rows;r++,row++) { + size+= SIZEOF(xkbOverlayRowWireDesc); + size+= row->num_keys*SIZEOF(xkbOverlayKeyWireDesc); + } + } + } + } + return size; +} + +static char * +XkbWriteGeomSections(char *wire,XkbGeometryPtr geom,Bool swap) +{ +register int i; +XkbSectionPtr section; +xkbSectionWireDesc * sectionWire; + + for (i=0,section=geom->sections;i<geom->num_sections;i++,section++) { + sectionWire= (xkbSectionWireDesc *)wire; + sectionWire->name= section->name; + sectionWire->top= section->top; + sectionWire->left= section->left; + sectionWire->width= section->width; + sectionWire->height= section->height; + sectionWire->angle= section->angle; + sectionWire->priority= section->priority; + sectionWire->nRows= section->num_rows; + sectionWire->nDoodads= section->num_doodads; + sectionWire->nOverlays= section->num_overlays; + sectionWire->pad= 0; + if (swap) { + register int n; + swapl(§ionWire->name,n); + swaps(§ionWire->top,n); + swaps(§ionWire->left,n); + swaps(§ionWire->width,n); + swaps(§ionWire->height,n); + swaps(§ionWire->angle,n); + } + wire= (char *)§ionWire[1]; + if (section->rows) { + int r; + XkbRowPtr row; + xkbRowWireDesc * rowWire; + for (r=0,row=section->rows;r<section->num_rows;r++,row++) { + rowWire= (xkbRowWireDesc *)wire; + rowWire->top= row->top; + rowWire->left= row->left; + rowWire->nKeys= row->num_keys; + rowWire->vertical= row->vertical; + rowWire->pad= 0; + if (swap) { + register int n; + swaps(&rowWire->top,n); + swaps(&rowWire->left,n); + } + wire= (char *)&rowWire[1]; + if (row->keys) { + int k; + XkbKeyPtr key; + xkbKeyWireDesc * keyWire; + keyWire= (xkbKeyWireDesc *)wire; + for (k=0,key=row->keys;k<row->num_keys;k++,key++) { + memcpy(keyWire[k].name,key->name.name,XkbKeyNameLength); + keyWire[k].gap= key->gap; + keyWire[k].shapeNdx= key->shape_ndx; + keyWire[k].colorNdx= key->color_ndx; + if (swap) { + register int n; + swaps(&keyWire[k].gap,n); + } + } + wire= (char *)&keyWire[row->num_keys]; + } + } + } + if (section->doodads) { + wire= XkbWriteGeomDoodads(wire, + section->num_doodads,section->doodads, + swap); + } + if (section->overlays) { + register int o; + for (o=0;o<section->num_overlays;o++) { + wire= XkbWriteGeomOverlay(wire,§ion->overlays[o],swap); + } + } + } + return wire; +} + +static Status +XkbComputeGetGeometryReplySize( XkbGeometryPtr geom, + xkbGetGeometryReply * rep, + Atom name) +{ +int len; + + if (geom!=NULL) { + len= XkbSizeCountedString(geom->label_font); + len+= XkbSizeGeomProperties(geom); + len+= XkbSizeGeomColors(geom); + len+= XkbSizeGeomShapes(geom); + len+= XkbSizeGeomSections(geom); + len+= XkbSizeGeomDoodads(geom->num_doodads,geom->doodads); + len+= XkbSizeGeomKeyAliases(geom); + rep->length= len/4; + rep->found= TRUE; + rep->name= geom->name; + rep->widthMM= geom->width_mm; + rep->heightMM= geom->height_mm; + rep->nProperties= geom->num_properties; + rep->nColors= geom->num_colors; + rep->nShapes= geom->num_shapes; + rep->nSections= geom->num_sections; + rep->nDoodads= geom->num_doodads; + rep->nKeyAliases= geom->num_key_aliases; + rep->baseColorNdx= XkbGeomColorIndex(geom,geom->base_color); + rep->labelColorNdx= XkbGeomColorIndex(geom,geom->label_color); + } + else { + rep->length= 0; + rep->found= FALSE; + rep->name= name; + rep->widthMM= rep->heightMM= 0; + rep->nProperties= rep->nColors= rep->nShapes= 0; + rep->nSections= rep->nDoodads= 0; + rep->nKeyAliases= 0; + rep->labelColorNdx= rep->baseColorNdx= 0; + } + return Success; +} + +static int +XkbSendGeometry( ClientPtr client, + XkbGeometryPtr geom, + xkbGetGeometryReply * rep, + Bool freeGeom) +{ + char *desc,*start; + int len; + + if (geom!=NULL) { + len= rep->length*4; + start= desc= malloc(len); + if (!start) + return BadAlloc; + desc= XkbWriteCountedString(desc,geom->label_font,client->swapped); + if ( rep->nProperties>0 ) + desc = XkbWriteGeomProperties(desc,geom,client->swapped); + if ( rep->nColors>0 ) + desc = XkbWriteGeomColors(desc,geom,client->swapped); + if ( rep->nShapes>0 ) + desc = XkbWriteGeomShapes(desc,geom,client->swapped); + if ( rep->nSections>0 ) + desc = XkbWriteGeomSections(desc,geom,client->swapped); + if ( rep->nDoodads>0 ) + desc = XkbWriteGeomDoodads(desc,geom->num_doodads,geom->doodads, + client->swapped); + if ( rep->nKeyAliases>0 ) + desc = XkbWriteGeomKeyAliases(desc,geom,client->swapped); + if ((desc-start)!=(len)) { + ErrorF("[xkb] BOGUS LENGTH in XkbSendGeometry, expected %d, got %ld\n", + len, (unsigned long)(desc-start)); + } + } + else { + len= 0; + start= NULL; + } + if (client->swapped) { + register int n; + swaps(&rep->sequenceNumber,n); + swapl(&rep->length,n); + swapl(&rep->name,n); + swaps(&rep->widthMM,n); + swaps(&rep->heightMM,n); + swaps(&rep->nProperties,n); + swaps(&rep->nColors,n); + swaps(&rep->nShapes,n); + swaps(&rep->nSections,n); + swaps(&rep->nDoodads,n); + swaps(&rep->nKeyAliases,n); + } + WriteToClient(client, SIZEOF(xkbGetGeometryReply), (char *)rep); + if (len>0) + WriteToClient(client, len, start); + if (start!=NULL) + free((char *)start); + if (freeGeom) + XkbFreeGeometry(geom,XkbGeomAllMask,TRUE); + return Success; +} + +int +ProcXkbGetGeometry(ClientPtr client) +{ + DeviceIntPtr dev; + xkbGetGeometryReply rep; + XkbGeometryPtr geom; + Bool shouldFree; + Status status; + + REQUEST(xkbGetGeometryReq); + REQUEST_SIZE_MATCH(xkbGetGeometryReq); + + if (!(client->xkbClientFlags&_XkbClientInitialized)) + return BadAccess; + + CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess); + CHK_ATOM_OR_NONE(stuff->name); + + geom= XkbLookupNamedGeometry(dev,stuff->name,&shouldFree); + rep.type= X_Reply; + rep.deviceID= dev->id; + rep.sequenceNumber= client->sequence; + rep.length= 0; + status= XkbComputeGetGeometryReplySize(geom,&rep,stuff->name); + if (status!=Success) + return status; + else return XkbSendGeometry(client,geom,&rep,shouldFree); +} + +/***====================================================================***/ + +static char * +_GetCountedString(char **wire_inout,Bool swap) +{ +char * wire,*str; +CARD16 len,*plen; + + wire= *wire_inout; + plen= (CARD16 *)wire; + if (swap) { + register int n; + swaps(plen,n); + } + len= *plen; + str= malloc(len+1); + if (str) { + memcpy(str,&wire[2],len); + str[len]= '\0'; + } + wire+= XkbPaddedSize(len+2); + *wire_inout= wire; + return str; +} + +static Status +_CheckSetDoodad( char ** wire_inout, + XkbGeometryPtr geom, + XkbSectionPtr section, + ClientPtr client) +{ +char * wire; +xkbDoodadWireDesc * dWire; +XkbDoodadPtr doodad; + + dWire= (xkbDoodadWireDesc *)(*wire_inout); + wire= (char *)&dWire[1]; + if (client->swapped) { + register int n; + swapl(&dWire->any.name,n); + swaps(&dWire->any.top,n); + swaps(&dWire->any.left,n); + swaps(&dWire->any.angle,n); + } + CHK_ATOM_ONLY(dWire->any.name); + doodad= XkbAddGeomDoodad(geom,section,dWire->any.name); + if (!doodad) + return BadAlloc; + doodad->any.type= dWire->any.type; + doodad->any.priority= dWire->any.priority; + doodad->any.top= dWire->any.top; + doodad->any.left= dWire->any.left; + doodad->any.angle= dWire->any.angle; + switch (doodad->any.type) { + case XkbOutlineDoodad: + case XkbSolidDoodad: + if (dWire->shape.colorNdx>=geom->num_colors) { + client->errorValue= _XkbErrCode3(0x40,geom->num_colors, + dWire->shape.colorNdx); + return BadMatch; + } + if (dWire->shape.shapeNdx>=geom->num_shapes) { + client->errorValue= _XkbErrCode3(0x41,geom->num_shapes, + dWire->shape.shapeNdx); + return BadMatch; + } + doodad->shape.color_ndx= dWire->shape.colorNdx; + doodad->shape.shape_ndx= dWire->shape.shapeNdx; + break; + case XkbTextDoodad: + if (dWire->text.colorNdx>=geom->num_colors) { + client->errorValue= _XkbErrCode3(0x42,geom->num_colors, + dWire->text.colorNdx); + return BadMatch; + } + if (client->swapped) { + register int n; + swaps(&dWire->text.width,n); + swaps(&dWire->text.height,n); + } + doodad->text.width= dWire->text.width; + doodad->text.height= dWire->text.height; + doodad->text.color_ndx= dWire->text.colorNdx; + doodad->text.text= _GetCountedString(&wire,client->swapped); + doodad->text.font= _GetCountedString(&wire,client->swapped); + break; + case XkbIndicatorDoodad: + if (dWire->indicator.onColorNdx>=geom->num_colors) { + client->errorValue= _XkbErrCode3(0x43,geom->num_colors, + dWire->indicator.onColorNdx); + return BadMatch; + } + if (dWire->indicator.offColorNdx>=geom->num_colors) { + client->errorValue= _XkbErrCode3(0x44,geom->num_colors, + dWire->indicator.offColorNdx); + return BadMatch; + } + if (dWire->indicator.shapeNdx>=geom->num_shapes) { + client->errorValue= _XkbErrCode3(0x45,geom->num_shapes, + dWire->indicator.shapeNdx); + return BadMatch; + } + doodad->indicator.shape_ndx= dWire->indicator.shapeNdx; + doodad->indicator.on_color_ndx= dWire->indicator.onColorNdx; + doodad->indicator.off_color_ndx= dWire->indicator.offColorNdx; + break; + case XkbLogoDoodad: + if (dWire->logo.colorNdx>=geom->num_colors) { + client->errorValue= _XkbErrCode3(0x46,geom->num_colors, + dWire->logo.colorNdx); + return BadMatch; + } + if (dWire->logo.shapeNdx>=geom->num_shapes) { + client->errorValue= _XkbErrCode3(0x47,geom->num_shapes, + dWire->logo.shapeNdx); + return BadMatch; + } + doodad->logo.color_ndx= dWire->logo.colorNdx; + doodad->logo.shape_ndx= dWire->logo.shapeNdx; + doodad->logo.logo_name= _GetCountedString(&wire,client->swapped); + break; + default: + client->errorValue= _XkbErrCode2(0x4F,dWire->any.type); + return BadValue; + } + *wire_inout= wire; + return Success; +} + +static Status +_CheckSetOverlay( char ** wire_inout, + XkbGeometryPtr geom, + XkbSectionPtr section, + ClientPtr client) +{ +register int r; +char * wire; +XkbOverlayPtr ol; +xkbOverlayWireDesc * olWire; +xkbOverlayRowWireDesc * rWire; + + wire= *wire_inout; + olWire= (xkbOverlayWireDesc *)wire; + if (client->swapped) { + register int n; + swapl(&olWire->name,n); + } + CHK_ATOM_ONLY(olWire->name); + ol= XkbAddGeomOverlay(section,olWire->name,olWire->nRows); + rWire= (xkbOverlayRowWireDesc *)&olWire[1]; + for (r=0;r<olWire->nRows;r++) { + register int k; + xkbOverlayKeyWireDesc * kWire; + XkbOverlayRowPtr row; + + if (rWire->rowUnder>section->num_rows) { + client->errorValue= _XkbErrCode4(0x20,r,section->num_rows, + rWire->rowUnder); + return BadMatch; + } + row= XkbAddGeomOverlayRow(ol,rWire->rowUnder,rWire->nKeys); + kWire= (xkbOverlayKeyWireDesc *)&rWire[1]; + for (k=0;k<rWire->nKeys;k++,kWire++) { + if (XkbAddGeomOverlayKey(ol,row, + (char *)kWire->over,(char *)kWire->under)==NULL) { + client->errorValue= _XkbErrCode3(0x21,r,k); + return BadMatch; + } + } + rWire= (xkbOverlayRowWireDesc *)kWire; + } + olWire= (xkbOverlayWireDesc *)rWire; + wire= (char *)olWire; + *wire_inout= wire; + return Success; +} + +static Status +_CheckSetSections( XkbGeometryPtr geom, + xkbSetGeometryReq * req, + char ** wire_inout, + ClientPtr client) +{ +Status status; +register int s; +char * wire; +xkbSectionWireDesc * sWire; +XkbSectionPtr section; + + wire= *wire_inout; + if (req->nSections<1) + return Success; + sWire= (xkbSectionWireDesc *)wire; + for (s=0;s<req->nSections;s++) { + register int r; + xkbRowWireDesc * rWire; + if (client->swapped) { + register int n; + swapl(&sWire->name,n); + swaps(&sWire->top,n); + swaps(&sWire->left,n); + swaps(&sWire->width,n); + swaps(&sWire->height,n); + swaps(&sWire->angle,n); + } + CHK_ATOM_ONLY(sWire->name); + section= XkbAddGeomSection(geom,sWire->name,sWire->nRows, + sWire->nDoodads,sWire->nOverlays); + if (!section) + return BadAlloc; + section->priority= sWire->priority; + section->top= sWire->top; + section->left= sWire->left; + section->width= sWire->width; + section->height= sWire->height; + section->angle= sWire->angle; + rWire= (xkbRowWireDesc *)&sWire[1]; + for (r=0;r<sWire->nRows;r++) { + register int k; + XkbRowPtr row; + xkbKeyWireDesc * kWire; + if (client->swapped) { + register int n; + swaps(&rWire->top,n); + swaps(&rWire->left,n); + } + row= XkbAddGeomRow(section,rWire->nKeys); + if (!row) + return BadAlloc; + row->top= rWire->top; + row->left= rWire->left; + row->vertical= rWire->vertical; + kWire= (xkbKeyWireDesc *)&rWire[1]; + for (k=0;k<rWire->nKeys;k++) { + XkbKeyPtr key; + key= XkbAddGeomKey(row); + if (!key) + return BadAlloc; + memcpy(key->name.name,kWire[k].name,XkbKeyNameLength); + key->gap= kWire[k].gap; + key->shape_ndx= kWire[k].shapeNdx; + key->color_ndx= kWire[k].colorNdx; + if (key->shape_ndx>=geom->num_shapes) { + client->errorValue= _XkbErrCode3(0x10,key->shape_ndx, + geom->num_shapes); + return BadMatch; + } + if (key->color_ndx>=geom->num_colors) { + client->errorValue= _XkbErrCode3(0x11,key->color_ndx, + geom->num_colors); + return BadMatch; + } + } + rWire= (xkbRowWireDesc *)&kWire[rWire->nKeys]; + } + wire= (char *)rWire; + if (sWire->nDoodads>0) { + register int d; + for (d=0;d<sWire->nDoodads;d++) { + status=_CheckSetDoodad(&wire,geom,section,client); + if (status!=Success) + return status; + } + } + if (sWire->nOverlays>0) { + register int o; + for (o=0;o<sWire->nOverlays;o++) { + status= _CheckSetOverlay(&wire,geom,section,client); + if (status!=Success) + return status; + } + } + sWire= (xkbSectionWireDesc *)wire; + } + wire= (char *)sWire; + *wire_inout= wire; + return Success; +} + +static Status +_CheckSetShapes( XkbGeometryPtr geom, + xkbSetGeometryReq * req, + char ** wire_inout, + ClientPtr client) +{ +register int i; +char * wire; + + wire= *wire_inout; + if (req->nShapes<1) { + client->errorValue= _XkbErrCode2(0x06,req->nShapes); + return BadValue; + } + else { + xkbShapeWireDesc * shapeWire; + XkbShapePtr shape; + register int o; + shapeWire= (xkbShapeWireDesc *)wire; + for (i=0;i<req->nShapes;i++) { + xkbOutlineWireDesc * olWire; + XkbOutlinePtr ol; + shape= XkbAddGeomShape(geom,shapeWire->name,shapeWire->nOutlines); + if (!shape) + return BadAlloc; + olWire= (xkbOutlineWireDesc *)(&shapeWire[1]); + for (o=0;o<shapeWire->nOutlines;o++) { + register int p; + XkbPointPtr pt; + xkbPointWireDesc * ptWire; + + ol= XkbAddGeomOutline(shape,olWire->nPoints); + if (!ol) + return BadAlloc; + ol->corner_radius= olWire->cornerRadius; + ptWire= (xkbPointWireDesc *)&olWire[1]; + for (p=0,pt=ol->points;p<olWire->nPoints;p++,pt++) { + pt->x= ptWire[p].x; + pt->y= ptWire[p].y; + if (client->swapped) { + register int n; + swaps(&pt->x,n); + swaps(&pt->y,n); + } + } + ol->num_points= olWire->nPoints; + olWire= (xkbOutlineWireDesc *)(&ptWire[olWire->nPoints]); + } + if (shapeWire->primaryNdx!=XkbNoShape) + shape->primary= &shape->outlines[shapeWire->primaryNdx]; + if (shapeWire->approxNdx!=XkbNoShape) + shape->approx= &shape->outlines[shapeWire->approxNdx]; + shapeWire= (xkbShapeWireDesc *)olWire; + } + wire= (char *)shapeWire; + } + if (geom->num_shapes!=req->nShapes) { + client->errorValue= _XkbErrCode3(0x07,geom->num_shapes,req->nShapes); + return BadMatch; + } + + *wire_inout= wire; + return Success; +} + +static Status +_CheckSetGeom( XkbGeometryPtr geom, + xkbSetGeometryReq * req, + ClientPtr client) +{ +register int i; +Status status; +char * wire; + + wire= (char *)&req[1]; + geom->label_font= _GetCountedString(&wire,client->swapped); + + for (i=0;i<req->nProperties;i++) { + char *name,*val; + name= _GetCountedString(&wire,client->swapped); + if (!name) + return BadAlloc; + val= _GetCountedString(&wire,client->swapped); + if (!val) { + free(name); + return BadAlloc; + } + if (XkbAddGeomProperty(geom,name,val)==NULL) { + free(name); + free(val); + return BadAlloc; + } + free(name); + free(val); + } + + if (req->nColors<2) { + client->errorValue= _XkbErrCode3(0x01,2,req->nColors); + return BadValue; + } + if (req->baseColorNdx>req->nColors) { + client->errorValue=_XkbErrCode3(0x03,req->nColors,req->baseColorNdx); + return BadMatch; + } + if (req->labelColorNdx>req->nColors) { + client->errorValue= _XkbErrCode3(0x03,req->nColors,req->labelColorNdx); + return BadMatch; + } + if (req->labelColorNdx==req->baseColorNdx) { + client->errorValue= _XkbErrCode3(0x04,req->baseColorNdx, + req->labelColorNdx); + return BadMatch; + } + + for (i=0;i<req->nColors;i++) { + char *name; + name= _GetCountedString(&wire,client->swapped); + if (!name) + return BadAlloc; + if (!XkbAddGeomColor(geom,name,geom->num_colors)) { + free(name); + return BadAlloc; + } + free(name); + } + if (req->nColors!=geom->num_colors) { + client->errorValue= _XkbErrCode3(0x05,req->nColors,geom->num_colors); + return BadMatch; + } + geom->label_color= &geom->colors[req->labelColorNdx]; + geom->base_color= &geom->colors[req->baseColorNdx]; + + if ((status=_CheckSetShapes(geom,req,&wire,client))!=Success) + return status; + + if ((status=_CheckSetSections(geom,req,&wire,client))!=Success) + return status; + + for (i=0;i<req->nDoodads;i++) { + status=_CheckSetDoodad(&wire,geom,NULL,client); + if (status!=Success) + return status; + } + + for (i=0;i<req->nKeyAliases;i++) { + if (XkbAddGeomKeyAlias(geom,&wire[XkbKeyNameLength],wire)==NULL) + return BadAlloc; + wire+= 2*XkbKeyNameLength; + } + return Success; +} + +static int +_XkbSetGeometry(ClientPtr client, DeviceIntPtr dev, xkbSetGeometryReq *stuff) +{ + XkbDescPtr xkb; + Bool new_name; + xkbNewKeyboardNotify nkn; + XkbGeometryPtr geom,old; + XkbGeometrySizesRec sizes; + Status status; + + xkb= dev->key->xkbInfo->desc; + old= xkb->geom; + xkb->geom= NULL; + + sizes.which= XkbGeomAllMask; + sizes.num_properties= stuff->nProperties; + sizes.num_colors= stuff->nColors; + sizes.num_shapes= stuff->nShapes; + sizes.num_sections= stuff->nSections; + sizes.num_doodads= stuff->nDoodads; + sizes.num_key_aliases= stuff->nKeyAliases; + if ((status= XkbAllocGeometry(xkb,&sizes))!=Success) { + xkb->geom= old; + return status; + } + geom= xkb->geom; + geom->name= stuff->name; + geom->width_mm= stuff->widthMM; + geom->height_mm= stuff->heightMM; + if ((status= _CheckSetGeom(geom,stuff,client))!=Success) { + XkbFreeGeometry(geom,XkbGeomAllMask,TRUE); + xkb->geom= old; + return status; + } + new_name= (xkb->names->geometry!=geom->name); + xkb->names->geometry= geom->name; + if (old) + XkbFreeGeometry(old,XkbGeomAllMask,TRUE); + if (new_name) { + xkbNamesNotify nn; + memset(&nn, 0, sizeof(xkbNamesNotify)); + nn.changed= XkbGeometryNameMask; + XkbSendNamesNotify(dev,&nn); + } + nkn.deviceID= nkn.oldDeviceID= dev->id; + nkn.minKeyCode= nkn.oldMinKeyCode= xkb->min_key_code; + nkn.maxKeyCode= nkn.oldMaxKeyCode= xkb->max_key_code; + nkn.requestMajor= XkbReqCode; + nkn.requestMinor= X_kbSetGeometry; + nkn.changed= XkbNKN_GeometryMask; + XkbSendNewKeyboardNotify(dev,&nkn); + return Success; +} + +int +ProcXkbSetGeometry(ClientPtr client) +{ + DeviceIntPtr dev; + int rc; + + REQUEST(xkbSetGeometryReq); + REQUEST_AT_LEAST_SIZE(xkbSetGeometryReq); + + if (!(client->xkbClientFlags&_XkbClientInitialized)) + return BadAccess; + + CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess); + CHK_ATOM_OR_NONE(stuff->name); + + rc = _XkbSetGeometry(client, dev, stuff); + if (rc != Success) + return rc; + + if (stuff->deviceSpec == XkbUseCoreKbd) + { + DeviceIntPtr other; + for (other = inputInfo.devices; other; other = other->next) + { + if ((other != dev) && other->key && !IsMaster(other) && GetMaster(other, MASTER_KEYBOARD) == dev) + { + rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixManageAccess); + if (rc == Success) + _XkbSetGeometry(client, other, stuff); + } + } + } + + return Success; +} + +/***====================================================================***/ + +int +ProcXkbPerClientFlags(ClientPtr client) +{ + DeviceIntPtr dev; + xkbPerClientFlagsReply rep; + XkbInterestPtr interest; + Mask access_mode = DixGetAttrAccess | DixSetAttrAccess; + + REQUEST(xkbPerClientFlagsReq); + REQUEST_SIZE_MATCH(xkbPerClientFlagsReq); + + if (!(client->xkbClientFlags&_XkbClientInitialized)) + return BadAccess; + + CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, access_mode); + CHK_MASK_LEGAL(0x01,stuff->change,XkbPCF_AllFlagsMask); + CHK_MASK_MATCH(0x02,stuff->change,stuff->value); + + interest = XkbFindClientResource((DevicePtr)dev,client); + memset(&rep, 0, sizeof(xkbPerClientFlagsReply)); + rep.type= X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + if (stuff->change) { + client->xkbClientFlags&= ~stuff->change; + client->xkbClientFlags|= stuff->value; + } + if (stuff->change&XkbPCF_AutoResetControlsMask) { + Bool want; + want= stuff->value&XkbPCF_AutoResetControlsMask; + if (interest && !want) { + interest->autoCtrls= interest->autoCtrlValues= 0; + } + else if (want && (!interest)) { + XID id = FakeClientID(client->index); + if (!AddResource(id,RT_XKBCLIENT,dev)) + return BadAlloc; + interest= XkbAddClientResource((DevicePtr)dev,client,id); + if (!interest) + return BadAlloc; + } + if (interest && want ) { + register unsigned affect; + affect= stuff->ctrlsToChange; + + CHK_MASK_LEGAL(0x03,affect,XkbAllBooleanCtrlsMask); + CHK_MASK_MATCH(0x04,affect,stuff->autoCtrls); + CHK_MASK_MATCH(0x05,stuff->autoCtrls,stuff->autoCtrlValues); + + interest->autoCtrls&= ~affect; + interest->autoCtrlValues&= ~affect; + interest->autoCtrls|= stuff->autoCtrls&affect; + interest->autoCtrlValues|= stuff->autoCtrlValues&affect; + } + } + rep.supported = XkbPCF_AllFlagsMask; + rep.value= client->xkbClientFlags&XkbPCF_AllFlagsMask; + if (interest) { + rep.autoCtrls= interest->autoCtrls; + rep.autoCtrlValues= interest->autoCtrlValues; + } + else { + rep.autoCtrls= rep.autoCtrlValues= 0; + } + if ( client->swapped ) { + register int n; + swaps(&rep.sequenceNumber, n); + swapl(&rep.supported,n); + swapl(&rep.value,n); + swapl(&rep.autoCtrls,n); + swapl(&rep.autoCtrlValues,n); + } + WriteToClient(client,SIZEOF(xkbPerClientFlagsReply), (char *)&rep); + return Success; +} + +/***====================================================================***/ + +/* all latin-1 alphanumerics, plus parens, minus, underscore, slash */ +/* and wildcards */ +static unsigned char componentSpecLegal[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0xa7, 0xff, 0x87, + 0xfe, 0xff, 0xff, 0x87, 0xfe, 0xff, 0xff, 0x07, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0x7f, 0xff +}; + +/* same as above but accepts percent, plus and bar too */ +static unsigned char componentExprLegal[] = { + 0x00, 0x00, 0x00, 0x00, 0x20, 0xaf, 0xff, 0x87, + 0xfe, 0xff, 0xff, 0x87, 0xfe, 0xff, 0xff, 0x17, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0x7f, 0xff +}; + +static char * +GetComponentSpec(unsigned char **pWire,Bool allowExpr,int *errRtrn) +{ +int len; +register int i; +unsigned char *wire,*str,*tmp,*legal; + + if (allowExpr) legal= &componentExprLegal[0]; + else legal= &componentSpecLegal[0]; + + wire= *pWire; + len= (*(unsigned char *)wire++); + if (len>0) { + str= calloc(1, len+1); + if (str) { + tmp= str; + for (i=0;i<len;i++) { + if (legal[(*wire)/8]&(1<<((*wire)%8))) + *tmp++= *wire++; + else wire++; + } + if (tmp!=str) + *tmp++= '\0'; + else { + free(str); + str= NULL; + } + } + else { + *errRtrn= BadAlloc; + } + } + else { + str= NULL; + } + *pWire= wire; + return (char *)str; +} + +/***====================================================================***/ + +int +ProcXkbListComponents(ClientPtr client) +{ + DeviceIntPtr dev; + xkbListComponentsReply rep; + unsigned len; + int status; + unsigned char * str; + XkbSrvListInfoRec list; + + REQUEST(xkbListComponentsReq); + REQUEST_AT_LEAST_SIZE(xkbListComponentsReq); + + if (!(client->xkbClientFlags&_XkbClientInitialized)) + return BadAccess; + + CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess); + + status= Success; + str= (unsigned char *)&stuff[1]; + memset(&list, 0, sizeof(XkbSrvListInfoRec)); + list.maxRtrn= stuff->maxNames; + list.pattern[_XkbListKeycodes]= GetComponentSpec(&str,FALSE,&status); + list.pattern[_XkbListTypes]= GetComponentSpec(&str,FALSE,&status); + list.pattern[_XkbListCompat]= GetComponentSpec(&str,FALSE,&status); + list.pattern[_XkbListSymbols]= GetComponentSpec(&str,FALSE,&status); + list.pattern[_XkbListGeometry]= GetComponentSpec(&str,FALSE,&status); + if (status!=Success) + return status; + len= str-((unsigned char *)stuff); + if ((XkbPaddedSize(len)/4)!=stuff->length) + return BadLength; + if ((status=XkbDDXList(dev,&list,client))!=Success) { + free(list.pool); + list.pool = NULL; + return status; + } + memset(&rep, 0, sizeof(xkbListComponentsReply)); + rep.type= X_Reply; + rep.deviceID = dev->id; + rep.sequenceNumber = client->sequence; + rep.length = XkbPaddedSize(list.nPool)/4; + rep.nKeymaps = 0; + rep.nKeycodes = list.nFound[_XkbListKeycodes]; + rep.nTypes = list.nFound[_XkbListTypes]; + rep.nCompatMaps = list.nFound[_XkbListCompat]; + rep.nSymbols = list.nFound[_XkbListSymbols]; + rep.nGeometries = list.nFound[_XkbListGeometry]; + rep.extra= 0; + if (list.nTotal>list.maxRtrn) + rep.extra = (list.nTotal-list.maxRtrn); + if (client->swapped) { + register int n; + swaps(&rep.sequenceNumber,n); + swapl(&rep.length,n); + swaps(&rep.nKeymaps,n); + swaps(&rep.nKeycodes,n); + swaps(&rep.nTypes,n); + swaps(&rep.nCompatMaps,n); + swaps(&rep.nSymbols,n); + swaps(&rep.nGeometries,n); + swaps(&rep.extra,n); + } + WriteToClient(client,SIZEOF(xkbListComponentsReply),(char *)&rep); + if (list.nPool && list.pool) { + WriteToClient(client,XkbPaddedSize(list.nPool), (char *)list.pool); + free(list.pool); + list.pool= NULL; + } + return Success; +} + +/***====================================================================***/ + +int +ProcXkbGetKbdByName(ClientPtr client) +{ + DeviceIntPtr dev; + DeviceIntPtr tmpd; + xkbGetKbdByNameReply rep = {0}; + xkbGetMapReply mrep = {0}; + xkbGetCompatMapReply crep = {0}; + xkbGetIndicatorMapReply irep = {0}; + xkbGetNamesReply nrep = {0}; + xkbGetGeometryReply grep = {0}; + XkbComponentNamesRec names = {0}; + XkbDescPtr xkb, new; + unsigned char * str; + char mapFile[PATH_MAX]; + unsigned len; + unsigned fwant,fneed,reported; + int status; + Bool geom_changed; + XkbSrvLedInfoPtr old_sli; + XkbSrvLedInfoPtr sli; + Mask access_mode = DixGetAttrAccess | DixManageAccess; + + REQUEST(xkbGetKbdByNameReq); + REQUEST_AT_LEAST_SIZE(xkbGetKbdByNameReq); + + if (!(client->xkbClientFlags&_XkbClientInitialized)) + return BadAccess; + + CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, access_mode); + + xkb = dev->key->xkbInfo->desc; + status= Success; + str= (unsigned char *)&stuff[1]; + if (GetComponentSpec(&str,TRUE,&status)) /* keymap, unsupported */ + return BadMatch; + names.keycodes= GetComponentSpec(&str,TRUE,&status); + names.types= GetComponentSpec(&str,TRUE,&status); + names.compat= GetComponentSpec(&str,TRUE,&status); + names.symbols= GetComponentSpec(&str,TRUE,&status); + names.geometry= GetComponentSpec(&str,TRUE,&status); + if (status!=Success) + return status; + len= str-((unsigned char *)stuff); + if ((XkbPaddedSize(len)/4)!=stuff->length) + return BadLength; + + CHK_MASK_LEGAL(0x01,stuff->want,XkbGBN_AllComponentsMask); + CHK_MASK_LEGAL(0x02,stuff->need,XkbGBN_AllComponentsMask); + + if (stuff->load) + fwant= XkbGBN_AllComponentsMask; + else fwant= stuff->want|stuff->need; + if ((!names.compat)&& + (fwant&(XkbGBN_CompatMapMask|XkbGBN_IndicatorMapMask))) { + names.compat= Xstrdup("%"); + } + if ((!names.types)&&(fwant&(XkbGBN_TypesMask))) { + names.types= Xstrdup("%"); + } + if ((!names.symbols)&&(fwant&XkbGBN_SymbolsMask)) { + names.symbols= Xstrdup("%"); + } + geom_changed= ((names.geometry!=NULL)&&(strcmp(names.geometry,"%")!=0)); + if ((!names.geometry)&&(fwant&XkbGBN_GeometryMask)) { + names.geometry= Xstrdup("%"); + geom_changed= FALSE; + } + + memset(mapFile, 0, PATH_MAX); + rep.type= X_Reply; + rep.deviceID = dev->id; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.minKeyCode = xkb->min_key_code; + rep.maxKeyCode = xkb->max_key_code; + rep.loaded= FALSE; + fwant= XkbConvertGetByNameComponents(TRUE,stuff->want)|XkmVirtualModsMask; + fneed= XkbConvertGetByNameComponents(TRUE,stuff->need); + rep.reported= XkbConvertGetByNameComponents(FALSE,fwant|fneed); + if (stuff->load) { + fneed|= XkmKeymapRequired; + fwant|= XkmKeymapLegal; + } + if ((fwant|fneed)&XkmSymbolsMask) { + fneed|= XkmKeyNamesIndex|XkmTypesIndex; + fwant|= XkmIndicatorsIndex; + } + + /* We pass dev in here so we can get the old names out if needed. */ + rep.found = XkbDDXLoadKeymapByNames(dev,&names,fwant,fneed,&new, + mapFile,PATH_MAX); + rep.newKeyboard= FALSE; + rep.pad1= rep.pad2= rep.pad3= rep.pad4= 0; + + stuff->want|= stuff->need; + if (new==NULL) + rep.reported= 0; + else { + if (stuff->load) + rep.loaded= TRUE; + if (stuff->load || + ((rep.reported&XkbGBN_SymbolsMask) && (new->compat))) { + XkbChangesRec changes; + memset(&changes, 0, sizeof(changes)); + XkbUpdateDescActions(new, + new->min_key_code,XkbNumKeys(new), + &changes); + } + + if (new->map==NULL) + rep.reported&= ~(XkbGBN_SymbolsMask|XkbGBN_TypesMask); + else if (rep.reported&(XkbGBN_SymbolsMask|XkbGBN_TypesMask)) { + mrep.type= X_Reply; + mrep.deviceID = dev->id; + mrep.sequenceNumber= client->sequence; + mrep.length = ((SIZEOF(xkbGetMapReply)-SIZEOF(xGenericReply))>>2); + mrep.minKeyCode = new->min_key_code; + mrep.maxKeyCode = new->max_key_code; + mrep.present = 0; + mrep.totalSyms = mrep.totalActs = + mrep.totalKeyBehaviors= mrep.totalKeyExplicit= + mrep.totalModMapKeys= mrep.totalVModMapKeys= 0; + if (rep.reported&(XkbGBN_TypesMask|XkbGBN_ClientSymbolsMask)) { + mrep.present|= XkbKeyTypesMask; + mrep.firstType = 0; + mrep.nTypes = mrep.totalTypes= new->map->num_types; + } + else { + mrep.firstType = mrep.nTypes= 0; + mrep.totalTypes= 0; + } + if (rep.reported&XkbGBN_ClientSymbolsMask) { + mrep.present|= (XkbKeySymsMask|XkbModifierMapMask); + mrep.firstKeySym = mrep.firstModMapKey= new->min_key_code; + mrep.nKeySyms = mrep.nModMapKeys= XkbNumKeys(new); + } + else { + mrep.firstKeySym= mrep.firstModMapKey= 0; + mrep.nKeySyms= mrep.nModMapKeys= 0; + } + if (rep.reported&XkbGBN_ServerSymbolsMask) { + mrep.present|= XkbAllServerInfoMask; + mrep.virtualMods= ~0; + mrep.firstKeyAct = mrep.firstKeyBehavior = + mrep.firstKeyExplicit = new->min_key_code; + mrep.nKeyActs = mrep.nKeyBehaviors = + mrep.nKeyExplicit = XkbNumKeys(new); + mrep.firstVModMapKey= new->min_key_code; + mrep.nVModMapKeys= XkbNumKeys(new); + } + else { + mrep.virtualMods= 0; + mrep.firstKeyAct= mrep.firstKeyBehavior= + mrep.firstKeyExplicit = 0; + mrep.nKeyActs= mrep.nKeyBehaviors= mrep.nKeyExplicit= 0; + } + XkbComputeGetMapReplySize(new,&mrep); + rep.length+= SIZEOF(xGenericReply)/4+mrep.length; + } + if (new->compat==NULL) + rep.reported&= ~XkbGBN_CompatMapMask; + else if (rep.reported&XkbGBN_CompatMapMask) { + crep.type= X_Reply; + crep.deviceID= dev->id; + crep.sequenceNumber= client->sequence; + crep.length= 0; + crep.groups= XkbAllGroupsMask; + crep.firstSI= 0; + crep.nSI= crep.nTotalSI= new->compat->num_si; + XkbComputeGetCompatMapReplySize(new->compat,&crep); + rep.length+= SIZEOF(xGenericReply)/4+crep.length; + } + if (new->indicators==NULL) + rep.reported&= ~XkbGBN_IndicatorMapMask; + else if (rep.reported&XkbGBN_IndicatorMapMask) { + irep.type= X_Reply; + irep.deviceID= dev->id; + irep.sequenceNumber= client->sequence; + irep.length= 0; + irep.which= XkbAllIndicatorsMask; + XkbComputeGetIndicatorMapReplySize(new->indicators,&irep); + rep.length+= SIZEOF(xGenericReply)/4+irep.length; + } + if (new->names==NULL) + rep.reported&= ~(XkbGBN_OtherNamesMask|XkbGBN_KeyNamesMask); + else if (rep.reported&(XkbGBN_OtherNamesMask|XkbGBN_KeyNamesMask)) { + nrep.type= X_Reply; + nrep.deviceID= dev->id; + nrep.sequenceNumber= client->sequence; + nrep.length= 0; + nrep.minKeyCode= new->min_key_code; + nrep.maxKeyCode= new->max_key_code; + if (rep.reported&XkbGBN_OtherNamesMask) { + nrep.which= XkbAllNamesMask; + if (new->map!=NULL) + nrep.nTypes= new->map->num_types; + else nrep.nTypes= 0; + nrep.nKTLevels= 0; + nrep.groupNames= XkbAllGroupsMask; + nrep.virtualMods= XkbAllVirtualModsMask; + nrep.indicators= XkbAllIndicatorsMask; + nrep.nRadioGroups= new->names->num_rg; + } + else { + nrep.which= 0; + nrep.nTypes= 0; + nrep.nKTLevels= 0; + nrep.groupNames= 0; + nrep.virtualMods= 0; + nrep.indicators= 0; + nrep.nRadioGroups= 0; + } + if (rep.reported&XkbGBN_KeyNamesMask) { + nrep.which|= XkbKeyNamesMask; + nrep.firstKey= new->min_key_code; + nrep.nKeys= XkbNumKeys(new); + nrep.nKeyAliases= new->names->num_key_aliases; + if (nrep.nKeyAliases) + nrep.which|= XkbKeyAliasesMask; + } + else { + nrep.which&= ~(XkbKeyNamesMask|XkbKeyAliasesMask); + nrep.firstKey= nrep.nKeys= 0; + nrep.nKeyAliases= 0; + } + XkbComputeGetNamesReplySize(new,&nrep); + rep.length+= SIZEOF(xGenericReply)/4+nrep.length; + } + if (new->geom==NULL) + rep.reported&= ~XkbGBN_GeometryMask; + else if (rep.reported&XkbGBN_GeometryMask) { + grep.type= X_Reply; + grep.deviceID= dev->id; + grep.sequenceNumber= client->sequence; + grep.length= 0; + grep.found= TRUE; + grep.pad= 0; + grep.widthMM= grep.heightMM= 0; + grep.nProperties= grep.nColors= grep.nShapes= 0; + grep.nSections= grep.nDoodads= 0; + grep.baseColorNdx= grep.labelColorNdx= 0; + XkbComputeGetGeometryReplySize(new->geom,&grep,None); + rep.length+= SIZEOF(xGenericReply)/4+grep.length; + } + } + + reported= rep.reported; + if ( client->swapped ) { + register int n; + swaps(&rep.sequenceNumber,n); + swapl(&rep.length,n); + swaps(&rep.found,n); + swaps(&rep.reported,n); + } + WriteToClient(client,SIZEOF(xkbGetKbdByNameReply), (char *)&rep); + if (reported&(XkbGBN_SymbolsMask|XkbGBN_TypesMask)) + XkbSendMap(client,new,&mrep); + if (reported&XkbGBN_CompatMapMask) + XkbSendCompatMap(client,new->compat,&crep); + if (reported&XkbGBN_IndicatorMapMask) + XkbSendIndicatorMap(client,new->indicators,&irep); + if (reported&(XkbGBN_KeyNamesMask|XkbGBN_OtherNamesMask)) + XkbSendNames(client,new,&nrep); + if (reported&XkbGBN_GeometryMask) + XkbSendGeometry(client,new->geom,&grep,FALSE); + if (rep.loaded) { + XkbDescPtr old_xkb; + xkbNewKeyboardNotify nkn; + int i,nG,nTG; + old_xkb= xkb; + xkb= new; + dev->key->xkbInfo->desc= xkb; + new= old_xkb; /* so it'll get freed automatically */ + + *xkb->ctrls= *old_xkb->ctrls; + for (nG=nTG=0,i=xkb->min_key_code;i<=xkb->max_key_code;i++) { + nG= XkbKeyNumGroups(xkb,i); + if (nG>=XkbNumKbdGroups) { + nTG= XkbNumKbdGroups; + break; + } + if (nG>nTG) { + nTG= nG; + } + } + xkb->ctrls->num_groups= nTG; + + for (tmpd = inputInfo.devices; tmpd; tmpd = tmpd->next) { + if ((tmpd == dev) || (!IsMaster(tmpd) && GetMaster(tmpd, MASTER_KEYBOARD) == dev)) { + if (tmpd != dev) + XkbCopyDeviceKeymap(tmpd, dev); + + if (tmpd->kbdfeed && tmpd->kbdfeed->xkb_sli) { + old_sli = tmpd->kbdfeed->xkb_sli; + tmpd->kbdfeed->xkb_sli = NULL; + sli = XkbAllocSrvLedInfo(tmpd, tmpd->kbdfeed, NULL, 0); + if (sli) { + sli->explicitState = old_sli->explicitState; + sli->effectiveState = old_sli->effectiveState; + } + tmpd->kbdfeed->xkb_sli = sli; + XkbFreeSrvLedInfo(old_sli); + } + } + } + + nkn.deviceID= nkn.oldDeviceID= dev->id; + nkn.minKeyCode= new->min_key_code; + nkn.maxKeyCode= new->max_key_code; + nkn.oldMinKeyCode= xkb->min_key_code; + nkn.oldMaxKeyCode= xkb->max_key_code; + nkn.requestMajor= XkbReqCode; + nkn.requestMinor= X_kbGetKbdByName; + nkn.changed= XkbNKN_KeycodesMask; + if (geom_changed) + nkn.changed|= XkbNKN_GeometryMask; + XkbSendNewKeyboardNotify(dev,&nkn); + + if (!IsMaster(dev)) { + DeviceIntPtr master = GetMaster(dev, MASTER_KEYBOARD); + if (master && master->lastSlave == dev) { + XkbCopyDeviceKeymap(master, dev); + XkbSendNewKeyboardNotify(dev,&nkn); + } + } + } + if ((new!=NULL)&&(new!=xkb)) { + XkbFreeKeyboard(new,XkbAllComponentsMask,TRUE); + new= NULL; + } + free(names.keycodes); + names.keycodes = NULL; + free(names.types); + names.types = NULL; + free(names.compat); + names.compat = NULL; + free(names.symbols); + names.symbols = NULL; + free(names.geometry); + names.geometry = NULL; + return Success; +} + +/***====================================================================***/ + +static int +ComputeDeviceLedInfoSize( DeviceIntPtr dev, + unsigned int what, + XkbSrvLedInfoPtr sli) +{ +int nNames,nMaps; +register unsigned n,bit; + + if (sli==NULL) + return 0; + nNames= nMaps= 0; + if ((what&XkbXI_IndicatorNamesMask)==0) + sli->namesPresent= 0; + if ((what&XkbXI_IndicatorMapsMask)==0) + sli->mapsPresent= 0; + + for (n=0,bit=1;n<XkbNumIndicators;n++,bit<<=1) { + if (sli->names && sli->names[n]!=None) { + sli->namesPresent|= bit; + nNames++; + } + if (sli->maps && XkbIM_InUse(&sli->maps[n])) { + sli->mapsPresent|= bit; + nMaps++; + } + } + return (nNames*4)+(nMaps*SIZEOF(xkbIndicatorMapWireDesc)); +} + +static int +CheckDeviceLedFBs( DeviceIntPtr dev, + int class, + int id, + xkbGetDeviceInfoReply * rep, + ClientPtr client) +{ +int nFBs= 0; +int length= 0; +Bool classOk; + + if (class==XkbDfltXIClass) { + if (dev->kbdfeed) class= KbdFeedbackClass; + else if (dev->leds) class= LedFeedbackClass; + else { + client->errorValue= _XkbErrCode2(XkbErr_BadClass,class); + return XkbKeyboardErrorCode; + } + } + classOk= FALSE; + if ((dev->kbdfeed)&&((class==KbdFeedbackClass)||(class==XkbAllXIClasses))) { + KbdFeedbackPtr kf; + classOk= TRUE; + for (kf= dev->kbdfeed;(kf);kf=kf->next) { + if ((id!=XkbAllXIIds)&&(id!=XkbDfltXIId)&&(id!=kf->ctrl.id)) + continue; + nFBs++; + length+= SIZEOF(xkbDeviceLedsWireDesc); + if (!kf->xkb_sli) + kf->xkb_sli= XkbAllocSrvLedInfo(dev,kf,NULL,0); + length+= ComputeDeviceLedInfoSize(dev,rep->present,kf->xkb_sli); + if (id!=XkbAllXIIds) + break; + } + } + if ((dev->leds)&&((class==LedFeedbackClass)||(class==XkbAllXIClasses))) { + LedFeedbackPtr lf; + classOk= TRUE; + for (lf= dev->leds;(lf);lf=lf->next) { + if ((id!=XkbAllXIIds)&&(id!=XkbDfltXIId)&&(id!=lf->ctrl.id)) + continue; + nFBs++; + length+= SIZEOF(xkbDeviceLedsWireDesc); + if (!lf->xkb_sli) + lf->xkb_sli= XkbAllocSrvLedInfo(dev,NULL,lf,0); + length+= ComputeDeviceLedInfoSize(dev,rep->present,lf->xkb_sli); + if (id!=XkbAllXIIds) + break; + } + } + if (nFBs>0) { + rep->nDeviceLedFBs= nFBs; + rep->length+= (length/4); + return Success; + } + if (classOk) client->errorValue= _XkbErrCode2(XkbErr_BadId,id); + else client->errorValue= _XkbErrCode2(XkbErr_BadClass,class); + return XkbKeyboardErrorCode; +} + +static int +SendDeviceLedInfo( XkbSrvLedInfoPtr sli, + ClientPtr client) +{ +xkbDeviceLedsWireDesc wire; +int length; + + length= 0; + wire.ledClass= sli->class; + wire.ledID= sli->id; + wire.namesPresent= sli->namesPresent; + wire.mapsPresent= sli->mapsPresent; + wire.physIndicators= sli->physIndicators; + wire.state= sli->effectiveState; + if (client->swapped) { + register int n; + swaps(&wire.ledClass,n); + swaps(&wire.ledID,n); + swapl(&wire.namesPresent,n); + swapl(&wire.mapsPresent,n); + swapl(&wire.physIndicators,n); + swapl(&wire.state,n); + } + WriteToClient(client,SIZEOF(xkbDeviceLedsWireDesc),(char *)&wire); + length+= SIZEOF(xkbDeviceLedsWireDesc); + if (sli->namesPresent|sli->mapsPresent) { + register unsigned i,bit; + if (sli->namesPresent) { + CARD32 awire; + for (i=0,bit=1;i<XkbNumIndicators;i++,bit<<=1) { + if (sli->namesPresent&bit) { + awire= (CARD32)sli->names[i]; + if (client->swapped) { + register int n; + swapl(&awire,n); + } + WriteToClient(client,4,(char *)&awire); + length+= 4; + } + } + } + if (sli->mapsPresent) { + for (i=0,bit=1;i<XkbNumIndicators;i++,bit<<=1) { + xkbIndicatorMapWireDesc iwire; + if (sli->mapsPresent&bit) { + iwire.flags= sli->maps[i].flags; + iwire.whichGroups= sli->maps[i].which_groups; + iwire.groups= sli->maps[i].groups; + iwire.whichMods= sli->maps[i].which_mods; + iwire.mods= sli->maps[i].mods.mask; + iwire.realMods= sli->maps[i].mods.real_mods; + iwire.virtualMods= sli->maps[i].mods.vmods; + iwire.ctrls= sli->maps[i].ctrls; + if (client->swapped) { + register int n; + swaps(&iwire.virtualMods,n); + swapl(&iwire.ctrls,n); + } + WriteToClient(client,SIZEOF(xkbIndicatorMapWireDesc), + (char *)&iwire); + length+= SIZEOF(xkbIndicatorMapWireDesc); + } + } + } + } + return length; +} + +static int +SendDeviceLedFBs( DeviceIntPtr dev, + int class, + int id, + unsigned wantLength, + ClientPtr client) +{ +int length= 0; + + if (class==XkbDfltXIClass) { + if (dev->kbdfeed) class= KbdFeedbackClass; + else if (dev->leds) class= LedFeedbackClass; + } + if ((dev->kbdfeed)&& + ((class==KbdFeedbackClass)||(class==XkbAllXIClasses))) { + KbdFeedbackPtr kf; + for (kf= dev->kbdfeed;(kf);kf=kf->next) { + if ((id==XkbAllXIIds)||(id==XkbDfltXIId)||(id==kf->ctrl.id)) { + length+= SendDeviceLedInfo(kf->xkb_sli,client); + if (id!=XkbAllXIIds) + break; + } + } + } + if ((dev->leds)&& + ((class==LedFeedbackClass)||(class==XkbAllXIClasses))) { + LedFeedbackPtr lf; + for (lf= dev->leds;(lf);lf=lf->next) { + if ((id==XkbAllXIIds)||(id==XkbDfltXIId)||(id==lf->ctrl.id)) { + length+= SendDeviceLedInfo(lf->xkb_sli,client); + if (id!=XkbAllXIIds) + break; + } + } + } + if (length==wantLength) + return Success; + else return BadLength; +} + +int +ProcXkbGetDeviceInfo(ClientPtr client) +{ +DeviceIntPtr dev; +xkbGetDeviceInfoReply rep; +int status,nDeviceLedFBs; +unsigned length,nameLen; +CARD16 ledClass,ledID; +unsigned wanted; +char * str; + + REQUEST(xkbGetDeviceInfoReq); + REQUEST_SIZE_MATCH(xkbGetDeviceInfoReq); + + if (!(client->xkbClientFlags&_XkbClientInitialized)) + return BadAccess; + + wanted= stuff->wanted; + + CHK_ANY_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess); + CHK_MASK_LEGAL(0x01,wanted,XkbXI_AllDeviceFeaturesMask); + + if ((!dev->button)||((stuff->nBtns<1)&&(!stuff->allBtns))) + wanted&= ~XkbXI_ButtonActionsMask; + if ((!dev->kbdfeed)&&(!dev->leds)) + wanted&= ~XkbXI_IndicatorsMask; + + nameLen= XkbSizeCountedString(dev->name); + memset((char *)&rep, 0, SIZEOF(xkbGetDeviceInfoReply)); + rep.type = X_Reply; + rep.deviceID= dev->id; + rep.sequenceNumber = client->sequence; + rep.length = nameLen/4; + rep.present = wanted; + rep.supported = XkbXI_AllDeviceFeaturesMask; + rep.unsupported = 0; + rep.firstBtnWanted = rep.nBtnsWanted = 0; + rep.firstBtnRtrn = rep.nBtnsRtrn = 0; + if (dev->button) + rep.totalBtns= dev->button->numButtons; + else rep.totalBtns= 0; + rep.devType= dev->xinput_type; + rep.hasOwnState= (dev->key && dev->key->xkbInfo); + rep.nDeviceLedFBs = 0; + if (dev->kbdfeed) rep.dfltKbdFB= dev->kbdfeed->ctrl.id; + else rep.dfltKbdFB= XkbXINone; + if (dev->leds) rep.dfltLedFB= dev->leds->ctrl.id; + else rep.dfltLedFB= XkbXINone; + + ledClass= stuff->ledClass; + ledID= stuff->ledID; + + rep.firstBtnWanted= rep.nBtnsWanted= 0; + rep.firstBtnRtrn= rep.nBtnsRtrn= 0; + if (wanted&XkbXI_ButtonActionsMask) { + if (stuff->allBtns) { + stuff->firstBtn= 0; + stuff->nBtns= dev->button->numButtons; + } + + if ((stuff->firstBtn+stuff->nBtns)>dev->button->numButtons) { + client->errorValue = _XkbErrCode4(0x02,dev->button->numButtons, + stuff->firstBtn, + stuff->nBtns); + return BadValue; + } + else { + rep.firstBtnWanted= stuff->firstBtn; + rep.nBtnsWanted= stuff->nBtns; + if (dev->button->xkb_acts!=NULL) { + XkbAction *act; + register int i; + + rep.firstBtnRtrn= stuff->firstBtn; + rep.nBtnsRtrn= stuff->nBtns; + act= &dev->button->xkb_acts[rep.firstBtnWanted]; + for (i=0;i<rep.nBtnsRtrn;i++,act++) { + if (act->type!=XkbSA_NoAction) + break; + } + rep.firstBtnRtrn+= i; + rep.nBtnsRtrn-= i; + act= &dev->button->xkb_acts[rep.firstBtnRtrn+rep.nBtnsRtrn-1]; + for (i=0;i<rep.nBtnsRtrn;i++,act--) { + if (act->type!=XkbSA_NoAction) + break; + } + rep.nBtnsRtrn-= i; + } + rep.length+= (rep.nBtnsRtrn*SIZEOF(xkbActionWireDesc))/4; + } + } + + if (wanted&XkbXI_IndicatorsMask) { + status= CheckDeviceLedFBs(dev,ledClass,ledID,&rep,client); + if (status!=Success) + return status; + } + length= rep.length*4; + nDeviceLedFBs = rep.nDeviceLedFBs; + if (client->swapped) { + register int n; + swaps(&rep.sequenceNumber,n); + swapl(&rep.length,n); + swaps(&rep.present,n); + swaps(&rep.supported,n); + swaps(&rep.unsupported,n); + swaps(&rep.nDeviceLedFBs,n); + swapl(&rep.type,n); + } + WriteToClient(client,SIZEOF(xkbGetDeviceInfoReply), (char *)&rep); + + str= malloc(nameLen); + if (!str) + return BadAlloc; + XkbWriteCountedString(str,dev->name,client->swapped); + WriteToClient(client,nameLen,str); + free(str); + length-= nameLen; + + if (rep.nBtnsRtrn>0) { + int sz; + xkbActionWireDesc * awire; + sz= rep.nBtnsRtrn*SIZEOF(xkbActionWireDesc); + awire= (xkbActionWireDesc *)&dev->button->xkb_acts[rep.firstBtnRtrn]; + WriteToClient(client,sz,(char *)awire); + length-= sz; + } + if (nDeviceLedFBs>0) { + status= SendDeviceLedFBs(dev,ledClass,ledID,length,client); + if (status!=Success) + return status; + } + else if (length!=0) { + ErrorF("[xkb] Internal Error! BadLength in ProcXkbGetDeviceInfo\n"); + ErrorF("[xkb] Wrote %d fewer bytes than expected\n",length); + return BadLength; + } + return Success; +} + +static char * +CheckSetDeviceIndicators( char * wire, + DeviceIntPtr dev, + int num, + int * status_rtrn, + ClientPtr client) +{ +xkbDeviceLedsWireDesc * ledWire; +int i; +XkbSrvLedInfoPtr sli; + + ledWire= (xkbDeviceLedsWireDesc *)wire; + for (i=0;i<num;i++) { + if (client->swapped) { + register int n; + swaps(&ledWire->ledClass,n); + swaps(&ledWire->ledID,n); + swapl(&ledWire->namesPresent,n); + swapl(&ledWire->mapsPresent,n); + swapl(&ledWire->physIndicators,n); + } + + sli= XkbFindSrvLedInfo(dev,ledWire->ledClass,ledWire->ledID, + XkbXI_IndicatorsMask); + if (sli!=NULL) { + register int n; + register unsigned bit; + int nMaps,nNames; + CARD32 *atomWire; + xkbIndicatorMapWireDesc *mapWire; + + nMaps= nNames= 0; + for (n=0,bit=1;n<XkbNumIndicators;n++,bit<<=1) { + if (ledWire->namesPresent&bit) + nNames++; + if (ledWire->mapsPresent&bit) + nMaps++; + } + atomWire= (CARD32 *)&ledWire[1]; + if (nNames>0) { + for (n=0;n<nNames;n++) { + if (client->swapped) { + register int t; + swapl(atomWire,t); + } + CHK_ATOM_OR_NONE3(((Atom)(*atomWire)),client->errorValue, + *status_rtrn,NULL); + atomWire++; + } + } + mapWire= (xkbIndicatorMapWireDesc *)atomWire; + if (nMaps>0) { + for (n=0;n<nMaps;n++) { + if (client->swapped) { + register int t; + swaps(&mapWire->virtualMods,t); + swapl(&mapWire->ctrls,t); + } + CHK_MASK_LEGAL3(0x21,mapWire->whichGroups, + XkbIM_UseAnyGroup, + client->errorValue, + *status_rtrn,NULL); + CHK_MASK_LEGAL3(0x22,mapWire->whichMods,XkbIM_UseAnyMods, + client->errorValue, + *status_rtrn,NULL); + mapWire++; + } + } + ledWire= (xkbDeviceLedsWireDesc *)mapWire; + } + else { + /* SHOULD NEVER HAPPEN */ + return (char *)ledWire; + } + } + return (char *)ledWire; +} + +static char * +SetDeviceIndicators( char * wire, + DeviceIntPtr dev, + unsigned changed, + int num, + int * status_rtrn, + ClientPtr client, + xkbExtensionDeviceNotify *ev) +{ +xkbDeviceLedsWireDesc * ledWire; +int i; +XkbEventCauseRec cause; +unsigned namec,mapc,statec; +xkbExtensionDeviceNotify ed; +XkbChangesRec changes; +DeviceIntPtr kbd; + + memset((char *)&ed, 0, sizeof(xkbExtensionDeviceNotify)); + memset((char *)&changes, 0, sizeof(XkbChangesRec)); + XkbSetCauseXkbReq(&cause,X_kbSetDeviceInfo,client); + ledWire= (xkbDeviceLedsWireDesc *)wire; + for (i=0;i<num;i++) { + register int n; + register unsigned bit; + CARD32 * atomWire; + xkbIndicatorMapWireDesc * mapWire; + XkbSrvLedInfoPtr sli; + + namec= mapc= statec= 0; + sli= XkbFindSrvLedInfo(dev,ledWire->ledClass,ledWire->ledID, + XkbXI_IndicatorMapsMask); + if (!sli) { + /* SHOULD NEVER HAPPEN!! */ + return (char *)ledWire; + } + + atomWire= (CARD32 *)&ledWire[1]; + if (changed&XkbXI_IndicatorNamesMask) { + namec= sli->namesPresent|ledWire->namesPresent; + memset((char *)sli->names, 0, XkbNumIndicators*sizeof(Atom)); + } + if (ledWire->namesPresent) { + sli->namesPresent= ledWire->namesPresent; + memset((char *)sli->names, 0, XkbNumIndicators*sizeof(Atom)); + for (n=0,bit=1;n<XkbNumIndicators;n++,bit<<=1) { + if (ledWire->namesPresent&bit) { + sli->names[n]= (Atom)*atomWire; + if (sli->names[n]==None) + ledWire->namesPresent&= ~bit; + atomWire++; + } + } + } + mapWire= (xkbIndicatorMapWireDesc *)atomWire; + if (changed&XkbXI_IndicatorMapsMask) { + mapc= sli->mapsPresent|ledWire->mapsPresent; + sli->mapsPresent= ledWire->mapsPresent; + memset((char*)sli->maps, 0, XkbNumIndicators*sizeof(XkbIndicatorMapRec)); + } + if (ledWire->mapsPresent) { + for (n=0,bit=1;n<XkbNumIndicators;n++,bit<<=1) { + if (ledWire->mapsPresent&bit) { + sli->maps[n].flags= mapWire->flags; + sli->maps[n].which_groups= mapWire->whichGroups; + sli->maps[n].groups= mapWire->groups; + sli->maps[n].which_mods= mapWire->whichMods; + sli->maps[n].mods.mask= mapWire->mods; + sli->maps[n].mods.real_mods=mapWire->realMods; + sli->maps[n].mods.vmods= mapWire->virtualMods; + sli->maps[n].ctrls= mapWire->ctrls; + mapWire++; + } + } + } + if (changed&XkbXI_IndicatorStateMask) { + statec= sli->effectiveState^ledWire->state; + sli->explicitState&= ~statec; + sli->explicitState|= (ledWire->state&statec); + } + if (namec) + XkbApplyLedNameChanges(dev,sli,namec,&ed,&changes,&cause); + if (mapc) + XkbApplyLedMapChanges(dev,sli,mapc,&ed,&changes,&cause); + if (statec) + XkbApplyLedStateChanges(dev,sli,statec,&ed,&changes,&cause); + + kbd= dev; + if ((sli->flags&XkbSLI_HasOwnState)==0) + kbd = inputInfo.keyboard; + + XkbFlushLedEvents(dev,kbd,sli,&ed,&changes,&cause); + ledWire= (xkbDeviceLedsWireDesc *)mapWire; + } + return (char *)ledWire; +} + + +static int +_XkbSetDeviceInfo(ClientPtr client, DeviceIntPtr dev, + xkbSetDeviceInfoReq *stuff) +{ + char *wire; + + wire= (char *)&stuff[1]; + if (stuff->change&XkbXI_ButtonActionsMask) { + if (!dev->button) { + client->errorValue = _XkbErrCode2(XkbErr_BadClass,ButtonClass); + return XkbKeyboardErrorCode; + } + if ((stuff->firstBtn+stuff->nBtns)>dev->button->numButtons) { + client->errorValue= _XkbErrCode4(0x02,stuff->firstBtn,stuff->nBtns, + dev->button->numButtons); + return BadMatch; + } + wire+= (stuff->nBtns*SIZEOF(xkbActionWireDesc)); + } + if (stuff->change&XkbXI_IndicatorsMask) { + int status= Success; + wire= CheckSetDeviceIndicators(wire,dev,stuff->nDeviceLedFBs, + &status,client); + if (status!=Success) + return status; + } + if (((wire-((char *)stuff))/4)!=stuff->length) + return BadLength; + + return Success; +} + +static int +_XkbSetDeviceInfoCheck(ClientPtr client, DeviceIntPtr dev, + xkbSetDeviceInfoReq *stuff) +{ + char *wire; + xkbExtensionDeviceNotify ed; + + memset((char *)&ed, 0, SIZEOF(xkbExtensionDeviceNotify)); + ed.deviceID= dev->id; + wire= (char *)&stuff[1]; + if (stuff->change&XkbXI_ButtonActionsMask) { + int nBtns,sz,i; + XkbAction * acts; + DeviceIntPtr kbd; + + nBtns= dev->button->numButtons; + acts= dev->button->xkb_acts; + if (acts==NULL) { + acts= calloc(nBtns, sizeof(XkbAction)); + if (!acts) + return BadAlloc; + dev->button->xkb_acts= acts; + } + sz= stuff->nBtns*SIZEOF(xkbActionWireDesc); + memcpy((char *)&acts[stuff->firstBtn],(char *)wire,sz); + wire+= sz; + ed.reason|= XkbXI_ButtonActionsMask; + ed.firstBtn= stuff->firstBtn; + ed.nBtns= stuff->nBtns; + + if (dev->key) kbd= dev; + else kbd= inputInfo.keyboard; + acts= &dev->button->xkb_acts[stuff->firstBtn]; + for (i=0;i<stuff->nBtns;i++,acts++) { + if (acts->type!=XkbSA_NoAction) + XkbSetActionKeyMods(kbd->key->xkbInfo->desc,acts,0); + } + } + if (stuff->change&XkbXI_IndicatorsMask) { + int status= Success; + wire= SetDeviceIndicators(wire,dev,stuff->change, + stuff->nDeviceLedFBs, &status,client,&ed); + if (status!=Success) + return status; + } + if ((stuff->change)&&(ed.reason)) + XkbSendExtensionDeviceNotify(dev,client,&ed); + return Success; +} + +int +ProcXkbSetDeviceInfo(ClientPtr client) +{ + DeviceIntPtr dev; + int rc; + + REQUEST(xkbSetDeviceInfoReq); + REQUEST_AT_LEAST_SIZE(xkbSetDeviceInfoReq); + + if (!(client->xkbClientFlags&_XkbClientInitialized)) + return BadAccess; + + CHK_ANY_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess); + CHK_MASK_LEGAL(0x01,stuff->change,XkbXI_AllFeaturesMask); + + rc = _XkbSetDeviceInfoCheck(client, dev, stuff); + + if (rc != Success) + return rc; + + if (stuff->deviceSpec == XkbUseCoreKbd || stuff->deviceSpec == XkbUseCorePtr) + { + DeviceIntPtr other; + for (other = inputInfo.devices; other; other = other->next) + { + if (((other != dev) && !IsMaster(other) && GetMaster(other, MASTER_KEYBOARD) == dev) && + ((stuff->deviceSpec == XkbUseCoreKbd && other->key) || + (stuff->deviceSpec == XkbUseCorePtr && other->button))) + { + rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixManageAccess); + if (rc == Success) + { + rc = _XkbSetDeviceInfoCheck(client, other, stuff); + if (rc != Success) + return rc; + } + } + } + } + + /* checks done, apply */ + rc = _XkbSetDeviceInfo(client, dev, stuff); + if (rc != Success) + return rc; + + if (stuff->deviceSpec == XkbUseCoreKbd || stuff->deviceSpec == XkbUseCorePtr) + { + DeviceIntPtr other; + for (other = inputInfo.devices; other; other = other->next) + { + if (((other != dev) && !IsMaster(other) && GetMaster(other, MASTER_KEYBOARD) == dev) && + ((stuff->deviceSpec == XkbUseCoreKbd && other->key) || + (stuff->deviceSpec == XkbUseCorePtr && other->button))) + { + rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixManageAccess); + if (rc == Success) + { + rc = _XkbSetDeviceInfo(client, other, stuff); + if (rc != Success) + return rc; + } + } + } + } + + return Success; +} + +/***====================================================================***/ + +int +ProcXkbSetDebuggingFlags(ClientPtr client) +{ +CARD32 newFlags,newCtrls,extraLength; +xkbSetDebuggingFlagsReply rep; +int rc; + + REQUEST(xkbSetDebuggingFlagsReq); + REQUEST_AT_LEAST_SIZE(xkbSetDebuggingFlagsReq); + + rc = XaceHook(XACE_SERVER_ACCESS, client, DixDebugAccess); + if (rc != Success) + return rc; + + newFlags= xkbDebugFlags&(~stuff->affectFlags); + newFlags|= (stuff->flags&stuff->affectFlags); + newCtrls= xkbDebugCtrls&(~stuff->affectCtrls); + newCtrls|= (stuff->ctrls&stuff->affectCtrls); + if (xkbDebugFlags || newFlags || stuff->msgLength) { + ErrorF("[xkb] XkbDebug: Setting debug flags to 0x%lx\n",(long)newFlags); + if (newCtrls!=xkbDebugCtrls) + ErrorF("[xkb] XkbDebug: Setting debug controls to 0x%lx\n",(long)newCtrls); + } + extraLength= (stuff->length<<2)-sz_xkbSetDebuggingFlagsReq; + if (stuff->msgLength>0) { + char *msg; + if (extraLength<XkbPaddedSize(stuff->msgLength)) { + ErrorF("[xkb] XkbDebug: msgLength= %d, length= %ld (should be %d)\n", + stuff->msgLength,(long)extraLength, + XkbPaddedSize(stuff->msgLength)); + return BadLength; + } + msg= (char *)&stuff[1]; + if (msg[stuff->msgLength-1]!='\0') { + ErrorF("[xkb] XkbDebug: message not null-terminated\n"); + return BadValue; + } + ErrorF("[xkb] XkbDebug: %s\n",msg); + } + xkbDebugFlags = newFlags; + xkbDebugCtrls = newCtrls; + + rep.type= X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.currentFlags = newFlags; + rep.currentCtrls = newCtrls; + rep.supportedFlags = ~0; + rep.supportedCtrls = ~0; + if ( client->swapped ) { + register int n; + swaps(&rep.sequenceNumber, n); + swapl(&rep.currentFlags, n); + swapl(&rep.currentCtrls, n); + swapl(&rep.supportedFlags, n); + swapl(&rep.supportedCtrls, n); + } + WriteToClient(client,SIZEOF(xkbSetDebuggingFlagsReply), (char *)&rep); + return Success; +} + +/***====================================================================***/ + +static int +ProcXkbDispatch (ClientPtr client) +{ + REQUEST(xReq); + switch (stuff->data) + { + case X_kbUseExtension: + return ProcXkbUseExtension(client); + case X_kbSelectEvents: + return ProcXkbSelectEvents(client); + case X_kbBell: + return ProcXkbBell(client); + case X_kbGetState: + return ProcXkbGetState(client); + case X_kbLatchLockState: + return ProcXkbLatchLockState(client); + case X_kbGetControls: + return ProcXkbGetControls(client); + case X_kbSetControls: + return ProcXkbSetControls(client); + case X_kbGetMap: + return ProcXkbGetMap(client); + case X_kbSetMap: + return ProcXkbSetMap(client); + case X_kbGetCompatMap: + return ProcXkbGetCompatMap(client); + case X_kbSetCompatMap: + return ProcXkbSetCompatMap(client); + case X_kbGetIndicatorState: + return ProcXkbGetIndicatorState(client); + case X_kbGetIndicatorMap: + return ProcXkbGetIndicatorMap(client); + case X_kbSetIndicatorMap: + return ProcXkbSetIndicatorMap(client); + case X_kbGetNamedIndicator: + return ProcXkbGetNamedIndicator(client); + case X_kbSetNamedIndicator: + return ProcXkbSetNamedIndicator(client); + case X_kbGetNames: + return ProcXkbGetNames(client); + case X_kbSetNames: + return ProcXkbSetNames(client); + case X_kbGetGeometry: + return ProcXkbGetGeometry(client); + case X_kbSetGeometry: + return ProcXkbSetGeometry(client); + case X_kbPerClientFlags: + return ProcXkbPerClientFlags(client); + case X_kbListComponents: + return ProcXkbListComponents(client); + case X_kbGetKbdByName: + return ProcXkbGetKbdByName(client); + case X_kbGetDeviceInfo: + return ProcXkbGetDeviceInfo(client); + case X_kbSetDeviceInfo: + return ProcXkbSetDeviceInfo(client); + case X_kbSetDebuggingFlags: + return ProcXkbSetDebuggingFlags(client); + default: + return BadRequest; + } +} + +static int +XkbClientGone(pointer data,XID id) +{ + DevicePtr pXDev = (DevicePtr)data; + + if (!XkbRemoveResourceClient(pXDev,id)) { + ErrorF("[xkb] Internal Error! bad RemoveResourceClient in XkbClientGone\n"); + } + return 1; +} + +void +XkbExtensionInit(void) +{ + ExtensionEntry *extEntry; + + RT_XKBCLIENT = CreateNewResourceType(XkbClientGone, "XkbClient"); + if (!RT_XKBCLIENT) + return; + + if (!XkbInitPrivates()) + return; + + if ((extEntry = AddExtension(XkbName, XkbNumberEvents, XkbNumberErrors, + ProcXkbDispatch, SProcXkbDispatch, + NULL, StandardMinorOpcode))) { + XkbReqCode = (unsigned char)extEntry->base; + XkbEventBase = (unsigned char)extEntry->eventBase; + XkbErrorBase = (unsigned char)extEntry->errorBase; + XkbKeyboardErrorCode = XkbErrorBase+XkbKeyboard; + } + return; +} + + diff --git a/xorg-server/xkb/xkbAccessX.c b/xorg-server/xkb/xkbAccessX.c index 70b1c6013..12fe2a1f5 100644 --- a/xorg-server/xkb/xkbAccessX.c +++ b/xorg-server/xkb/xkbAccessX.c @@ -1,773 +1,773 @@ -/************************************************************
-Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc.
-
-Permission 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 that both that copyright
-notice and this permission notice appear in supporting
-documentation, and that the name of Silicon Graphics not be
-used in advertising or publicity pertaining to distribution
-of the software without specific prior written permission.
-Silicon Graphics makes no representation about the suitability
-of this software for any purpose. It is provided "as is"
-without any express or implied warranty.
-
-SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
-SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
-AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
-GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
-DAMAGES OR ANY 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 THIS SOFTWARE.
-
-********************************************************/
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#include <stdio.h>
-#include <math.h>
-#include <X11/X.h>
-#include <X11/Xproto.h>
-#include <X11/keysym.h>
-#include "exglobals.h"
-#include <X11/extensions/XIproto.h>
-#include "inputstr.h"
-#include "eventstr.h"
-#include <xkbsrv.h>
-#if !defined(WIN32)
-#include <sys/time.h>
-#endif
-
-int XkbDfltRepeatDelay= 660;
-int XkbDfltRepeatInterval= 40;
-
-#define DFLT_TIMEOUT_CTRLS (XkbAX_KRGMask|XkbStickyKeysMask|XkbMouseKeysMask)
-#define DFLT_TIMEOUT_OPTS (XkbAX_IndicatorFBMask)
-
-unsigned short XkbDfltAccessXTimeout= 120;
-unsigned int XkbDfltAccessXTimeoutMask= DFLT_TIMEOUT_CTRLS;
-static unsigned int XkbDfltAccessXTimeoutValues= 0;
-static unsigned int XkbDfltAccessXTimeoutOptionsMask= DFLT_TIMEOUT_OPTS;
-static unsigned int XkbDfltAccessXTimeoutOptionsValues= 0;
-unsigned int XkbDfltAccessXFeedback= XkbAccessXFeedbackMask;
-unsigned short XkbDfltAccessXOptions= XkbAX_AllOptionsMask & ~(XkbAX_IndicatorFBMask|XkbAX_SKReleaseFBMask|XkbAX_SKRejectFBMask);
-
-void
-AccessXComputeCurveFactor(XkbSrvInfoPtr xkbi,XkbControlsPtr ctrls)
-{
- xkbi->mouseKeysCurve= 1.0+(((double)ctrls->mk_curve)*0.001);
- xkbi->mouseKeysCurveFactor= ( ((double)ctrls->mk_max_speed)/
- pow((double)ctrls->mk_time_to_max,xkbi->mouseKeysCurve));
- return;
-}
-
-void
-AccessXInit(DeviceIntPtr keybd)
-{
-XkbSrvInfoPtr xkbi = keybd->key->xkbInfo;
-XkbControlsPtr ctrls = xkbi->desc->ctrls;
-
- xkbi->shiftKeyCount= 0;
- xkbi->mouseKeysCounter= 0;
- xkbi->inactiveKey= 0;
- xkbi->slowKey= 0;
- xkbi->repeatKey= 0;
- xkbi->krgTimerActive= _OFF_TIMER;
- xkbi->beepType= _BEEP_NONE;
- xkbi->beepCount= 0;
- xkbi->mouseKeyTimer= NULL;
- xkbi->slowKeysTimer= NULL;
- xkbi->bounceKeysTimer= NULL;
- xkbi->repeatKeyTimer= NULL;
- xkbi->krgTimer= NULL;
- xkbi->beepTimer= NULL;
- ctrls->repeat_delay = XkbDfltRepeatDelay;
- ctrls->repeat_interval = XkbDfltRepeatInterval;
- ctrls->debounce_delay = 300;
- ctrls->slow_keys_delay = 300;
- ctrls->mk_delay = 160;
- ctrls->mk_interval = 40;
- ctrls->mk_time_to_max = 30;
- ctrls->mk_max_speed = 30;
- ctrls->mk_curve = 500;
- ctrls->mk_dflt_btn = 1;
- ctrls->ax_timeout = XkbDfltAccessXTimeout;
- ctrls->axt_ctrls_mask = XkbDfltAccessXTimeoutMask;
- ctrls->axt_ctrls_values = XkbDfltAccessXTimeoutValues;
- ctrls->axt_opts_mask = XkbDfltAccessXTimeoutOptionsMask;
- ctrls->axt_opts_values = XkbDfltAccessXTimeoutOptionsValues;
- if (XkbDfltAccessXTimeout)
- ctrls->enabled_ctrls |= XkbAccessXTimeoutMask;
- else
- ctrls->enabled_ctrls &= ~XkbAccessXTimeoutMask;
- ctrls->enabled_ctrls |= XkbDfltAccessXFeedback;
- ctrls->ax_options = XkbDfltAccessXOptions;
- AccessXComputeCurveFactor(xkbi,ctrls);
- return;
-}
-
-/************************************************************************/
-/* */
-/* AccessXKeyboardEvent */
-/* */
-/* Generate a synthetic keyboard event. */
-/* */
-/************************************************************************/
-static void
-AccessXKeyboardEvent(DeviceIntPtr keybd,
- int type,
- BYTE keyCode,
- Bool isRepeat)
-{
- DeviceEvent event;
- memset(&event, 0, sizeof(DeviceEvent));
- event.header = ET_Internal;
- event.type = type;
- event.detail.key = keyCode;
- event.time = GetTimeInMillis();
- event.length = sizeof(DeviceEvent);
- event.key_repeat = isRepeat;
- event.sourceid = keybd->id;
- event.deviceid = keybd->id;
-
- if (xkbDebugFlags&0x8) {
- DebugF("[xkb] AXKE: Key %d %s\n", keyCode,
- (event.type == ET_KeyPress ? "down" : "up"));
- }
-
- XkbProcessKeyboardEvent(&event, keybd);
- return;
-} /* AccessXKeyboardEvent */
-
-/************************************************************************/
-/* */
-/* AccessXKRGTurnOn */
-/* */
-/* Turn the keyboard response group on. */
-/* */
-/************************************************************************/
-static void
-AccessXKRGTurnOn(DeviceIntPtr dev,CARD16 KRGControl,xkbControlsNotify *pCN)
-{
-XkbSrvInfoPtr xkbi = dev->key->xkbInfo;
-XkbControlsPtr ctrls = xkbi->desc->ctrls;
-XkbControlsRec old;
-XkbEventCauseRec cause;
-XkbSrvLedInfoPtr sli;
-
- old= *ctrls;
- ctrls->enabled_ctrls |= (KRGControl&XkbAX_KRGMask);
- if (XkbComputeControlsNotify(dev,&old,ctrls,pCN,FALSE))
- XkbSendControlsNotify(dev,pCN);
- cause.kc= pCN->keycode;
- cause.event= pCN->eventType;
- cause.mjr= pCN->requestMajor;
- cause.mnr= pCN->requestMinor;
- sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId,0);
- XkbUpdateIndicators(dev,sli->usesControls,TRUE,NULL,&cause);
- if (XkbAX_NeedFeedback(ctrls,XkbAX_FeatureFBMask))
- XkbDDXAccessXBeep(dev,_BEEP_FEATURE_ON,KRGControl);
- return;
-
-} /* AccessXKRGTurnOn */
-
-/************************************************************************/
-/* */
-/* AccessXKRGTurnOff */
-/* */
-/* Turn the keyboard response group off. */
-/* */
-/************************************************************************/
-static void
-AccessXKRGTurnOff(DeviceIntPtr dev,xkbControlsNotify *pCN)
-{
-XkbSrvInfoPtr xkbi = dev->key->xkbInfo;
-XkbControlsPtr ctrls = xkbi->desc->ctrls;
-XkbControlsRec old;
-XkbEventCauseRec cause;
-XkbSrvLedInfoPtr sli;
-
- old = *ctrls;
- ctrls->enabled_ctrls &= ~XkbAX_KRGMask;
- if (XkbComputeControlsNotify(dev,&old,ctrls,pCN,FALSE))
- XkbSendControlsNotify(dev,pCN);
- cause.kc= pCN->keycode;
- cause.event= pCN->eventType;
- cause.mjr= pCN->requestMajor;
- cause.mnr= pCN->requestMinor;
- sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId,0);
- XkbUpdateIndicators(dev,sli->usesControls,TRUE,NULL,&cause);
- if (XkbAX_NeedFeedback(ctrls,XkbAX_FeatureFBMask)) {
- unsigned changes= old.enabled_ctrls^ctrls->enabled_ctrls;
- XkbDDXAccessXBeep(dev,_BEEP_FEATURE_OFF,changes);
- }
- return;
-
-} /* AccessXKRGTurnOff */
-
-/************************************************************************/
-/* */
-/* AccessXStickyKeysTurnOn */
-/* */
-/* Turn StickyKeys on. */
-/* */
-/************************************************************************/
-static void
-AccessXStickyKeysTurnOn(DeviceIntPtr dev,xkbControlsNotify *pCN)
-{
-XkbSrvInfoPtr xkbi = dev->key->xkbInfo;
-XkbControlsPtr ctrls = xkbi->desc->ctrls;
-XkbControlsRec old;
-XkbEventCauseRec cause;
-XkbSrvLedInfoPtr sli;
-
- old = *ctrls;
- ctrls->enabled_ctrls |= XkbStickyKeysMask;
- xkbi->shiftKeyCount = 0;
- if (XkbComputeControlsNotify(dev,&old,ctrls,pCN,FALSE))
- XkbSendControlsNotify(dev,pCN);
- cause.kc= pCN->keycode;
- cause.event= pCN->eventType;
- cause.mjr= pCN->requestMajor;
- cause.mnr= pCN->requestMinor;
- sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId,0);
- XkbUpdateIndicators(dev,sli->usesControls,TRUE,NULL,&cause);
- if (XkbAX_NeedFeedback(ctrls,XkbAX_FeatureFBMask)) {
- XkbDDXAccessXBeep(dev,_BEEP_FEATURE_ON,XkbStickyKeysMask);
- }
- return;
-
-} /* AccessXStickyKeysTurnOn */
-
-/************************************************************************/
-/* */
-/* AccessXStickyKeysTurnOff */
-/* */
-/* Turn StickyKeys off. */
-/* */
-/************************************************************************/
-static void
-AccessXStickyKeysTurnOff(DeviceIntPtr dev,xkbControlsNotify *pCN)
-{
-XkbSrvInfoPtr xkbi = dev->key->xkbInfo;
-XkbControlsPtr ctrls = xkbi->desc->ctrls;
-XkbControlsRec old;
-XkbEventCauseRec cause;
-XkbSrvLedInfoPtr sli;
-
- old = *ctrls;
- ctrls->enabled_ctrls &= ~XkbStickyKeysMask;
- xkbi->shiftKeyCount = 0;
- if (XkbComputeControlsNotify(dev,&old,ctrls,pCN,FALSE))
- XkbSendControlsNotify(dev,pCN);
-
- cause.kc= pCN->keycode;
- cause.event= pCN->eventType;
- cause.mjr= pCN->requestMajor;
- cause.mnr= pCN->requestMinor;
- sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId,0);
- XkbUpdateIndicators(dev,sli->usesControls,TRUE,NULL,&cause);
- if (XkbAX_NeedFeedback(ctrls,XkbAX_FeatureFBMask)) {
- XkbDDXAccessXBeep(dev,_BEEP_FEATURE_OFF,XkbStickyKeysMask);
- }
-#ifndef NO_CLEAR_LATCHES_FOR_STICKY_KEYS_OFF
- XkbClearAllLatchesAndLocks(dev,xkbi,FALSE,&cause);
-#endif
- return;
-} /* AccessXStickyKeysTurnOff */
-
-static CARD32
-AccessXKRGExpire(OsTimerPtr timer,CARD32 now,pointer arg)
-{
-XkbSrvInfoPtr xkbi= ((DeviceIntPtr)arg)->key->xkbInfo;
-xkbControlsNotify cn;
-
- if (xkbi->krgTimerActive==_KRG_WARN_TIMER) {
- XkbDDXAccessXBeep((DeviceIntPtr)arg,_BEEP_SLOW_WARN,XkbStickyKeysMask);
- xkbi->krgTimerActive= _KRG_TIMER;
- return 4000;
- }
- xkbi->krgTimerActive= _OFF_TIMER;
- cn.keycode = 0;
- cn.eventType = 0;
- cn.requestMajor = 0;
- cn.requestMinor = 0;
- if (xkbi->desc->ctrls->enabled_ctrls&XkbSlowKeysMask)
- AccessXKRGTurnOff((DeviceIntPtr)arg,&cn);
- else AccessXKRGTurnOn((DeviceIntPtr)arg,XkbSlowKeysMask,&cn);
- return 0;
-}
-
-static CARD32
-AccessXRepeatKeyExpire(OsTimerPtr timer,CARD32 now,pointer arg)
-{
-DeviceIntPtr dev = (DeviceIntPtr) arg;
-XkbSrvInfoPtr xkbi = dev->key->xkbInfo;
-
- if (xkbi->repeatKey == 0)
- return 0;
-
- AccessXKeyboardEvent(dev, ET_KeyPress, xkbi->repeatKey, TRUE);
-
- return xkbi->desc->ctrls->repeat_interval;
-}
-
-void
-AccessXCancelRepeatKey(XkbSrvInfoPtr xkbi,KeyCode key)
-{
- if (xkbi->repeatKey==key)
- xkbi->repeatKey= 0;
- return;
-}
-
-static CARD32
-AccessXSlowKeyExpire(OsTimerPtr timer,CARD32 now,pointer arg)
-{
-DeviceIntPtr keybd;
-XkbSrvInfoPtr xkbi;
-XkbDescPtr xkb;
-XkbControlsPtr ctrls;
-
- keybd= (DeviceIntPtr)arg;
- xkbi= keybd->key->xkbInfo;
- xkb= xkbi->desc;
- ctrls= xkb->ctrls;
- if (xkbi->slowKey!=0) {
- xkbAccessXNotify ev;
- KeySym *sym= XkbKeySymsPtr(xkb,xkbi->slowKey);
- ev.detail= XkbAXN_SKAccept;
- ev.keycode= xkbi->slowKey;
- ev.slowKeysDelay= ctrls->slow_keys_delay;
- ev.debounceDelay= ctrls->debounce_delay;
- XkbSendAccessXNotify(keybd,&ev);
- if (XkbAX_NeedFeedback(ctrls,XkbAX_SKAcceptFBMask))
- XkbDDXAccessXBeep(keybd,_BEEP_SLOW_ACCEPT,XkbSlowKeysMask);
- AccessXKeyboardEvent(keybd, ET_KeyPress,xkbi->slowKey,FALSE);
- /* check for magic sequences */
- if ((ctrls->enabled_ctrls&XkbAccessXKeysMask) &&
- ((sym[0]==XK_Shift_R)||(sym[0]==XK_Shift_L)))
- xkbi->shiftKeyCount++;
-
- /* Start repeating if necessary. Stop autorepeating if the user
- * presses a non-modifier key that doesn't autorepeat.
- */
- if (keybd->kbdfeed->ctrl.autoRepeat &&
- ((xkbi->slowKey != xkbi->mouseKey) || (!xkbi->mouseKeysAccel)) &&
- (ctrls->enabled_ctrls&XkbRepeatKeysMask)) {
- if (BitIsOn(keybd->kbdfeed->ctrl.autoRepeats,xkbi->slowKey)) {
- xkbi->repeatKey = xkbi->slowKey;
- xkbi->repeatKeyTimer= TimerSet(xkbi->repeatKeyTimer,
- 0, ctrls->repeat_delay,
- AccessXRepeatKeyExpire, (pointer)keybd);
- }
- }
- }
- return 0;
-}
-
-static CARD32
-AccessXBounceKeyExpire(OsTimerPtr timer,CARD32 now,pointer arg)
-{
-XkbSrvInfoPtr xkbi= ((DeviceIntPtr)arg)->key->xkbInfo;
-
- xkbi->inactiveKey= 0;
- return 0;
-}
-
-static CARD32
-AccessXTimeoutExpire(OsTimerPtr timer,CARD32 now,pointer arg)
-{
-DeviceIntPtr dev = (DeviceIntPtr)arg;
-XkbSrvInfoPtr xkbi= dev->key->xkbInfo;
-XkbControlsPtr ctrls= xkbi->desc->ctrls;
-XkbControlsRec old;
-xkbControlsNotify cn;
-XkbEventCauseRec cause;
-XkbSrvLedInfoPtr sli;
-
- if (xkbi->lastPtrEventTime) {
- unsigned timeToWait = (ctrls->ax_timeout*1000);
- unsigned timeElapsed = (now-xkbi->lastPtrEventTime);
-
- if (timeToWait > timeElapsed)
- return timeToWait - timeElapsed;
- }
- old= *ctrls;
- xkbi->shiftKeyCount= 0;
- ctrls->enabled_ctrls&= ~ctrls->axt_ctrls_mask;
- ctrls->enabled_ctrls|=
- (ctrls->axt_ctrls_values&ctrls->axt_ctrls_mask);
- if (ctrls->axt_opts_mask) {
- ctrls->ax_options&= ~ctrls->axt_opts_mask;
- ctrls->ax_options|= (ctrls->axt_opts_values&ctrls->axt_opts_mask);
- }
- if (XkbComputeControlsNotify(dev,&old,ctrls,&cn,FALSE)) {
- cn.keycode = 0;
- cn.eventType = 0;
- cn.requestMajor = 0;
- cn.requestMinor = 0;
- XkbSendControlsNotify(dev,&cn);
- }
- XkbSetCauseUnknown(&cause);
- sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId,0);
- XkbUpdateIndicators(dev,sli->usesControls,TRUE,NULL,&cause);
- if (ctrls->ax_options!=old.ax_options) {
- unsigned set,cleared,bell;
- set= ctrls->ax_options&(~old.ax_options);
- cleared= (~ctrls->ax_options)&old.ax_options;
- if (set && cleared) bell= _BEEP_FEATURE_CHANGE;
- else if (set) bell= _BEEP_FEATURE_ON;
- else bell= _BEEP_FEATURE_OFF;
- XkbDDXAccessXBeep(dev,bell,XkbAccessXTimeoutMask);
- }
- xkbi->krgTimerActive= _OFF_TIMER;
- return 0;
-}
-
-
-/************************************************************************/
-/* */
-/* AccessXFilterPressEvent */
-/* */
-/* Filter events before they get any further if SlowKeys is turned on. */
-/* In addition, this routine handles the ever so popular magic key */
-/* acts for turning various accessibility features on/off. */
-/* */
-/* Returns TRUE if this routine has discarded the event. */
-/* Returns FALSE if the event needs further processing. */
-/* */
-/************************************************************************/
-Bool
-AccessXFilterPressEvent( DeviceEvent* event,
- DeviceIntPtr keybd)
-{
-XkbSrvInfoPtr xkbi = keybd->key->xkbInfo;
-XkbControlsPtr ctrls = xkbi->desc->ctrls;
-Bool ignoreKeyEvent = FALSE;
-KeyCode key = event->detail.key;
-KeySym * sym = XkbKeySymsPtr(xkbi->desc,key);
-
- if (ctrls->enabled_ctrls&XkbAccessXKeysMask) {
- /* check for magic sequences */
- if ((sym[0]==XK_Shift_R)||(sym[0]==XK_Shift_L)) {
- if (XkbAX_NeedFeedback(ctrls,XkbAX_SlowWarnFBMask)) {
- xkbi->krgTimerActive = _KRG_WARN_TIMER;
- xkbi->krgTimer= TimerSet(xkbi->krgTimer, 0, 4000,
- AccessXKRGExpire, (pointer)keybd);
- }
- else {
- xkbi->krgTimerActive = _KRG_TIMER;
- xkbi->krgTimer= TimerSet(xkbi->krgTimer, 0, 8000,
- AccessXKRGExpire, (pointer)keybd);
- }
- if (!(ctrls->enabled_ctrls & XkbSlowKeysMask)) {
- CARD32 now= GetTimeInMillis();
- if ((now-xkbi->lastShiftEventTime)>15000)
- xkbi->shiftKeyCount= 1;
- else xkbi->shiftKeyCount++;
- xkbi->lastShiftEventTime= now;
- }
- }
- else {
- if (xkbi->krgTimerActive) {
- xkbi->krgTimer= TimerSet(xkbi->krgTimer,0, 0, NULL, NULL);
- xkbi->krgTimerActive= _OFF_TIMER;
- }
- }
- }
-
- /* Don't transmit the KeyPress if SlowKeys is turned on;
- * The wakeup handler will synthesize one for us if the user
- * has held the key long enough.
- */
- if (ctrls->enabled_ctrls & XkbSlowKeysMask) {
- xkbAccessXNotify ev;
- /* If key was already pressed, ignore subsequent press events
- * from the server's autorepeat
- */
- if(xkbi->slowKey == key)
- return TRUE;
- ev.detail= XkbAXN_SKPress;
- ev.keycode= key;
- ev.slowKeysDelay= ctrls->slow_keys_delay;
- ev.debounceDelay= ctrls->debounce_delay;
- XkbSendAccessXNotify(keybd,&ev);
- if (XkbAX_NeedFeedback(ctrls,XkbAX_SKPressFBMask))
- XkbDDXAccessXBeep(keybd,_BEEP_SLOW_PRESS,XkbSlowKeysMask);
- xkbi->slowKey= key;
- xkbi->slowKeysTimer = TimerSet(xkbi->slowKeysTimer,
- 0, ctrls->slow_keys_delay,
- AccessXSlowKeyExpire, (pointer)keybd);
- ignoreKeyEvent = TRUE;
- }
-
- /* Don't transmit the KeyPress if BounceKeys is turned on
- * and the user pressed the same key within a given time period
- * from the last release.
- */
- else if ((ctrls->enabled_ctrls & XkbBounceKeysMask) &&
- (key == xkbi->inactiveKey)) {
- if (XkbAX_NeedFeedback(ctrls,XkbAX_BKRejectFBMask))
- XkbDDXAccessXBeep(keybd,_BEEP_BOUNCE_REJECT,XkbBounceKeysMask);
- ignoreKeyEvent = TRUE;
- }
-
- /* Start repeating if necessary. Stop autorepeating if the user
- * presses a non-modifier key that doesn't autorepeat.
- */
- if (XkbDDXUsesSoftRepeat(keybd)) {
- if ((keybd->kbdfeed->ctrl.autoRepeat) &&
- ((ctrls->enabled_ctrls&(XkbSlowKeysMask|XkbRepeatKeysMask))==
- XkbRepeatKeysMask)) {
- if (BitIsOn(keybd->kbdfeed->ctrl.autoRepeats,key)) {
- if (xkbDebugFlags&0x10)
- DebugF("Starting software autorepeat...\n");
- if (xkbi->repeatKey == key)
- ignoreKeyEvent = TRUE;
- else {
- xkbi->repeatKey = key;
- xkbi->repeatKeyTimer= TimerSet(xkbi->repeatKeyTimer,
- 0, ctrls->repeat_delay,
- AccessXRepeatKeyExpire, (pointer)keybd);
- }
- }
- }
- }
-
- /* Check for two keys being pressed at the same time. This section
- * essentially says the following:
- *
- * If StickyKeys is on, and a modifier is currently being held down,
- * and one of the following is true: the current key is not a modifier
- * or the currentKey is a modifier, but not the only modifier being
- * held down, turn StickyKeys off if the TwoKeys off ctrl is set.
- */
- if ((ctrls->enabled_ctrls & XkbStickyKeysMask) &&
- (xkbi->state.base_mods!=0) &&
- (XkbAX_NeedOption(ctrls,XkbAX_TwoKeysMask))) {
- xkbControlsNotify cn;
- cn.keycode = key;
- cn.eventType = KeyPress;
- cn.requestMajor = 0;
- cn.requestMinor = 0;
- AccessXStickyKeysTurnOff(keybd,&cn);
- }
-
- if (!ignoreKeyEvent)
- XkbProcessKeyboardEvent(event, keybd);
- return ignoreKeyEvent;
-} /* AccessXFilterPressEvent */
-
-/************************************************************************/
-/* */
-/* AccessXFilterReleaseEvent */
-/* */
-/* Filter events before they get any further if SlowKeys is turned on. */
-/* In addition, this routine handles the ever so popular magic key */
-/* acts for turning various accessibility features on/off. */
-/* */
-/* Returns TRUE if this routine has discarded the event. */
-/* Returns FALSE if the event needs further processing. */
-/* */
-/************************************************************************/
-Bool
-AccessXFilterReleaseEvent( DeviceEvent* event,
- DeviceIntPtr keybd)
-{
-XkbSrvInfoPtr xkbi = keybd->key->xkbInfo;
-XkbControlsPtr ctrls = xkbi->desc->ctrls;
-KeyCode key = event->detail.key;
-Bool ignoreKeyEvent = FALSE;
-
- /* Don't transmit the KeyRelease if BounceKeys is on and
- * this is the release of a key that was ignored due to
- * BounceKeys.
- */
- if (ctrls->enabled_ctrls & XkbBounceKeysMask) {
- if ((key!=xkbi->mouseKey)&&(!BitIsOn(keybd->key->down,key)))
- ignoreKeyEvent = TRUE;
- xkbi->inactiveKey= key;
- xkbi->bounceKeysTimer= TimerSet(xkbi->bounceKeysTimer, 0,
- ctrls->debounce_delay,
- AccessXBounceKeyExpire, (pointer)keybd);
- }
-
- /* Don't transmit the KeyRelease if SlowKeys is turned on and
- * the user didn't hold the key long enough. We know we passed
- * the key if the down bit was set by CoreProcessKeyboadEvent.
- */
- if (ctrls->enabled_ctrls & XkbSlowKeysMask) {
- xkbAccessXNotify ev;
- unsigned beep_type;
- ev.keycode= key;
- ev.slowKeysDelay= ctrls->slow_keys_delay;
- ev.debounceDelay= ctrls->debounce_delay;
- if (BitIsOn(keybd->key->down,key) || (xkbi->mouseKey == key)) {
- ev.detail= XkbAXN_SKRelease;
- beep_type= _BEEP_SLOW_RELEASE;
- }
- else {
- ev.detail= XkbAXN_SKReject;
- beep_type= _BEEP_SLOW_REJECT;
- ignoreKeyEvent = TRUE;
- }
- XkbSendAccessXNotify(keybd,&ev);
- if (XkbAX_NeedFeedback(ctrls,XkbAX_SKRejectFBMask)) {
- XkbDDXAccessXBeep(keybd,beep_type,XkbSlowKeysMask);
- }
- if (xkbi->slowKey==key)
- xkbi->slowKey= 0;
- }
-
- /* Stop Repeating if the user releases the key that is currently
- * repeating.
- */
- if (xkbi->repeatKey==key) {
- xkbi->repeatKey= 0;
- }
-
- if ((ctrls->enabled_ctrls&XkbAccessXTimeoutMask)&&(ctrls->ax_timeout>0)) {
- xkbi->lastPtrEventTime= 0;
- xkbi->krgTimer= TimerSet(xkbi->krgTimer, 0,
- ctrls->ax_timeout*1000,
- AccessXTimeoutExpire, (pointer)keybd);
- xkbi->krgTimerActive= _ALL_TIMEOUT_TIMER;
- }
- else if (xkbi->krgTimerActive!=_OFF_TIMER) {
- xkbi->krgTimer= TimerSet(xkbi->krgTimer, 0, 0, NULL, NULL);
- xkbi->krgTimerActive= _OFF_TIMER;
- }
-
- /* Keep track of how many times the Shift key has been pressed.
- * If it has been pressed and released 5 times in a row, toggle
- * the state of StickyKeys.
- */
- if ((!ignoreKeyEvent)&&(xkbi->shiftKeyCount)) {
- KeySym *pSym= XkbKeySymsPtr(xkbi->desc,key);
- if ((pSym[0]!=XK_Shift_L)&&(pSym[0]!=XK_Shift_R)) {
- xkbi->shiftKeyCount= 0;
- }
- else if (xkbi->shiftKeyCount>=5) {
- xkbControlsNotify cn;
- cn.keycode = key;
- cn.eventType = KeyPress;
- cn.requestMajor = 0;
- cn.requestMinor = 0;
- if (ctrls->enabled_ctrls & XkbStickyKeysMask)
- AccessXStickyKeysTurnOff(keybd,&cn);
- else
- AccessXStickyKeysTurnOn(keybd,&cn);
- xkbi->shiftKeyCount= 0;
- }
- }
-
- if (!ignoreKeyEvent)
- XkbProcessKeyboardEvent(event, keybd);
- return ignoreKeyEvent;
-
-} /* AccessXFilterReleaseEvent */
-
-/************************************************************************/
-/* */
-/* ProcessPointerEvent */
-/* */
-/* This routine merely sets the shiftKeyCount and clears the keyboard */
-/* response group timer (if necessary) on a mouse event. This is so */
-/* multiple shifts with just the mouse and shift-drags with the mouse */
-/* don't accidentally turn on StickyKeys or the Keyboard Response Group.*/
-/* */
-/************************************************************************/
-extern int xkbDevicePrivateIndex;
-extern void xkbUnwrapProc(DeviceIntPtr, DeviceHandleProc, pointer);
-void
-ProcessPointerEvent( InternalEvent *ev,
- DeviceIntPtr mouse)
-{
-DeviceIntPtr dev;
-XkbSrvInfoPtr xkbi = NULL;
-unsigned changed = 0;
-ProcessInputProc backupproc;
-xkbDeviceInfoPtr xkbPrivPtr = XKBDEVICEINFO(mouse);
-DeviceEvent *event = &ev->device_event;
-
- dev = (IsMaster(mouse) || mouse->u.master) ? GetMaster(mouse, MASTER_KEYBOARD) : mouse;
-
- if (dev && dev->key)
- {
- xkbi = dev->key->xkbInfo;
- xkbi->shiftKeyCount = 0;
- xkbi->lastPtrEventTime= event->time;
- }
-
- if (event->type == ET_ButtonPress) {
- changed |= XkbPointerButtonMask;
- }
- else if (event->type == ET_ButtonRelease) {
- if (xkbi) {
- xkbi->lockedPtrButtons&= ~(1 << (event->detail.key & 0x7));
-
- if (IsMaster(dev))
- {
- DeviceIntPtr source;
- int rc;
- rc = dixLookupDevice(&source, event->sourceid, serverClient, DixWriteAccess);
- if (rc != Success)
- ErrorF("[xkb] bad sourceid '%d' on button release event.\n", event->sourceid);
- else if (!IsXTestDevice(source, GetMaster(dev, MASTER_POINTER)))
- XkbFakeDeviceButton(dev, FALSE, event->detail.key);
- }
- }
-
- changed |= XkbPointerButtonMask;
- }
-
- UNWRAP_PROCESS_INPUT_PROC(mouse, xkbPrivPtr, backupproc);
- mouse->public.processInputProc(ev, mouse);
- COND_WRAP_PROCESS_INPUT_PROC(mouse, xkbPrivPtr,
- backupproc, xkbUnwrapProc);
-
- if (!xkbi)
- return;
-
- xkbi->state.ptr_buttons = (mouse->button) ? mouse->button->state : 0;
-
- /* clear any latched modifiers */
- if ( xkbi->state.latched_mods && (event->type == ET_ButtonRelease) ) {
- unsigned changed_leds;
- XkbStateRec oldState;
- XkbSrvLedInfoPtr sli;
-
- sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId,0);
- oldState= xkbi->state;
- XkbLatchModifiers(dev,0xFF,0x00);
-
- XkbComputeDerivedState(xkbi);
- changed |= XkbStateChangedFlags(&oldState,&xkbi->state);
- if (changed&sli->usedComponents) {
- changed_leds= XkbIndicatorsToUpdate(dev,changed,FALSE);
- if (changed_leds) {
- XkbEventCauseRec cause;
- XkbSetCauseKey(&cause,(event->detail.key & 0x7), event->type);
- XkbUpdateIndicators(dev,changed_leds,TRUE,NULL,&cause);
- }
- }
- }
-
- if (((xkbi->flags&_XkbStateNotifyInProgress)==0)&&(changed!=0)) {
- xkbStateNotify sn;
- sn.keycode= event->detail.key;
- sn.eventType= event->type;
- sn.requestMajor = sn.requestMinor = 0;
- sn.changed= changed;
- XkbSendStateNotify(dev,&sn);
- }
-
-} /* ProcessPointerEvent */
-
-
-
-
+/************************************************************ +Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc. + +Permission 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 that both that copyright +notice and this permission notice appear in supporting +documentation, and that the name of Silicon Graphics not be +used in advertising or publicity pertaining to distribution +of the software without specific prior written permission. +Silicon Graphics makes no representation about the suitability +of this software for any purpose. It is provided "as is" +without any express or implied warranty. + +SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS +SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON +GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL +DAMAGES OR ANY 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 THIS SOFTWARE. + +********************************************************/ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include <stdio.h> +#include <math.h> +#include <X11/X.h> +#include <X11/Xproto.h> +#include <X11/keysym.h> +#include "exglobals.h" +#include <X11/extensions/XIproto.h> +#include "inputstr.h" +#include "eventstr.h" +#include <xkbsrv.h> +#if !defined(WIN32) +#include <sys/time.h> +#endif + +int XkbDfltRepeatDelay= 660; +int XkbDfltRepeatInterval= 40; + +#define DFLT_TIMEOUT_CTRLS (XkbAX_KRGMask|XkbStickyKeysMask|XkbMouseKeysMask) +#define DFLT_TIMEOUT_OPTS (XkbAX_IndicatorFBMask) + +unsigned short XkbDfltAccessXTimeout= 120; +unsigned int XkbDfltAccessXTimeoutMask= DFLT_TIMEOUT_CTRLS; +static unsigned int XkbDfltAccessXTimeoutValues= 0; +static unsigned int XkbDfltAccessXTimeoutOptionsMask= DFLT_TIMEOUT_OPTS; +static unsigned int XkbDfltAccessXTimeoutOptionsValues= 0; +unsigned int XkbDfltAccessXFeedback= XkbAccessXFeedbackMask; +unsigned short XkbDfltAccessXOptions= XkbAX_AllOptionsMask & ~(XkbAX_IndicatorFBMask|XkbAX_SKReleaseFBMask|XkbAX_SKRejectFBMask); + +void +AccessXComputeCurveFactor(XkbSrvInfoPtr xkbi,XkbControlsPtr ctrls) +{ + xkbi->mouseKeysCurve= 1.0+(((double)ctrls->mk_curve)*0.001); + xkbi->mouseKeysCurveFactor= ( ((double)ctrls->mk_max_speed)/ + pow((double)ctrls->mk_time_to_max,xkbi->mouseKeysCurve)); + return; +} + +void +AccessXInit(DeviceIntPtr keybd) +{ +XkbSrvInfoPtr xkbi = keybd->key->xkbInfo; +XkbControlsPtr ctrls = xkbi->desc->ctrls; + + xkbi->shiftKeyCount= 0; + xkbi->mouseKeysCounter= 0; + xkbi->inactiveKey= 0; + xkbi->slowKey= 0; + xkbi->repeatKey= 0; + xkbi->krgTimerActive= _OFF_TIMER; + xkbi->beepType= _BEEP_NONE; + xkbi->beepCount= 0; + xkbi->mouseKeyTimer= NULL; + xkbi->slowKeysTimer= NULL; + xkbi->bounceKeysTimer= NULL; + xkbi->repeatKeyTimer= NULL; + xkbi->krgTimer= NULL; + xkbi->beepTimer= NULL; + ctrls->repeat_delay = XkbDfltRepeatDelay; + ctrls->repeat_interval = XkbDfltRepeatInterval; + ctrls->debounce_delay = 300; + ctrls->slow_keys_delay = 300; + ctrls->mk_delay = 160; + ctrls->mk_interval = 40; + ctrls->mk_time_to_max = 30; + ctrls->mk_max_speed = 30; + ctrls->mk_curve = 500; + ctrls->mk_dflt_btn = 1; + ctrls->ax_timeout = XkbDfltAccessXTimeout; + ctrls->axt_ctrls_mask = XkbDfltAccessXTimeoutMask; + ctrls->axt_ctrls_values = XkbDfltAccessXTimeoutValues; + ctrls->axt_opts_mask = XkbDfltAccessXTimeoutOptionsMask; + ctrls->axt_opts_values = XkbDfltAccessXTimeoutOptionsValues; + if (XkbDfltAccessXTimeout) + ctrls->enabled_ctrls |= XkbAccessXTimeoutMask; + else + ctrls->enabled_ctrls &= ~XkbAccessXTimeoutMask; + ctrls->enabled_ctrls |= XkbDfltAccessXFeedback; + ctrls->ax_options = XkbDfltAccessXOptions; + AccessXComputeCurveFactor(xkbi,ctrls); + return; +} + +/************************************************************************/ +/* */ +/* AccessXKeyboardEvent */ +/* */ +/* Generate a synthetic keyboard event. */ +/* */ +/************************************************************************/ +static void +AccessXKeyboardEvent(DeviceIntPtr keybd, + int type, + BYTE keyCode, + Bool isRepeat) +{ + DeviceEvent event; + memset(&event, 0, sizeof(DeviceEvent)); + event.header = ET_Internal; + event.type = type; + event.detail.key = keyCode; + event.time = GetTimeInMillis(); + event.length = sizeof(DeviceEvent); + event.key_repeat = isRepeat; + event.sourceid = keybd->id; + event.deviceid = keybd->id; + + if (xkbDebugFlags&0x8) { + DebugF("[xkb] AXKE: Key %d %s\n", keyCode, + (event.type == ET_KeyPress ? "down" : "up")); + } + + XkbProcessKeyboardEvent(&event, keybd); + return; +} /* AccessXKeyboardEvent */ + +/************************************************************************/ +/* */ +/* AccessXKRGTurnOn */ +/* */ +/* Turn the keyboard response group on. */ +/* */ +/************************************************************************/ +static void +AccessXKRGTurnOn(DeviceIntPtr dev,CARD16 KRGControl,xkbControlsNotify *pCN) +{ +XkbSrvInfoPtr xkbi = dev->key->xkbInfo; +XkbControlsPtr ctrls = xkbi->desc->ctrls; +XkbControlsRec old; +XkbEventCauseRec cause; +XkbSrvLedInfoPtr sli; + + old= *ctrls; + ctrls->enabled_ctrls |= (KRGControl&XkbAX_KRGMask); + if (XkbComputeControlsNotify(dev,&old,ctrls,pCN,FALSE)) + XkbSendControlsNotify(dev,pCN); + cause.kc= pCN->keycode; + cause.event= pCN->eventType; + cause.mjr= pCN->requestMajor; + cause.mnr= pCN->requestMinor; + sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId,0); + XkbUpdateIndicators(dev,sli->usesControls,TRUE,NULL,&cause); + if (XkbAX_NeedFeedback(ctrls,XkbAX_FeatureFBMask)) + XkbDDXAccessXBeep(dev,_BEEP_FEATURE_ON,KRGControl); + return; + +} /* AccessXKRGTurnOn */ + +/************************************************************************/ +/* */ +/* AccessXKRGTurnOff */ +/* */ +/* Turn the keyboard response group off. */ +/* */ +/************************************************************************/ +static void +AccessXKRGTurnOff(DeviceIntPtr dev,xkbControlsNotify *pCN) +{ +XkbSrvInfoPtr xkbi = dev->key->xkbInfo; +XkbControlsPtr ctrls = xkbi->desc->ctrls; +XkbControlsRec old; +XkbEventCauseRec cause; +XkbSrvLedInfoPtr sli; + + old = *ctrls; + ctrls->enabled_ctrls &= ~XkbAX_KRGMask; + if (XkbComputeControlsNotify(dev,&old,ctrls,pCN,FALSE)) + XkbSendControlsNotify(dev,pCN); + cause.kc= pCN->keycode; + cause.event= pCN->eventType; + cause.mjr= pCN->requestMajor; + cause.mnr= pCN->requestMinor; + sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId,0); + XkbUpdateIndicators(dev,sli->usesControls,TRUE,NULL,&cause); + if (XkbAX_NeedFeedback(ctrls,XkbAX_FeatureFBMask)) { + unsigned changes= old.enabled_ctrls^ctrls->enabled_ctrls; + XkbDDXAccessXBeep(dev,_BEEP_FEATURE_OFF,changes); + } + return; + +} /* AccessXKRGTurnOff */ + +/************************************************************************/ +/* */ +/* AccessXStickyKeysTurnOn */ +/* */ +/* Turn StickyKeys on. */ +/* */ +/************************************************************************/ +static void +AccessXStickyKeysTurnOn(DeviceIntPtr dev,xkbControlsNotify *pCN) +{ +XkbSrvInfoPtr xkbi = dev->key->xkbInfo; +XkbControlsPtr ctrls = xkbi->desc->ctrls; +XkbControlsRec old; +XkbEventCauseRec cause; +XkbSrvLedInfoPtr sli; + + old = *ctrls; + ctrls->enabled_ctrls |= XkbStickyKeysMask; + xkbi->shiftKeyCount = 0; + if (XkbComputeControlsNotify(dev,&old,ctrls,pCN,FALSE)) + XkbSendControlsNotify(dev,pCN); + cause.kc= pCN->keycode; + cause.event= pCN->eventType; + cause.mjr= pCN->requestMajor; + cause.mnr= pCN->requestMinor; + sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId,0); + XkbUpdateIndicators(dev,sli->usesControls,TRUE,NULL,&cause); + if (XkbAX_NeedFeedback(ctrls,XkbAX_FeatureFBMask)) { + XkbDDXAccessXBeep(dev,_BEEP_FEATURE_ON,XkbStickyKeysMask); + } + return; + +} /* AccessXStickyKeysTurnOn */ + +/************************************************************************/ +/* */ +/* AccessXStickyKeysTurnOff */ +/* */ +/* Turn StickyKeys off. */ +/* */ +/************************************************************************/ +static void +AccessXStickyKeysTurnOff(DeviceIntPtr dev,xkbControlsNotify *pCN) +{ +XkbSrvInfoPtr xkbi = dev->key->xkbInfo; +XkbControlsPtr ctrls = xkbi->desc->ctrls; +XkbControlsRec old; +XkbEventCauseRec cause; +XkbSrvLedInfoPtr sli; + + old = *ctrls; + ctrls->enabled_ctrls &= ~XkbStickyKeysMask; + xkbi->shiftKeyCount = 0; + if (XkbComputeControlsNotify(dev,&old,ctrls,pCN,FALSE)) + XkbSendControlsNotify(dev,pCN); + + cause.kc= pCN->keycode; + cause.event= pCN->eventType; + cause.mjr= pCN->requestMajor; + cause.mnr= pCN->requestMinor; + sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId,0); + XkbUpdateIndicators(dev,sli->usesControls,TRUE,NULL,&cause); + if (XkbAX_NeedFeedback(ctrls,XkbAX_FeatureFBMask)) { + XkbDDXAccessXBeep(dev,_BEEP_FEATURE_OFF,XkbStickyKeysMask); + } +#ifndef NO_CLEAR_LATCHES_FOR_STICKY_KEYS_OFF + XkbClearAllLatchesAndLocks(dev,xkbi,FALSE,&cause); +#endif + return; +} /* AccessXStickyKeysTurnOff */ + +static CARD32 +AccessXKRGExpire(OsTimerPtr timer,CARD32 now,pointer arg) +{ +XkbSrvInfoPtr xkbi= ((DeviceIntPtr)arg)->key->xkbInfo; +xkbControlsNotify cn; + + if (xkbi->krgTimerActive==_KRG_WARN_TIMER) { + XkbDDXAccessXBeep((DeviceIntPtr)arg,_BEEP_SLOW_WARN,XkbStickyKeysMask); + xkbi->krgTimerActive= _KRG_TIMER; + return 4000; + } + xkbi->krgTimerActive= _OFF_TIMER; + cn.keycode = 0; + cn.eventType = 0; + cn.requestMajor = 0; + cn.requestMinor = 0; + if (xkbi->desc->ctrls->enabled_ctrls&XkbSlowKeysMask) + AccessXKRGTurnOff((DeviceIntPtr)arg,&cn); + else AccessXKRGTurnOn((DeviceIntPtr)arg,XkbSlowKeysMask,&cn); + return 0; +} + +static CARD32 +AccessXRepeatKeyExpire(OsTimerPtr timer,CARD32 now,pointer arg) +{ +DeviceIntPtr dev = (DeviceIntPtr) arg; +XkbSrvInfoPtr xkbi = dev->key->xkbInfo; + + if (xkbi->repeatKey == 0) + return 0; + + AccessXKeyboardEvent(dev, ET_KeyPress, xkbi->repeatKey, TRUE); + + return xkbi->desc->ctrls->repeat_interval; +} + +void +AccessXCancelRepeatKey(XkbSrvInfoPtr xkbi,KeyCode key) +{ + if (xkbi->repeatKey==key) + xkbi->repeatKey= 0; + return; +} + +static CARD32 +AccessXSlowKeyExpire(OsTimerPtr timer,CARD32 now,pointer arg) +{ +DeviceIntPtr keybd; +XkbSrvInfoPtr xkbi; +XkbDescPtr xkb; +XkbControlsPtr ctrls; + + keybd= (DeviceIntPtr)arg; + xkbi= keybd->key->xkbInfo; + xkb= xkbi->desc; + ctrls= xkb->ctrls; + if (xkbi->slowKey!=0) { + xkbAccessXNotify ev; + KeySym *sym= XkbKeySymsPtr(xkb,xkbi->slowKey); + ev.detail= XkbAXN_SKAccept; + ev.keycode= xkbi->slowKey; + ev.slowKeysDelay= ctrls->slow_keys_delay; + ev.debounceDelay= ctrls->debounce_delay; + XkbSendAccessXNotify(keybd,&ev); + if (XkbAX_NeedFeedback(ctrls,XkbAX_SKAcceptFBMask)) + XkbDDXAccessXBeep(keybd,_BEEP_SLOW_ACCEPT,XkbSlowKeysMask); + AccessXKeyboardEvent(keybd, ET_KeyPress,xkbi->slowKey,FALSE); + /* check for magic sequences */ + if ((ctrls->enabled_ctrls&XkbAccessXKeysMask) && + ((sym[0]==XK_Shift_R)||(sym[0]==XK_Shift_L))) + xkbi->shiftKeyCount++; + + /* Start repeating if necessary. Stop autorepeating if the user + * presses a non-modifier key that doesn't autorepeat. + */ + if (keybd->kbdfeed->ctrl.autoRepeat && + ((xkbi->slowKey != xkbi->mouseKey) || (!xkbi->mouseKeysAccel)) && + (ctrls->enabled_ctrls&XkbRepeatKeysMask)) { + if (BitIsOn(keybd->kbdfeed->ctrl.autoRepeats,xkbi->slowKey)) { + xkbi->repeatKey = xkbi->slowKey; + xkbi->repeatKeyTimer= TimerSet(xkbi->repeatKeyTimer, + 0, ctrls->repeat_delay, + AccessXRepeatKeyExpire, (pointer)keybd); + } + } + } + return 0; +} + +static CARD32 +AccessXBounceKeyExpire(OsTimerPtr timer,CARD32 now,pointer arg) +{ +XkbSrvInfoPtr xkbi= ((DeviceIntPtr)arg)->key->xkbInfo; + + xkbi->inactiveKey= 0; + return 0; +} + +static CARD32 +AccessXTimeoutExpire(OsTimerPtr timer,CARD32 now,pointer arg) +{ +DeviceIntPtr dev = (DeviceIntPtr)arg; +XkbSrvInfoPtr xkbi= dev->key->xkbInfo; +XkbControlsPtr ctrls= xkbi->desc->ctrls; +XkbControlsRec old; +xkbControlsNotify cn; +XkbEventCauseRec cause; +XkbSrvLedInfoPtr sli; + + if (xkbi->lastPtrEventTime) { + unsigned timeToWait = (ctrls->ax_timeout*1000); + unsigned timeElapsed = (now-xkbi->lastPtrEventTime); + + if (timeToWait > timeElapsed) + return timeToWait - timeElapsed; + } + old= *ctrls; + xkbi->shiftKeyCount= 0; + ctrls->enabled_ctrls&= ~ctrls->axt_ctrls_mask; + ctrls->enabled_ctrls|= + (ctrls->axt_ctrls_values&ctrls->axt_ctrls_mask); + if (ctrls->axt_opts_mask) { + ctrls->ax_options&= ~ctrls->axt_opts_mask; + ctrls->ax_options|= (ctrls->axt_opts_values&ctrls->axt_opts_mask); + } + if (XkbComputeControlsNotify(dev,&old,ctrls,&cn,FALSE)) { + cn.keycode = 0; + cn.eventType = 0; + cn.requestMajor = 0; + cn.requestMinor = 0; + XkbSendControlsNotify(dev,&cn); + } + XkbSetCauseUnknown(&cause); + sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId,0); + XkbUpdateIndicators(dev,sli->usesControls,TRUE,NULL,&cause); + if (ctrls->ax_options!=old.ax_options) { + unsigned set,cleared,bell; + set= ctrls->ax_options&(~old.ax_options); + cleared= (~ctrls->ax_options)&old.ax_options; + if (set && cleared) bell= _BEEP_FEATURE_CHANGE; + else if (set) bell= _BEEP_FEATURE_ON; + else bell= _BEEP_FEATURE_OFF; + XkbDDXAccessXBeep(dev,bell,XkbAccessXTimeoutMask); + } + xkbi->krgTimerActive= _OFF_TIMER; + return 0; +} + + +/************************************************************************/ +/* */ +/* AccessXFilterPressEvent */ +/* */ +/* Filter events before they get any further if SlowKeys is turned on. */ +/* In addition, this routine handles the ever so popular magic key */ +/* acts for turning various accessibility features on/off. */ +/* */ +/* Returns TRUE if this routine has discarded the event. */ +/* Returns FALSE if the event needs further processing. */ +/* */ +/************************************************************************/ +Bool +AccessXFilterPressEvent( DeviceEvent* event, + DeviceIntPtr keybd) +{ +XkbSrvInfoPtr xkbi = keybd->key->xkbInfo; +XkbControlsPtr ctrls = xkbi->desc->ctrls; +Bool ignoreKeyEvent = FALSE; +KeyCode key = event->detail.key; +KeySym * sym = XkbKeySymsPtr(xkbi->desc,key); + + if (ctrls->enabled_ctrls&XkbAccessXKeysMask) { + /* check for magic sequences */ + if ((sym[0]==XK_Shift_R)||(sym[0]==XK_Shift_L)) { + if (XkbAX_NeedFeedback(ctrls,XkbAX_SlowWarnFBMask)) { + xkbi->krgTimerActive = _KRG_WARN_TIMER; + xkbi->krgTimer= TimerSet(xkbi->krgTimer, 0, 4000, + AccessXKRGExpire, (pointer)keybd); + } + else { + xkbi->krgTimerActive = _KRG_TIMER; + xkbi->krgTimer= TimerSet(xkbi->krgTimer, 0, 8000, + AccessXKRGExpire, (pointer)keybd); + } + if (!(ctrls->enabled_ctrls & XkbSlowKeysMask)) { + CARD32 now= GetTimeInMillis(); + if ((now-xkbi->lastShiftEventTime)>15000) + xkbi->shiftKeyCount= 1; + else xkbi->shiftKeyCount++; + xkbi->lastShiftEventTime= now; + } + } + else { + if (xkbi->krgTimerActive) { + xkbi->krgTimer= TimerSet(xkbi->krgTimer,0, 0, NULL, NULL); + xkbi->krgTimerActive= _OFF_TIMER; + } + } + } + + /* Don't transmit the KeyPress if SlowKeys is turned on; + * The wakeup handler will synthesize one for us if the user + * has held the key long enough. + */ + if (ctrls->enabled_ctrls & XkbSlowKeysMask) { + xkbAccessXNotify ev; + /* If key was already pressed, ignore subsequent press events + * from the server's autorepeat + */ + if(xkbi->slowKey == key) + return TRUE; + ev.detail= XkbAXN_SKPress; + ev.keycode= key; + ev.slowKeysDelay= ctrls->slow_keys_delay; + ev.debounceDelay= ctrls->debounce_delay; + XkbSendAccessXNotify(keybd,&ev); + if (XkbAX_NeedFeedback(ctrls,XkbAX_SKPressFBMask)) + XkbDDXAccessXBeep(keybd,_BEEP_SLOW_PRESS,XkbSlowKeysMask); + xkbi->slowKey= key; + xkbi->slowKeysTimer = TimerSet(xkbi->slowKeysTimer, + 0, ctrls->slow_keys_delay, + AccessXSlowKeyExpire, (pointer)keybd); + ignoreKeyEvent = TRUE; + } + + /* Don't transmit the KeyPress if BounceKeys is turned on + * and the user pressed the same key within a given time period + * from the last release. + */ + else if ((ctrls->enabled_ctrls & XkbBounceKeysMask) && + (key == xkbi->inactiveKey)) { + if (XkbAX_NeedFeedback(ctrls,XkbAX_BKRejectFBMask)) + XkbDDXAccessXBeep(keybd,_BEEP_BOUNCE_REJECT,XkbBounceKeysMask); + ignoreKeyEvent = TRUE; + } + + /* Start repeating if necessary. Stop autorepeating if the user + * presses a non-modifier key that doesn't autorepeat. + */ + if (XkbDDXUsesSoftRepeat(keybd)) { + if ((keybd->kbdfeed->ctrl.autoRepeat) && + ((ctrls->enabled_ctrls&(XkbSlowKeysMask|XkbRepeatKeysMask))== + XkbRepeatKeysMask)) { + if (BitIsOn(keybd->kbdfeed->ctrl.autoRepeats,key)) { + if (xkbDebugFlags&0x10) + DebugF("Starting software autorepeat...\n"); + if (xkbi->repeatKey == key) + ignoreKeyEvent = TRUE; + else { + xkbi->repeatKey = key; + xkbi->repeatKeyTimer= TimerSet(xkbi->repeatKeyTimer, + 0, ctrls->repeat_delay, + AccessXRepeatKeyExpire, (pointer)keybd); + } + } + } + } + + /* Check for two keys being pressed at the same time. This section + * essentially says the following: + * + * If StickyKeys is on, and a modifier is currently being held down, + * and one of the following is true: the current key is not a modifier + * or the currentKey is a modifier, but not the only modifier being + * held down, turn StickyKeys off if the TwoKeys off ctrl is set. + */ + if ((ctrls->enabled_ctrls & XkbStickyKeysMask) && + (xkbi->state.base_mods!=0) && + (XkbAX_NeedOption(ctrls,XkbAX_TwoKeysMask))) { + xkbControlsNotify cn; + cn.keycode = key; + cn.eventType = KeyPress; + cn.requestMajor = 0; + cn.requestMinor = 0; + AccessXStickyKeysTurnOff(keybd,&cn); + } + + if (!ignoreKeyEvent) + XkbProcessKeyboardEvent(event, keybd); + return ignoreKeyEvent; +} /* AccessXFilterPressEvent */ + +/************************************************************************/ +/* */ +/* AccessXFilterReleaseEvent */ +/* */ +/* Filter events before they get any further if SlowKeys is turned on. */ +/* In addition, this routine handles the ever so popular magic key */ +/* acts for turning various accessibility features on/off. */ +/* */ +/* Returns TRUE if this routine has discarded the event. */ +/* Returns FALSE if the event needs further processing. */ +/* */ +/************************************************************************/ +Bool +AccessXFilterReleaseEvent( DeviceEvent* event, + DeviceIntPtr keybd) +{ +XkbSrvInfoPtr xkbi = keybd->key->xkbInfo; +XkbControlsPtr ctrls = xkbi->desc->ctrls; +KeyCode key = event->detail.key; +Bool ignoreKeyEvent = FALSE; + + /* Don't transmit the KeyRelease if BounceKeys is on and + * this is the release of a key that was ignored due to + * BounceKeys. + */ + if (ctrls->enabled_ctrls & XkbBounceKeysMask) { + if ((key!=xkbi->mouseKey)&&(!BitIsOn(keybd->key->down,key))) + ignoreKeyEvent = TRUE; + xkbi->inactiveKey= key; + xkbi->bounceKeysTimer= TimerSet(xkbi->bounceKeysTimer, 0, + ctrls->debounce_delay, + AccessXBounceKeyExpire, (pointer)keybd); + } + + /* Don't transmit the KeyRelease if SlowKeys is turned on and + * the user didn't hold the key long enough. We know we passed + * the key if the down bit was set by CoreProcessKeyboadEvent. + */ + if (ctrls->enabled_ctrls & XkbSlowKeysMask) { + xkbAccessXNotify ev; + unsigned beep_type; + ev.keycode= key; + ev.slowKeysDelay= ctrls->slow_keys_delay; + ev.debounceDelay= ctrls->debounce_delay; + if (BitIsOn(keybd->key->down,key) || (xkbi->mouseKey == key)) { + ev.detail= XkbAXN_SKRelease; + beep_type= _BEEP_SLOW_RELEASE; + } + else { + ev.detail= XkbAXN_SKReject; + beep_type= _BEEP_SLOW_REJECT; + ignoreKeyEvent = TRUE; + } + XkbSendAccessXNotify(keybd,&ev); + if (XkbAX_NeedFeedback(ctrls,XkbAX_SKRejectFBMask)) { + XkbDDXAccessXBeep(keybd,beep_type,XkbSlowKeysMask); + } + if (xkbi->slowKey==key) + xkbi->slowKey= 0; + } + + /* Stop Repeating if the user releases the key that is currently + * repeating. + */ + if (xkbi->repeatKey==key) { + xkbi->repeatKey= 0; + } + + if ((ctrls->enabled_ctrls&XkbAccessXTimeoutMask)&&(ctrls->ax_timeout>0)) { + xkbi->lastPtrEventTime= 0; + xkbi->krgTimer= TimerSet(xkbi->krgTimer, 0, + ctrls->ax_timeout*1000, + AccessXTimeoutExpire, (pointer)keybd); + xkbi->krgTimerActive= _ALL_TIMEOUT_TIMER; + } + else if (xkbi->krgTimerActive!=_OFF_TIMER) { + xkbi->krgTimer= TimerSet(xkbi->krgTimer, 0, 0, NULL, NULL); + xkbi->krgTimerActive= _OFF_TIMER; + } + + /* Keep track of how many times the Shift key has been pressed. + * If it has been pressed and released 5 times in a row, toggle + * the state of StickyKeys. + */ + if ((!ignoreKeyEvent)&&(xkbi->shiftKeyCount)) { + KeySym *pSym= XkbKeySymsPtr(xkbi->desc,key); + if ((pSym[0]!=XK_Shift_L)&&(pSym[0]!=XK_Shift_R)) { + xkbi->shiftKeyCount= 0; + } + else if (xkbi->shiftKeyCount>=5) { + xkbControlsNotify cn; + cn.keycode = key; + cn.eventType = KeyPress; + cn.requestMajor = 0; + cn.requestMinor = 0; + if (ctrls->enabled_ctrls & XkbStickyKeysMask) + AccessXStickyKeysTurnOff(keybd,&cn); + else + AccessXStickyKeysTurnOn(keybd,&cn); + xkbi->shiftKeyCount= 0; + } + } + + if (!ignoreKeyEvent) + XkbProcessKeyboardEvent(event, keybd); + return ignoreKeyEvent; + +} /* AccessXFilterReleaseEvent */ + +/************************************************************************/ +/* */ +/* ProcessPointerEvent */ +/* */ +/* This routine merely sets the shiftKeyCount and clears the keyboard */ +/* response group timer (if necessary) on a mouse event. This is so */ +/* multiple shifts with just the mouse and shift-drags with the mouse */ +/* don't accidentally turn on StickyKeys or the Keyboard Response Group.*/ +/* */ +/************************************************************************/ +extern int xkbDevicePrivateIndex; +extern void xkbUnwrapProc(DeviceIntPtr, DeviceHandleProc, pointer); +void +ProcessPointerEvent( InternalEvent *ev, + DeviceIntPtr mouse) +{ +DeviceIntPtr dev; +XkbSrvInfoPtr xkbi = NULL; +unsigned changed = 0; +ProcessInputProc backupproc; +xkbDeviceInfoPtr xkbPrivPtr = XKBDEVICEINFO(mouse); +DeviceEvent *event = &ev->device_event; + + dev = IsFloating(mouse) ? mouse : GetMaster(mouse, MASTER_KEYBOARD); + + if (dev && dev->key) + { + xkbi = dev->key->xkbInfo; + xkbi->shiftKeyCount = 0; + xkbi->lastPtrEventTime= event->time; + } + + if (event->type == ET_ButtonPress) { + changed |= XkbPointerButtonMask; + } + else if (event->type == ET_ButtonRelease) { + if (xkbi) { + xkbi->lockedPtrButtons&= ~(1 << (event->detail.key & 0x7)); + + if (IsMaster(dev)) + { + DeviceIntPtr source; + int rc; + rc = dixLookupDevice(&source, event->sourceid, serverClient, DixWriteAccess); + if (rc != Success) + ErrorF("[xkb] bad sourceid '%d' on button release event.\n", event->sourceid); + else if (!IsXTestDevice(source, GetMaster(dev, MASTER_POINTER))) + XkbFakeDeviceButton(dev, FALSE, event->detail.key); + } + } + + changed |= XkbPointerButtonMask; + } + + UNWRAP_PROCESS_INPUT_PROC(mouse, xkbPrivPtr, backupproc); + mouse->public.processInputProc(ev, mouse); + COND_WRAP_PROCESS_INPUT_PROC(mouse, xkbPrivPtr, + backupproc, xkbUnwrapProc); + + if (!xkbi) + return; + + xkbi->state.ptr_buttons = (mouse->button) ? mouse->button->state : 0; + + /* clear any latched modifiers */ + if ( xkbi->state.latched_mods && (event->type == ET_ButtonRelease) ) { + unsigned changed_leds; + XkbStateRec oldState; + XkbSrvLedInfoPtr sli; + + sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId,0); + oldState= xkbi->state; + XkbLatchModifiers(dev,0xFF,0x00); + + XkbComputeDerivedState(xkbi); + changed |= XkbStateChangedFlags(&oldState,&xkbi->state); + if (changed&sli->usedComponents) { + changed_leds= XkbIndicatorsToUpdate(dev,changed,FALSE); + if (changed_leds) { + XkbEventCauseRec cause; + XkbSetCauseKey(&cause,(event->detail.key & 0x7), event->type); + XkbUpdateIndicators(dev,changed_leds,TRUE,NULL,&cause); + } + } + } + + if (((xkbi->flags&_XkbStateNotifyInProgress)==0)&&(changed!=0)) { + xkbStateNotify sn; + sn.keycode= event->detail.key; + sn.eventType= event->type; + sn.requestMajor = sn.requestMinor = 0; + sn.changed= changed; + XkbSendStateNotify(dev,&sn); + } + +} /* ProcessPointerEvent */ + + + + diff --git a/xorg-server/xkb/xkbActions.c b/xorg-server/xkb/xkbActions.c index b3f91cd9e..65c678af8 100644 --- a/xorg-server/xkb/xkbActions.c +++ b/xorg-server/xkb/xkbActions.c @@ -1,1441 +1,1441 @@ -/************************************************************
-Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc.
-
-Permission 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 that both that copyright
-notice and this permission notice appear in supporting
-documentation, and that the name of Silicon Graphics not be
-used in advertising or publicity pertaining to distribution
-of the software without specific prior written permission.
-Silicon Graphics makes no representation about the suitability
-of this software for any purpose. It is provided "as is"
-without any express or implied warranty.
-
-SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
-SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
-AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
-GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
-DAMAGES OR ANY 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 THIS SOFTWARE.
-
-********************************************************/
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#include <stdio.h>
-#include <math.h>
-#include <X11/X.h>
-#include <X11/Xproto.h>
-#include <X11/keysym.h>
-#include "misc.h"
-#include "inputstr.h"
-#include "exevents.h"
-#include "eventstr.h"
-#include <xkbsrv.h>
-#include "xkb.h"
-#include <ctype.h>
-#include "mi.h"
-#include "mipointer.h"
-#include "inpututils.h"
-#define EXTENSION_EVENT_BASE 64
-
-DevPrivateKeyRec xkbDevicePrivateKeyRec;
-
-void XkbFakeDeviceButton(DeviceIntPtr dev,Bool press,int button);
-static void XkbFakePointerMotion(DeviceIntPtr dev, unsigned flags,int x,int y);
-
-void
-xkbUnwrapProc(DeviceIntPtr device, DeviceHandleProc proc,
- pointer data)
-{
- xkbDeviceInfoPtr xkbPrivPtr = XKBDEVICEINFO(device);
- ProcessInputProc backupproc;
- if(xkbPrivPtr->unwrapProc)
- xkbPrivPtr->unwrapProc = NULL;
-
- UNWRAP_PROCESS_INPUT_PROC(device,xkbPrivPtr, backupproc);
- proc(device,data);
- COND_WRAP_PROCESS_INPUT_PROC(device,xkbPrivPtr,
- backupproc,xkbUnwrapProc);
-}
-
-Bool
-XkbInitPrivates(void)
-{
- return dixRegisterPrivateKey(&xkbDevicePrivateKeyRec, PRIVATE_DEVICE, 0);
-}
-
-void
-XkbSetExtension(DeviceIntPtr device, ProcessInputProc proc)
-{
- xkbDeviceInfoPtr xkbPrivPtr;
-
- xkbPrivPtr = (xkbDeviceInfoPtr) calloc(1, sizeof(xkbDeviceInfoRec));
- if (!xkbPrivPtr)
- return;
- xkbPrivPtr->unwrapProc = NULL;
-
- dixSetPrivate(&device->devPrivates, xkbDevicePrivateKey, xkbPrivPtr);
- WRAP_PROCESS_INPUT_PROC(device, xkbPrivPtr, proc, xkbUnwrapProc);
-}
-
-/***====================================================================***/
-
-static XkbAction
-_FixUpAction(XkbDescPtr xkb,XkbAction *act)
-{
-static XkbAction fake;
-
- if (XkbIsPtrAction(act)&&(!(xkb->ctrls->enabled_ctrls&XkbMouseKeysMask))) {
- fake.type = XkbSA_NoAction;
- return fake;
- }
- if (xkb->ctrls->enabled_ctrls&XkbStickyKeysMask) {
- if (act->any.type==XkbSA_SetMods) {
- fake.mods.type = XkbSA_LatchMods;
- fake.mods.mask = act->mods.mask;
- if (XkbAX_NeedOption(xkb->ctrls,XkbAX_LatchToLockMask))
- fake.mods.flags= XkbSA_ClearLocks|XkbSA_LatchToLock;
- else fake.mods.flags= XkbSA_ClearLocks;
- return fake;
- }
- if (act->any.type==XkbSA_SetGroup) {
- fake.group.type = XkbSA_LatchGroup;
- if (XkbAX_NeedOption(xkb->ctrls,XkbAX_LatchToLockMask))
- fake.group.flags= XkbSA_ClearLocks|XkbSA_LatchToLock;
- else fake.group.flags= XkbSA_ClearLocks;
- XkbSASetGroup(&fake.group,XkbSAGroup(&act->group));
- return fake;
- }
- }
- return *act;
-}
-
-static XkbAction
-XkbGetKeyAction(XkbSrvInfoPtr xkbi,XkbStatePtr xkbState,CARD8 key)
-{
-int effectiveGroup;
-int col;
-XkbDescPtr xkb;
-XkbKeyTypePtr type;
-XkbAction * pActs;
-static XkbAction fake;
-
- xkb= xkbi->desc;
- if (!XkbKeyHasActions(xkb,key) || !XkbKeycodeInRange(xkb,key)) {
- fake.type = XkbSA_NoAction;
- return fake;
- }
- pActs= XkbKeyActionsPtr(xkb,key);
- col= 0;
-
- effectiveGroup = XkbGetEffectiveGroup(xkbi, xkbState, key);
- if (effectiveGroup != XkbGroup1Index)
- col += (effectiveGroup * XkbKeyGroupsWidth(xkb, key));
-
- type= XkbKeyKeyType(xkb,key,effectiveGroup);
- if (type->map!=NULL) {
- register unsigned i,mods;
- register XkbKTMapEntryPtr entry;
- mods= xkbState->mods&type->mods.mask;
- for (entry= type->map,i=0;i<type->map_count;i++,entry++) {
- if ((entry->active)&&(entry->mods.mask==mods)) {
- col+= entry->level;
- break;
- }
- }
- }
- if (pActs[col].any.type==XkbSA_NoAction)
- return pActs[col];
- fake= _FixUpAction(xkb,&pActs[col]);
- return fake;
-}
-
-static XkbAction
-XkbGetButtonAction(DeviceIntPtr kbd,DeviceIntPtr dev,int button)
-{
-XkbAction fake;
- if ((dev->button)&&(dev->button->xkb_acts)) {
- if (dev->button->xkb_acts[button-1].any.type!=XkbSA_NoAction) {
- fake= _FixUpAction(kbd->key->xkbInfo->desc,
- &dev->button->xkb_acts[button-1]);
- return fake;
- }
- }
- fake.any.type= XkbSA_NoAction;
- return fake;
-}
-
-/***====================================================================***/
-
-#define SYNTHETIC_KEYCODE 1
-#define BTN_ACT_FLAG 0x100
-
-static int
-_XkbFilterSetState( XkbSrvInfoPtr xkbi,
- XkbFilterPtr filter,
- unsigned keycode,
- XkbAction *pAction)
-{
- if (filter->keycode==0) { /* initial press */
- filter->keycode = keycode;
- filter->active = 1;
- filter->filterOthers = ((pAction->mods.mask&XkbSA_ClearLocks)!=0);
- filter->priv = 0;
- filter->filter = _XkbFilterSetState;
- if (pAction->type==XkbSA_SetMods) {
- filter->upAction = *pAction;
- xkbi->setMods= pAction->mods.mask;
- }
- else {
- xkbi->groupChange = XkbSAGroup(&pAction->group);
- if (pAction->group.flags&XkbSA_GroupAbsolute)
- xkbi->groupChange-= xkbi->state.base_group;
- filter->upAction= *pAction;
- XkbSASetGroup(&filter->upAction.group,xkbi->groupChange);
- }
- }
- else if (filter->keycode==keycode) {
- if (filter->upAction.type==XkbSA_SetMods) {
- xkbi->clearMods = filter->upAction.mods.mask;
- if (filter->upAction.mods.flags&XkbSA_ClearLocks) {
- xkbi->state.locked_mods&= ~filter->upAction.mods.mask;
- }
- }
- else {
- if (filter->upAction.group.flags&XkbSA_ClearLocks) {
- xkbi->state.locked_group = 0;
- }
- xkbi->groupChange = -XkbSAGroup(&filter->upAction.group);
- }
- filter->active = 0;
- }
- else {
- filter->upAction.mods.flags&= ~XkbSA_ClearLocks;
- filter->filterOthers = 0;
- }
- return 1;
-}
-
-#define LATCH_KEY_DOWN 1
-#define LATCH_PENDING 2
-#define NO_LATCH 3
-
-static int
-_XkbFilterLatchState( XkbSrvInfoPtr xkbi,
- XkbFilterPtr filter,
- unsigned keycode,
- XkbAction * pAction)
-{
-
- if (filter->keycode==0) { /* initial press */
- filter->keycode = keycode;
- filter->active = 1;
- filter->filterOthers = 1;
- filter->priv = LATCH_KEY_DOWN;
- filter->filter = _XkbFilterLatchState;
- if (pAction->type==XkbSA_LatchMods) {
- filter->upAction = *pAction;
- xkbi->setMods = pAction->mods.mask;
- }
- else {
- xkbi->groupChange = XkbSAGroup(&pAction->group);
- if (pAction->group.flags&XkbSA_GroupAbsolute)
- xkbi->groupChange-= xkbi->state.base_group;
- filter->upAction= *pAction;
- XkbSASetGroup(&filter->upAction.group,xkbi->groupChange);
- }
- }
- else if ( pAction && (filter->priv==LATCH_PENDING) ) {
- if (((1<<pAction->type)&XkbSA_BreakLatch)!=0) {
- filter->active = 0;
- if (filter->upAction.type==XkbSA_LatchMods)
- xkbi->state.latched_mods&= ~filter->upAction.mods.mask;
- else xkbi->state.latched_group-=XkbSAGroup(&filter->upAction.group);
- }
- else if ((pAction->type==filter->upAction.type)&&
- (pAction->mods.flags==filter->upAction.mods.flags)&&
- (pAction->mods.mask==filter->upAction.mods.mask)) {
- if (filter->upAction.mods.flags&XkbSA_LatchToLock) {
- XkbControlsPtr ctrls= xkbi->desc->ctrls;
- if (filter->upAction.type==XkbSA_LatchMods)
- pAction->mods.type= XkbSA_LockMods;
- else pAction->group.type= XkbSA_LockGroup;
- if (XkbAX_NeedFeedback(ctrls,XkbAX_StickyKeysFBMask)&&
- (ctrls->enabled_ctrls&XkbStickyKeysMask)) {
- XkbDDXAccessXBeep(xkbi->device,_BEEP_STICKY_LOCK,
- XkbStickyKeysMask);
- }
- }
- else {
- if (filter->upAction.type==XkbSA_LatchMods)
- pAction->mods.type= XkbSA_SetMods;
- else pAction->group.type= XkbSA_SetGroup;
- }
- if (filter->upAction.type==XkbSA_LatchMods)
- xkbi->state.latched_mods&= ~filter->upAction.mods.mask;
- else xkbi->state.latched_group-=XkbSAGroup(&filter->upAction.group);
- filter->active = 0;
- }
- }
- else if (filter->keycode==keycode) { /* release */
- XkbControlsPtr ctrls= xkbi->desc->ctrls;
- int needBeep;
- int beepType= _BEEP_NONE;
-
- needBeep= ((ctrls->enabled_ctrls&XkbStickyKeysMask)&&
- XkbAX_NeedFeedback(ctrls,XkbAX_StickyKeysFBMask));
- if (filter->upAction.type==XkbSA_LatchMods) {
- xkbi->clearMods = filter->upAction.mods.mask;
- if ((filter->upAction.mods.flags&XkbSA_ClearLocks)&&
- (xkbi->clearMods&xkbi->state.locked_mods)==xkbi->clearMods) {
- xkbi->state.locked_mods&= ~xkbi->clearMods;
- filter->priv= NO_LATCH;
- beepType= _BEEP_STICKY_UNLOCK;
- }
- }
- else {
- xkbi->groupChange = -XkbSAGroup(&filter->upAction.group);
- if ((filter->upAction.group.flags&XkbSA_ClearLocks)&&
- (xkbi->state.locked_group)) {
- xkbi->state.locked_group = 0;
- filter->priv = NO_LATCH;
- beepType= _BEEP_STICKY_UNLOCK;
- }
- }
- if (filter->priv==NO_LATCH) {
- filter->active= 0;
- }
- else {
- filter->priv= LATCH_PENDING;
- if (filter->upAction.type==XkbSA_LatchMods) {
- xkbi->state.latched_mods |= filter->upAction.mods.mask;
- needBeep = xkbi->state.latched_mods ? needBeep : 0;
- xkbi->state.latched_mods |= filter->upAction.mods.mask;
- }
- else {
- xkbi->state.latched_group+= XkbSAGroup(&filter->upAction.group);
- }
- if (needBeep && (beepType==_BEEP_NONE))
- beepType= _BEEP_STICKY_LATCH;
- }
- if (needBeep && (beepType!=_BEEP_NONE))
- XkbDDXAccessXBeep(xkbi->device,beepType,XkbStickyKeysMask);
- }
- else if (filter->priv==LATCH_KEY_DOWN) {
- filter->priv= NO_LATCH;
- filter->filterOthers = 0;
- }
- return 1;
-}
-
-static int
-_XkbFilterLockState( XkbSrvInfoPtr xkbi,
- XkbFilterPtr filter,
- unsigned keycode,
- XkbAction * pAction)
-{
- if (pAction&&(pAction->type==XkbSA_LockGroup)) {
- if (pAction->group.flags&XkbSA_GroupAbsolute)
- xkbi->state.locked_group= XkbSAGroup(&pAction->group);
- else xkbi->state.locked_group+= XkbSAGroup(&pAction->group);
- return 1;
- }
- if (filter->keycode==0) { /* initial press */
- filter->keycode = keycode;
- filter->active = 1;
- filter->filterOthers = 0;
- filter->priv = 0;
- filter->filter = _XkbFilterLockState;
- filter->upAction = *pAction;
- xkbi->state.locked_mods^= pAction->mods.mask;
- xkbi->setMods = pAction->mods.mask;
- }
- else if (filter->keycode==keycode) {
- filter->active = 0;
- xkbi->clearMods = filter->upAction.mods.mask;
- }
- return 1;
-}
-
-#define ISO_KEY_DOWN 0
-#define NO_ISO_LOCK 1
-
-static int
-_XkbFilterISOLock( XkbSrvInfoPtr xkbi,
- XkbFilterPtr filter,
- unsigned keycode,
- XkbAction * pAction)
-{
-
- if (filter->keycode==0) { /* initial press */
- CARD8 flags= pAction->iso.flags;
-
- filter->keycode = keycode;
- filter->active = 1;
- filter->filterOthers = 1;
- filter->priv = ISO_KEY_DOWN;
- filter->upAction = *pAction;
- filter->filter = _XkbFilterISOLock;
- if (flags&XkbSA_ISODfltIsGroup) {
- xkbi->groupChange = XkbSAGroup(&pAction->iso);
- xkbi->setMods = 0;
- }
- else {
- xkbi->setMods = pAction->iso.mask;
- xkbi->groupChange = 0;
- }
- if ((!(flags&XkbSA_ISONoAffectMods))&&(xkbi->state.base_mods)) {
- filter->priv= NO_ISO_LOCK;
- xkbi->state.locked_mods^= xkbi->state.base_mods;
- }
- if ((!(flags&XkbSA_ISONoAffectGroup))&&(xkbi->state.base_group)) {
-/* 6/22/93 (ef) -- lock groups if group key is down first */
- }
- if (!(flags&XkbSA_ISONoAffectPtr)) {
-/* 6/22/93 (ef) -- lock mouse buttons if they're down */
- }
- }
- else if (filter->keycode==keycode) {
- CARD8 flags= filter->upAction.iso.flags;
-
- if (flags&XkbSA_ISODfltIsGroup) {
- xkbi->groupChange = -XkbSAGroup(&filter->upAction.iso);
- xkbi->clearMods = 0;
- if (filter->priv==ISO_KEY_DOWN)
- xkbi->state.locked_group+= XkbSAGroup(&filter->upAction.iso);
- }
- else {
- xkbi->clearMods= filter->upAction.iso.mask;
- xkbi->groupChange= 0;
- if (filter->priv==ISO_KEY_DOWN)
- xkbi->state.locked_mods^= filter->upAction.iso.mask;
- }
- filter->active = 0;
- }
- else if (pAction) {
- CARD8 flags= filter->upAction.iso.flags;
-
- switch (pAction->type) {
- case XkbSA_SetMods: case XkbSA_LatchMods:
- if (!(flags&XkbSA_ISONoAffectMods)) {
- pAction->type= XkbSA_LockMods;
- filter->priv= NO_ISO_LOCK;
- }
- break;
- case XkbSA_SetGroup: case XkbSA_LatchGroup:
- if (!(flags&XkbSA_ISONoAffectGroup)) {
- pAction->type= XkbSA_LockGroup;
- filter->priv= NO_ISO_LOCK;
- }
- break;
- case XkbSA_PtrBtn:
- if (!(flags&XkbSA_ISONoAffectPtr)) {
- pAction->type= XkbSA_LockPtrBtn;
- filter->priv= NO_ISO_LOCK;
- }
- break;
- case XkbSA_SetControls:
- if (!(flags&XkbSA_ISONoAffectCtrls)) {
- pAction->type= XkbSA_LockControls;
- filter->priv= NO_ISO_LOCK;
- }
- break;
- }
- }
- return 1;
-}
-
-
-static CARD32
-_XkbPtrAccelExpire(OsTimerPtr timer,CARD32 now,pointer arg)
-{
-XkbSrvInfoPtr xkbi= (XkbSrvInfoPtr)arg;
-XkbControlsPtr ctrls= xkbi->desc->ctrls;
-int dx,dy;
-
- if (xkbi->mouseKey==0)
- return 0;
-
- if (xkbi->mouseKeysAccel) {
- if ((xkbi->mouseKeysCounter)<ctrls->mk_time_to_max) {
- double step;
- xkbi->mouseKeysCounter++;
- step= xkbi->mouseKeysCurveFactor*
- pow((double)xkbi->mouseKeysCounter,xkbi->mouseKeysCurve);
- if (xkbi->mouseKeysDX<0)
- dx= floor( ((double)xkbi->mouseKeysDX)*step );
- else dx= ceil( ((double)xkbi->mouseKeysDX)*step );
- if (xkbi->mouseKeysDY<0)
- dy= floor( ((double)xkbi->mouseKeysDY)*step );
- else dy= ceil( ((double)xkbi->mouseKeysDY)*step );
- }
- else {
- dx= xkbi->mouseKeysDX*ctrls->mk_max_speed;
- dy= xkbi->mouseKeysDY*ctrls->mk_max_speed;
- }
- if (xkbi->mouseKeysFlags&XkbSA_MoveAbsoluteX)
- dx= xkbi->mouseKeysDX;
- if (xkbi->mouseKeysFlags&XkbSA_MoveAbsoluteY)
- dy= xkbi->mouseKeysDY;
- }
- else {
- dx= xkbi->mouseKeysDX;
- dy= xkbi->mouseKeysDY;
- }
- XkbFakePointerMotion(xkbi->device, xkbi->mouseKeysFlags,dx,dy);
- return xkbi->desc->ctrls->mk_interval;
-}
-
-static int
-_XkbFilterPointerMove( XkbSrvInfoPtr xkbi,
- XkbFilterPtr filter,
- unsigned keycode,
- XkbAction * pAction)
-{
-int x,y;
-Bool accel;
-
- if (filter->keycode==0) { /* initial press */
- filter->keycode = keycode;
- filter->active = 1;
- filter->filterOthers = 0;
- filter->priv=0;
- filter->filter = _XkbFilterPointerMove;
- filter->upAction= *pAction;
- xkbi->mouseKeysCounter= 0;
- xkbi->mouseKey= keycode;
- accel= ((pAction->ptr.flags&XkbSA_NoAcceleration)==0);
- x= XkbPtrActionX(&pAction->ptr);
- y= XkbPtrActionY(&pAction->ptr);
- XkbFakePointerMotion(xkbi->device, pAction->ptr.flags,x,y);
- AccessXCancelRepeatKey(xkbi,keycode);
- xkbi->mouseKeysAccel= accel&&
- (xkbi->desc->ctrls->enabled_ctrls&XkbMouseKeysAccelMask);
- xkbi->mouseKeysFlags= pAction->ptr.flags;
- xkbi->mouseKeysDX= XkbPtrActionX(&pAction->ptr);
- xkbi->mouseKeysDY= XkbPtrActionY(&pAction->ptr);
- xkbi->mouseKeyTimer= TimerSet(xkbi->mouseKeyTimer, 0,
- xkbi->desc->ctrls->mk_delay,
- _XkbPtrAccelExpire,(pointer)xkbi);
- }
- else if (filter->keycode==keycode) {
- filter->active = 0;
- if (xkbi->mouseKey==keycode) {
- xkbi->mouseKey= 0;
- xkbi->mouseKeyTimer= TimerSet(xkbi->mouseKeyTimer, 0, 0,
- NULL, NULL);
- }
- }
- return 0;
-}
-
-static int
-_XkbFilterPointerBtn( XkbSrvInfoPtr xkbi,
- XkbFilterPtr filter,
- unsigned keycode,
- XkbAction * pAction)
-{
- if (filter->keycode==0) { /* initial press */
- int button= pAction->btn.button;
-
- if (button==XkbSA_UseDfltButton)
- button = xkbi->desc->ctrls->mk_dflt_btn;
-
- filter->keycode = keycode;
- filter->active = 1;
- filter->filterOthers = 0;
- filter->priv=0;
- filter->filter = _XkbFilterPointerBtn;
- filter->upAction= *pAction;
- filter->upAction.btn.button= button;
- switch (pAction->type) {
- case XkbSA_LockPtrBtn:
- if (((xkbi->lockedPtrButtons&(1<<button))==0)&&
- ((pAction->btn.flags&XkbSA_LockNoLock)==0)) {
- xkbi->lockedPtrButtons|= (1<<button);
- AccessXCancelRepeatKey(xkbi,keycode);
- XkbFakeDeviceButton(xkbi->device, 1, button);
- filter->upAction.type= XkbSA_NoAction;
- }
- break;
- case XkbSA_PtrBtn:
- {
- register int i,nClicks;
- AccessXCancelRepeatKey(xkbi,keycode);
- if (pAction->btn.count>0) {
- nClicks= pAction->btn.count;
- for (i=0;i<nClicks;i++) {
- XkbFakeDeviceButton(xkbi->device, 1, button);
- XkbFakeDeviceButton(xkbi->device, 0, button);
- }
- filter->upAction.type= XkbSA_NoAction;
- }
- else XkbFakeDeviceButton(xkbi->device, 1, button);
- }
- break;
- case XkbSA_SetPtrDflt:
- {
- XkbControlsPtr ctrls= xkbi->desc->ctrls;
- XkbControlsRec old;
- xkbControlsNotify cn;
-
- old= *ctrls;
- AccessXCancelRepeatKey(xkbi,keycode);
- switch (pAction->dflt.affect) {
- case XkbSA_AffectDfltBtn:
- if (pAction->dflt.flags&XkbSA_DfltBtnAbsolute)
- ctrls->mk_dflt_btn=
- XkbSAPtrDfltValue(&pAction->dflt);
- else {
- ctrls->mk_dflt_btn+=
- XkbSAPtrDfltValue(&pAction->dflt);
- if (ctrls->mk_dflt_btn>5)
- ctrls->mk_dflt_btn= 5;
- else if (ctrls->mk_dflt_btn<1)
- ctrls->mk_dflt_btn= 1;
- }
- break;
- default:
- ErrorF(
- "Attempt to change unknown pointer default (%d) ignored\n",
- pAction->dflt.affect);
- break;
- }
- if (XkbComputeControlsNotify(xkbi->device,
- &old,xkbi->desc->ctrls,
- &cn,FALSE)) {
- cn.keycode = keycode;
- /* XXX: what about DeviceKeyPress? */
- cn.eventType = KeyPress;
- cn.requestMajor = 0;
- cn.requestMinor = 0;
- XkbSendControlsNotify(xkbi->device,&cn);
- }
- }
- break;
- }
- }
- else if (filter->keycode==keycode) {
- int button= filter->upAction.btn.button;
-
- switch (filter->upAction.type) {
- case XkbSA_LockPtrBtn:
- if (((filter->upAction.btn.flags&XkbSA_LockNoUnlock)!=0)||
- ((xkbi->lockedPtrButtons&(1<<button))==0)) {
- break;
- }
- xkbi->lockedPtrButtons&= ~(1<<button);
-
- if (IsMaster(xkbi->device))
- {
- XkbMergeLockedPtrBtns(xkbi->device);
- /* One SD still has lock set, don't post event */
- if ((xkbi->lockedPtrButtons & (1 << button)) != 0)
- break;
- }
-
- /* fallthrough */
- case XkbSA_PtrBtn:
- XkbFakeDeviceButton(xkbi->device, 0, button);
- break;
- }
- filter->active = 0;
- }
- return 0;
-}
-
-static int
-_XkbFilterControls( XkbSrvInfoPtr xkbi,
- XkbFilterPtr filter,
- unsigned keycode,
- XkbAction * pAction)
-{
-XkbControlsRec old;
-XkbControlsPtr ctrls;
-DeviceIntPtr kbd;
-unsigned int change;
-XkbEventCauseRec cause;
-
- kbd= xkbi->device;
- ctrls= xkbi->desc->ctrls;
- old= *ctrls;
- if (filter->keycode==0) { /* initial press */
- filter->keycode = keycode;
- filter->active = 1;
- filter->filterOthers = 0;
- change= XkbActionCtrls(&pAction->ctrls);
- filter->priv = change;
- filter->filter = _XkbFilterControls;
- filter->upAction = *pAction;
-
- if (pAction->type==XkbSA_LockControls) {
- filter->priv= (ctrls->enabled_ctrls&change);
- change&= ~ctrls->enabled_ctrls;
- }
-
- if (change) {
- xkbControlsNotify cn;
- XkbSrvLedInfoPtr sli;
-
- ctrls->enabled_ctrls|= change;
- if (XkbComputeControlsNotify(kbd,&old,ctrls,&cn,FALSE)) {
- cn.keycode = keycode;
- /* XXX: what about DeviceKeyPress? */
- cn.eventType = KeyPress;
- cn.requestMajor = 0;
- cn.requestMinor = 0;
- XkbSendControlsNotify(kbd,&cn);
- }
-
- XkbSetCauseKey(&cause,keycode,KeyPress);
-
- /* If sticky keys were disabled, clear all locks and latches */
- if ((old.enabled_ctrls&XkbStickyKeysMask)&&
- (!(ctrls->enabled_ctrls&XkbStickyKeysMask))) {
- XkbClearAllLatchesAndLocks(kbd,xkbi,FALSE,&cause);
- }
- sli= XkbFindSrvLedInfo(kbd,XkbDfltXIClass,XkbDfltXIId,0);
- XkbUpdateIndicators(kbd,sli->usesControls,TRUE,NULL,&cause);
- if (XkbAX_NeedFeedback(ctrls,XkbAX_FeatureFBMask))
- XkbDDXAccessXBeep(kbd,_BEEP_FEATURE_ON,change);
- }
- }
- else if (filter->keycode==keycode) {
- change= filter->priv;
- if (change) {
- xkbControlsNotify cn;
- XkbSrvLedInfoPtr sli;
-
- ctrls->enabled_ctrls&= ~change;
- if (XkbComputeControlsNotify(kbd,&old,ctrls,&cn,FALSE)) {
- cn.keycode = keycode;
- cn.eventType = KeyRelease;
- cn.requestMajor = 0;
- cn.requestMinor = 0;
- XkbSendControlsNotify(kbd,&cn);
- }
-
- XkbSetCauseKey(&cause,keycode,KeyRelease);
- /* If sticky keys were disabled, clear all locks and latches */
- if ((old.enabled_ctrls&XkbStickyKeysMask)&&
- (!(ctrls->enabled_ctrls&XkbStickyKeysMask))) {
- XkbClearAllLatchesAndLocks(kbd,xkbi,FALSE,&cause);
- }
- sli= XkbFindSrvLedInfo(kbd,XkbDfltXIClass,XkbDfltXIId,0);
- XkbUpdateIndicators(kbd,sli->usesControls,TRUE,NULL,&cause);
- if (XkbAX_NeedFeedback(ctrls,XkbAX_FeatureFBMask))
- XkbDDXAccessXBeep(kbd,_BEEP_FEATURE_OFF,change);
- }
- filter->keycode= 0;
- filter->active= 0;
- }
- return 1;
-}
-
-static int
-_XkbFilterActionMessage(XkbSrvInfoPtr xkbi,
- XkbFilterPtr filter,
- unsigned keycode,
- XkbAction * pAction)
-{
-XkbMessageAction * pMsg;
-DeviceIntPtr kbd;
-
- kbd= xkbi->device;
- if (filter->keycode==0) { /* initial press */
- pMsg= &pAction->msg;
- if ((pMsg->flags&XkbSA_MessageOnRelease)||
- ((pMsg->flags&XkbSA_MessageGenKeyEvent)==0)) {
- filter->keycode = keycode;
- filter->active = 1;
- filter->filterOthers = 0;
- filter->priv = 0;
- filter->filter = _XkbFilterActionMessage;
- filter->upAction = *pAction;
- }
- if (pMsg->flags&XkbSA_MessageOnPress) {
- xkbActionMessage msg;
-
- msg.keycode= keycode;
- msg.press= 1;
- msg.keyEventFollows=((pMsg->flags&XkbSA_MessageGenKeyEvent)!=0);
- memcpy((char *)msg.message,
- (char *)pMsg->message,XkbActionMessageLength);
- XkbSendActionMessage(kbd,&msg);
- }
- return ((pAction->msg.flags&XkbSA_MessageGenKeyEvent)!=0);
- }
- else if (filter->keycode==keycode) {
- pMsg= &filter->upAction.msg;
- if (pMsg->flags&XkbSA_MessageOnRelease) {
- xkbActionMessage msg;
-
- msg.keycode= keycode;
- msg.press= 0;
- msg.keyEventFollows=((pMsg->flags&XkbSA_MessageGenKeyEvent)!=0);
- memcpy((char *)msg.message,(char *)pMsg->message,
- XkbActionMessageLength);
- XkbSendActionMessage(kbd,&msg);
- }
- filter->keycode= 0;
- filter->active= 0;
- return ((pMsg->flags&XkbSA_MessageGenKeyEvent)!=0);
- }
- return 0;
-}
-
-static int
-_XkbFilterRedirectKey( XkbSrvInfoPtr xkbi,
- XkbFilterPtr filter,
- unsigned keycode,
- XkbAction * pAction)
-{
-DeviceEvent ev;
-int x,y;
-XkbStateRec old;
-unsigned mods,mask;
-xkbDeviceInfoPtr xkbPrivPtr = XKBDEVICEINFO(xkbi->device);
-ProcessInputProc backupproc;
-
- /* never actually used uninitialised, but gcc isn't smart enough
- * to work that out. */
- memset(&old, 0, sizeof(old));
- memset(&ev, 0, sizeof(ev));
-
- if ((filter->keycode!=0)&&(filter->keycode!=keycode))
- return 1;
-
- GetSpritePosition(xkbi->device, &x,&y);
- ev.header = ET_Internal;
- ev.length = sizeof(DeviceEvent);
- ev.time = GetTimeInMillis();
- ev.root_x = x;
- ev.root_y = y;
-
- if (filter->keycode==0) { /* initial press */
- if ((pAction->redirect.new_key<xkbi->desc->min_key_code)||
- (pAction->redirect.new_key>xkbi->desc->max_key_code)) {
- return 1;
- }
- filter->keycode = keycode;
- filter->active = 1;
- filter->filterOthers = 0;
- filter->priv = 0;
- filter->filter = _XkbFilterRedirectKey;
- filter->upAction = *pAction;
-
- ev.type = ET_KeyPress;
- ev.detail.key = pAction->redirect.new_key;
-
- mask= XkbSARedirectVModsMask(&pAction->redirect);
- mods= XkbSARedirectVMods(&pAction->redirect);
- if (mask) XkbVirtualModsToReal(xkbi->desc,mask,&mask);
- if (mods) XkbVirtualModsToReal(xkbi->desc,mods,&mods);
- mask|= pAction->redirect.mods_mask;
- mods|= pAction->redirect.mods;
-
- if ( mask || mods ) {
- old= xkbi->state;
- xkbi->state.base_mods&= ~mask;
- xkbi->state.base_mods|= (mods&mask);
- xkbi->state.latched_mods&= ~mask;
- xkbi->state.latched_mods|= (mods&mask);
- xkbi->state.locked_mods&= ~mask;
- xkbi->state.locked_mods|= (mods&mask);
- XkbComputeDerivedState(xkbi);
- }
-
- UNWRAP_PROCESS_INPUT_PROC(xkbi->device,xkbPrivPtr, backupproc);
- xkbi->device->public.processInputProc((InternalEvent*)&ev, xkbi->device);
- COND_WRAP_PROCESS_INPUT_PROC(xkbi->device, xkbPrivPtr,
- backupproc,xkbUnwrapProc);
-
- if ( mask || mods )
- xkbi->state= old;
- }
- else if (filter->keycode==keycode) {
-
- ev.type = ET_KeyRelease;
- ev.detail.key = filter->upAction.redirect.new_key;
-
- mask= XkbSARedirectVModsMask(&filter->upAction.redirect);
- mods= XkbSARedirectVMods(&filter->upAction.redirect);
- if (mask) XkbVirtualModsToReal(xkbi->desc,mask,&mask);
- if (mods) XkbVirtualModsToReal(xkbi->desc,mods,&mods);
- mask|= filter->upAction.redirect.mods_mask;
- mods|= filter->upAction.redirect.mods;
-
- if ( mask || mods ) {
- old= xkbi->state;
- xkbi->state.base_mods&= ~mask;
- xkbi->state.base_mods|= (mods&mask);
- xkbi->state.latched_mods&= ~mask;
- xkbi->state.latched_mods|= (mods&mask);
- xkbi->state.locked_mods&= ~mask;
- xkbi->state.locked_mods|= (mods&mask);
- XkbComputeDerivedState(xkbi);
- }
-
- UNWRAP_PROCESS_INPUT_PROC(xkbi->device,xkbPrivPtr, backupproc);
- xkbi->device->public.processInputProc((InternalEvent*)&ev, xkbi->device);
- COND_WRAP_PROCESS_INPUT_PROC(xkbi->device, xkbPrivPtr,
- backupproc,xkbUnwrapProc);
-
- if ( mask || mods )
- xkbi->state= old;
-
- filter->keycode= 0;
- filter->active= 0;
- }
- return 0;
-}
-
-static int
-_XkbFilterSwitchScreen( XkbSrvInfoPtr xkbi,
- XkbFilterPtr filter,
- unsigned keycode,
- XkbAction * pAction)
-{
- DeviceIntPtr dev = xkbi->device;
- if (dev == inputInfo.keyboard)
- return 0;
-
- if (filter->keycode==0) { /* initial press */
- filter->keycode = keycode;
- filter->active = 1;
- filter->filterOthers = 0;
- filter->filter = _XkbFilterSwitchScreen;
- AccessXCancelRepeatKey(xkbi, keycode);
- XkbDDXSwitchScreen(dev,keycode,pAction);
- return 0;
- }
- else if (filter->keycode==keycode) {
- filter->active= 0;
- return 0;
- }
- return 1;
-}
-
-static int
-_XkbFilterXF86Private( XkbSrvInfoPtr xkbi,
- XkbFilterPtr filter,
- unsigned keycode,
- XkbAction * pAction)
-{
- DeviceIntPtr dev = xkbi->device;
- if (dev == inputInfo.keyboard)
- return 0;
-
- if (filter->keycode==0) { /* initial press */
- filter->keycode = keycode;
- filter->active = 1;
- filter->filterOthers = 0;
- filter->filter = _XkbFilterXF86Private;
- XkbDDXPrivate(dev,keycode,pAction);
- return 0;
- }
- else if (filter->keycode==keycode) {
- filter->active= 0;
- return 0;
- }
- return 1;
-}
-
-
-static int
-_XkbFilterDeviceBtn( XkbSrvInfoPtr xkbi,
- XkbFilterPtr filter,
- unsigned keycode,
- XkbAction * pAction)
-{
-DeviceIntPtr dev;
-int button;
-
- if (xkbi->device == inputInfo.keyboard)
- return 0;
-
- if (filter->keycode==0) { /* initial press */
- _XkbLookupButtonDevice(&dev, pAction->devbtn.device, serverClient,
- DixUnknownAccess, &button);
- if (!dev || !dev->public.on)
- return 1;
-
- button= pAction->devbtn.button;
- if ((button<1)||(button>dev->button->numButtons))
- return 1;
-
- filter->keycode = keycode;
- filter->active = 1;
- filter->filterOthers = 0;
- filter->priv=0;
- filter->filter = _XkbFilterDeviceBtn;
- filter->upAction= *pAction;
- switch (pAction->type) {
- case XkbSA_LockDeviceBtn:
- if ((pAction->devbtn.flags&XkbSA_LockNoLock)||
- BitIsOn(dev->button->down, button))
- return 0;
- XkbFakeDeviceButton(dev,TRUE,button);
- filter->upAction.type= XkbSA_NoAction;
- break;
- case XkbSA_DeviceBtn:
- if (pAction->devbtn.count>0) {
- int nClicks,i;
- nClicks= pAction->btn.count;
- for (i=0;i<nClicks;i++) {
- XkbFakeDeviceButton(dev,TRUE,button);
- XkbFakeDeviceButton(dev,FALSE,button);
- }
- filter->upAction.type= XkbSA_NoAction;
- }
- else XkbFakeDeviceButton(dev,TRUE,button);
- break;
- }
- }
- else if (filter->keycode==keycode) {
- int button;
-
- filter->active= 0;
- _XkbLookupButtonDevice(&dev, filter->upAction.devbtn.device,
- serverClient, DixUnknownAccess, &button);
- if (!dev || !dev->public.on)
- return 1;
-
- button= filter->upAction.btn.button;
- switch (filter->upAction.type) {
- case XkbSA_LockDeviceBtn:
- if ((filter->upAction.devbtn.flags&XkbSA_LockNoUnlock)||
- !BitIsOn(dev->button->down, button))
- return 0;
- XkbFakeDeviceButton(dev,FALSE,button);
- break;
- case XkbSA_DeviceBtn:
- XkbFakeDeviceButton(dev,FALSE,button);
- break;
- }
- filter->active = 0;
- }
- return 0;
-}
-
-static XkbFilterPtr
-_XkbNextFreeFilter(
- XkbSrvInfoPtr xkbi
-)
-{
-register int i;
-
- if (xkbi->szFilters==0) {
- xkbi->szFilters = 4;
- xkbi->filters = calloc(xkbi->szFilters, sizeof(XkbFilterRec));
- /* 6/21/93 (ef) -- XXX! deal with allocation failure */
- }
- for (i=0;i<xkbi->szFilters;i++) {
- if (!xkbi->filters[i].active) {
- xkbi->filters[i].keycode = 0;
- return &xkbi->filters[i];
- }
- }
- xkbi->szFilters*=2;
- xkbi->filters= realloc(xkbi->filters,
- xkbi->szFilters * sizeof(XkbFilterRec));
- /* 6/21/93 (ef) -- XXX! deal with allocation failure */
- memset(&xkbi->filters[xkbi->szFilters/2], 0,
- (xkbi->szFilters/2)*sizeof(XkbFilterRec));
- return &xkbi->filters[xkbi->szFilters/2];
-}
-
-static int
-_XkbApplyFilters(XkbSrvInfoPtr xkbi,unsigned kc,XkbAction *pAction)
-{
-register int i,send;
-
- send= 1;
- for (i=0;i<xkbi->szFilters;i++) {
- if ((xkbi->filters[i].active)&&(xkbi->filters[i].filter))
- send= ((*xkbi->filters[i].filter)(xkbi,&xkbi->filters[i],kc,pAction)
- && send);
- }
- return send;
-}
-
-void
-XkbHandleActions(DeviceIntPtr dev, DeviceIntPtr kbd, DeviceEvent* event)
-{
-int key,bit,i;
-XkbSrvInfoPtr xkbi;
-KeyClassPtr keyc;
-int changed,sendEvent;
-Bool genStateNotify;
-XkbAction act;
-XkbFilterPtr filter;
-Bool keyEvent;
-Bool pressEvent;
-ProcessInputProc backupproc;
-
-xkbDeviceInfoPtr xkbPrivPtr = XKBDEVICEINFO(dev);
-
- keyc= kbd->key;
- xkbi= keyc->xkbInfo;
- key= event->detail.key;
- /* The state may change, so if we're not in the middle of sending a state
- * notify, prepare for it */
- if ((xkbi->flags&_XkbStateNotifyInProgress)==0) {
- xkbi->prev_state = xkbi->state;
- xkbi->flags|= _XkbStateNotifyInProgress;
- genStateNotify= TRUE;
- }
- else genStateNotify= FALSE;
-
- xkbi->clearMods = xkbi->setMods = 0;
- xkbi->groupChange = 0;
-
- sendEvent = 1;
- keyEvent= ((event->type == ET_KeyPress) || (event->type == ET_KeyRelease));
- pressEvent= ((event->type == ET_KeyPress)|| (event->type == ET_ButtonPress));
-
- if (pressEvent) {
- if (keyEvent)
- act = XkbGetKeyAction(xkbi,&xkbi->state,key);
- else {
- act = XkbGetButtonAction(kbd,dev,key);
- key|= BTN_ACT_FLAG;
- }
- sendEvent = _XkbApplyFilters(xkbi,key,&act);
- if (sendEvent) {
- switch (act.type) {
- case XkbSA_SetMods:
- case XkbSA_SetGroup:
- filter = _XkbNextFreeFilter(xkbi);
- sendEvent = _XkbFilterSetState(xkbi,filter,key,&act);
- break;
- case XkbSA_LatchMods:
- case XkbSA_LatchGroup:
- filter = _XkbNextFreeFilter(xkbi);
- sendEvent=_XkbFilterLatchState(xkbi,filter,key,&act);
- break;
- case XkbSA_LockMods:
- case XkbSA_LockGroup:
- filter = _XkbNextFreeFilter(xkbi);
- sendEvent=_XkbFilterLockState(xkbi,filter,key,&act);
- break;
- case XkbSA_ISOLock:
- filter = _XkbNextFreeFilter(xkbi);
- sendEvent=_XkbFilterISOLock(xkbi,filter,key,&act);
- break;
- case XkbSA_MovePtr:
- filter = _XkbNextFreeFilter(xkbi);
- sendEvent= _XkbFilterPointerMove(xkbi,filter,key,&act);
- break;
- case XkbSA_PtrBtn:
- case XkbSA_LockPtrBtn:
- case XkbSA_SetPtrDflt:
- filter = _XkbNextFreeFilter(xkbi);
- sendEvent= _XkbFilterPointerBtn(xkbi,filter,key,&act);
- break;
- case XkbSA_Terminate:
- sendEvent= XkbDDXTerminateServer(dev,key,&act);
- break;
- case XkbSA_SwitchScreen:
- filter = _XkbNextFreeFilter(xkbi);
- sendEvent=_XkbFilterSwitchScreen(xkbi,filter,key,&act);
- break;
- case XkbSA_SetControls:
- case XkbSA_LockControls:
- filter = _XkbNextFreeFilter(xkbi);
- sendEvent=_XkbFilterControls(xkbi,filter,key,&act);
- break;
- case XkbSA_ActionMessage:
- filter = _XkbNextFreeFilter(xkbi);
- sendEvent=_XkbFilterActionMessage(xkbi,filter,key,&act);
- break;
- case XkbSA_RedirectKey:
- filter = _XkbNextFreeFilter(xkbi);
- sendEvent= _XkbFilterRedirectKey(xkbi,filter,key,&act);
- break;
- case XkbSA_DeviceBtn:
- case XkbSA_LockDeviceBtn:
- filter = _XkbNextFreeFilter(xkbi);
- sendEvent= _XkbFilterDeviceBtn(xkbi,filter,key,&act);
- break;
- case XkbSA_XFree86Private:
- filter = _XkbNextFreeFilter(xkbi);
- sendEvent= _XkbFilterXF86Private(xkbi,filter,key,&act);
- break;
- }
- }
- }
- else {
- if (!keyEvent)
- key|= BTN_ACT_FLAG;
- sendEvent = _XkbApplyFilters(xkbi,key,NULL);
- }
-
- if (xkbi->groupChange!=0)
- xkbi->state.base_group+= xkbi->groupChange;
- if (xkbi->setMods) {
- for (i=0,bit=1; xkbi->setMods; i++,bit<<=1 ) {
- if (xkbi->setMods&bit) {
- keyc->modifierKeyCount[i]++;
- xkbi->state.base_mods|= bit;
- xkbi->setMods&= ~bit;
- }
- }
- }
- if (xkbi->clearMods) {
- for (i=0,bit=1; xkbi->clearMods; i++,bit<<=1 ) {
- if (xkbi->clearMods&bit) {
- keyc->modifierKeyCount[i]--;
- if (keyc->modifierKeyCount[i]<=0) {
- xkbi->state.base_mods&= ~bit;
- keyc->modifierKeyCount[i] = 0;
- }
- xkbi->clearMods&= ~bit;
- }
- }
- }
-
- if (sendEvent) {
- DeviceIntPtr tmpdev;
- if (keyEvent)
- tmpdev = dev;
- else
- tmpdev = GetPairedDevice(dev);
-
- UNWRAP_PROCESS_INPUT_PROC(tmpdev,xkbPrivPtr, backupproc);
- dev->public.processInputProc((InternalEvent*)event, tmpdev);
- COND_WRAP_PROCESS_INPUT_PROC(tmpdev, xkbPrivPtr,
- backupproc,xkbUnwrapProc);
- }
- else if (keyEvent) {
- FixKeyState(event, dev);
- }
-
- XkbComputeDerivedState(xkbi);
- changed = XkbStateChangedFlags(&xkbi->prev_state,&xkbi->state);
- if (genStateNotify) {
- if (changed) {
- xkbStateNotify sn;
- sn.keycode= key;
- sn.eventType= event->type;
- sn.requestMajor = sn.requestMinor = 0;
- sn.changed= changed;
- XkbSendStateNotify(dev,&sn);
- }
- xkbi->flags&= ~_XkbStateNotifyInProgress;
- }
- changed= XkbIndicatorsToUpdate(dev,changed,FALSE);
- if (changed) {
- XkbEventCauseRec cause;
- XkbSetCauseKey(&cause, key, event->type);
- XkbUpdateIndicators(dev,changed,FALSE,NULL,&cause);
- }
- return;
-}
-
-int
-XkbLatchModifiers(DeviceIntPtr pXDev,CARD8 mask,CARD8 latches)
-{
-XkbSrvInfoPtr xkbi;
-XkbFilterPtr filter;
-XkbAction act;
-unsigned clear;
-
- if ( pXDev && pXDev->key && pXDev->key->xkbInfo ) {
- xkbi = pXDev->key->xkbInfo;
- clear= (mask&(~latches));
- xkbi->state.latched_mods&= ~clear;
- /* Clear any pending latch to locks.
- */
- act.type = XkbSA_NoAction;
- _XkbApplyFilters(xkbi,SYNTHETIC_KEYCODE,&act);
- act.type = XkbSA_LatchMods;
- act.mods.flags = 0;
- act.mods.mask = mask&latches;
- filter = _XkbNextFreeFilter(xkbi);
- _XkbFilterLatchState(xkbi,filter,SYNTHETIC_KEYCODE,&act);
- _XkbFilterLatchState(xkbi,filter,SYNTHETIC_KEYCODE,(XkbAction *)NULL);
- return Success;
- }
- return BadValue;
-}
-
-int
-XkbLatchGroup(DeviceIntPtr pXDev,int group)
-{
-XkbSrvInfoPtr xkbi;
-XkbFilterPtr filter;
-XkbAction act;
-
- if ( pXDev && pXDev->key && pXDev->key->xkbInfo ) {
- xkbi = pXDev->key->xkbInfo;
- act.type = XkbSA_LatchGroup;
- act.group.flags = 0;
- XkbSASetGroup(&act.group,group);
- filter = _XkbNextFreeFilter(xkbi);
- _XkbFilterLatchState(xkbi,filter,SYNTHETIC_KEYCODE,&act);
- _XkbFilterLatchState(xkbi,filter,SYNTHETIC_KEYCODE,(XkbAction *)NULL);
- return Success;
- }
- return BadValue;
-}
-
-/***====================================================================***/
-
-void
-XkbClearAllLatchesAndLocks( DeviceIntPtr dev,
- XkbSrvInfoPtr xkbi,
- Bool genEv,
- XkbEventCausePtr cause)
-{
-XkbStateRec os;
-xkbStateNotify sn;
-
- sn.changed= 0;
- os= xkbi->state;
- if (os.latched_mods) { /* clear all latches */
- XkbLatchModifiers(dev,~0,0);
- sn.changed|= XkbModifierLatchMask;
- }
- if (os.latched_group) {
- XkbLatchGroup(dev,0);
- sn.changed|= XkbGroupLatchMask;
- }
- if (os.locked_mods) {
- xkbi->state.locked_mods= 0;
- sn.changed|= XkbModifierLockMask;
- }
- if (os.locked_group) {
- xkbi->state.locked_group= 0;
- sn.changed|= XkbGroupLockMask;
- }
- if ( genEv && sn.changed) {
- CARD32 changed;
-
- XkbComputeDerivedState(xkbi);
- sn.keycode= cause->kc;
- sn.eventType= cause->event;
- sn.requestMajor= cause->mjr;
- sn.requestMinor= cause->mnr;
- sn.changed= XkbStateChangedFlags(&os,&xkbi->state);
- XkbSendStateNotify(dev,&sn);
- changed= XkbIndicatorsToUpdate(dev,sn.changed,FALSE);
- if (changed) {
- XkbUpdateIndicators(dev,changed,TRUE,NULL,cause);
- }
- }
- return;
-}
-
-/*
- * The event is injected into the event processing, not the EQ. Thus,
- * ensure that we restore the master after the event sequence to the
- * original set of classes. Otherwise, the master remains on the XTEST
- * classes and drops events that don't fit into the XTEST layout (e.g.
- * events with more than 2 valuators).
- *
- * FIXME: EQ injection in the processing stage is not designed for, so this
- * is a rather awkward hack. The event list returned by GetPointerEvents()
- * and friends is always prefixed with a DCE if the last _posted_ device was
- * different. For normal events, this sequence then resets the master during
- * the processing stage. Since we inject the PointerKey events in the
- * processing stage though, we need to manually reset to restore the
- * previous order, because the events already in the EQ must be sent for the
- * right device.
- * So we post-fix the event list we get from GPE with a DCE back to the
- * previous slave device.
- *
- * First one on drinking island wins!
- */
-static void
-InjectPointerKeyEvents(DeviceIntPtr dev, int type, int button, int flags, ValuatorMask *mask)
-{
- ScreenPtr pScreen;
- EventListPtr events;
- int nevents, i;
- DeviceIntPtr ptr, mpointer, lastSlave = NULL;
- Bool saveWait;
-
- if (IsMaster(dev)) {
- mpointer = GetMaster(dev, MASTER_POINTER);
- lastSlave = mpointer->u.lastSlave;
- ptr = GetXTestDevice(mpointer);
- } else if (!dev->u.master)
- ptr = dev;
- else
- return;
-
-
- events = InitEventList(GetMaximumEventsNum() + 1);
- OsBlockSignals();
- pScreen = miPointerGetScreen(ptr);
- saveWait = miPointerSetWaitForUpdate(pScreen, FALSE);
- nevents = GetPointerEvents(events, ptr, type, button, flags, mask);
- if (IsMaster(dev) && (lastSlave && lastSlave != ptr))
- UpdateFromMaster(&events[nevents], lastSlave, DEVCHANGE_POINTER_EVENT, &nevents);
- miPointerSetWaitForUpdate(pScreen, saveWait);
- OsReleaseSignals();
-
- for (i = 0; i < nevents; i++)
- mieqProcessDeviceEvent(ptr, (InternalEvent*)events[i].event, NULL);
-
- FreeEventList(events, GetMaximumEventsNum());
-
-}
-
-static void
-XkbFakePointerMotion(DeviceIntPtr dev, unsigned flags,int x,int y)
-{
- ValuatorMask mask;
- int gpe_flags = 0;
-
- /* ignore attached SDs */
- if (!IsMaster(dev) && GetMaster(dev, MASTER_POINTER) != NULL)
- return;
-
- if (flags & XkbSA_MoveAbsoluteX || flags & XkbSA_MoveAbsoluteY)
- gpe_flags = POINTER_ABSOLUTE;
- else
- gpe_flags = POINTER_RELATIVE;
-
- valuator_mask_set_range(&mask, 0, 2, (int[]){x, y});
-
- InjectPointerKeyEvents(dev, MotionNotify, 0, gpe_flags, &mask);
-}
-
-void
-XkbFakeDeviceButton(DeviceIntPtr dev,Bool press,int button)
-{
- DeviceIntPtr ptr;
- int down;
-
- /* If dev is a slave device, and the SD is attached, do nothing. If we'd
- * post through the attached master pointer we'd get duplicate events.
- *
- * if dev is a master keyboard, post through the XTEST device
- *
- * if dev is a floating slave, post through the device itself.
- */
-
- if (IsMaster(dev)) {
- DeviceIntPtr mpointer = GetMaster(dev, MASTER_POINTER);
- ptr = GetXTestDevice(mpointer);
- } else if (!dev->u.master)
- ptr = dev;
- else
- return;
-
- down = button_is_down(ptr, button, BUTTON_PROCESSED);
- if (press == down)
- return;
-
- InjectPointerKeyEvents(dev, press ? ButtonPress : ButtonRelease,
- button, 0, NULL);
-}
+/************************************************************ +Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc. + +Permission 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 that both that copyright +notice and this permission notice appear in supporting +documentation, and that the name of Silicon Graphics not be +used in advertising or publicity pertaining to distribution +of the software without specific prior written permission. +Silicon Graphics makes no representation about the suitability +of this software for any purpose. It is provided "as is" +without any express or implied warranty. + +SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS +SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON +GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL +DAMAGES OR ANY 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 THIS SOFTWARE. + +********************************************************/ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include <stdio.h> +#include <math.h> +#include <X11/X.h> +#include <X11/Xproto.h> +#include <X11/keysym.h> +#include "misc.h" +#include "inputstr.h" +#include "exevents.h" +#include "eventstr.h" +#include <xkbsrv.h> +#include "xkb.h" +#include <ctype.h> +#include "mi.h" +#include "mipointer.h" +#include "inpututils.h" +#define EXTENSION_EVENT_BASE 64 + +DevPrivateKeyRec xkbDevicePrivateKeyRec; + +void XkbFakeDeviceButton(DeviceIntPtr dev,Bool press,int button); +static void XkbFakePointerMotion(DeviceIntPtr dev, unsigned flags,int x,int y); + +void +xkbUnwrapProc(DeviceIntPtr device, DeviceHandleProc proc, + pointer data) +{ + xkbDeviceInfoPtr xkbPrivPtr = XKBDEVICEINFO(device); + ProcessInputProc backupproc; + if(xkbPrivPtr->unwrapProc) + xkbPrivPtr->unwrapProc = NULL; + + UNWRAP_PROCESS_INPUT_PROC(device,xkbPrivPtr, backupproc); + proc(device,data); + COND_WRAP_PROCESS_INPUT_PROC(device,xkbPrivPtr, + backupproc,xkbUnwrapProc); +} + +Bool +XkbInitPrivates(void) +{ + return dixRegisterPrivateKey(&xkbDevicePrivateKeyRec, PRIVATE_DEVICE, 0); +} + +void +XkbSetExtension(DeviceIntPtr device, ProcessInputProc proc) +{ + xkbDeviceInfoPtr xkbPrivPtr; + + xkbPrivPtr = (xkbDeviceInfoPtr) calloc(1, sizeof(xkbDeviceInfoRec)); + if (!xkbPrivPtr) + return; + xkbPrivPtr->unwrapProc = NULL; + + dixSetPrivate(&device->devPrivates, xkbDevicePrivateKey, xkbPrivPtr); + WRAP_PROCESS_INPUT_PROC(device, xkbPrivPtr, proc, xkbUnwrapProc); +} + +/***====================================================================***/ + +static XkbAction +_FixUpAction(XkbDescPtr xkb,XkbAction *act) +{ +static XkbAction fake; + + if (XkbIsPtrAction(act)&&(!(xkb->ctrls->enabled_ctrls&XkbMouseKeysMask))) { + fake.type = XkbSA_NoAction; + return fake; + } + if (xkb->ctrls->enabled_ctrls&XkbStickyKeysMask) { + if (act->any.type==XkbSA_SetMods) { + fake.mods.type = XkbSA_LatchMods; + fake.mods.mask = act->mods.mask; + if (XkbAX_NeedOption(xkb->ctrls,XkbAX_LatchToLockMask)) + fake.mods.flags= XkbSA_ClearLocks|XkbSA_LatchToLock; + else fake.mods.flags= XkbSA_ClearLocks; + return fake; + } + if (act->any.type==XkbSA_SetGroup) { + fake.group.type = XkbSA_LatchGroup; + if (XkbAX_NeedOption(xkb->ctrls,XkbAX_LatchToLockMask)) + fake.group.flags= XkbSA_ClearLocks|XkbSA_LatchToLock; + else fake.group.flags= XkbSA_ClearLocks; + XkbSASetGroup(&fake.group,XkbSAGroup(&act->group)); + return fake; + } + } + return *act; +} + +static XkbAction +XkbGetKeyAction(XkbSrvInfoPtr xkbi,XkbStatePtr xkbState,CARD8 key) +{ +int effectiveGroup; +int col; +XkbDescPtr xkb; +XkbKeyTypePtr type; +XkbAction * pActs; +static XkbAction fake; + + xkb= xkbi->desc; + if (!XkbKeyHasActions(xkb,key) || !XkbKeycodeInRange(xkb,key)) { + fake.type = XkbSA_NoAction; + return fake; + } + pActs= XkbKeyActionsPtr(xkb,key); + col= 0; + + effectiveGroup = XkbGetEffectiveGroup(xkbi, xkbState, key); + if (effectiveGroup != XkbGroup1Index) + col += (effectiveGroup * XkbKeyGroupsWidth(xkb, key)); + + type= XkbKeyKeyType(xkb,key,effectiveGroup); + if (type->map!=NULL) { + register unsigned i,mods; + register XkbKTMapEntryPtr entry; + mods= xkbState->mods&type->mods.mask; + for (entry= type->map,i=0;i<type->map_count;i++,entry++) { + if ((entry->active)&&(entry->mods.mask==mods)) { + col+= entry->level; + break; + } + } + } + if (pActs[col].any.type==XkbSA_NoAction) + return pActs[col]; + fake= _FixUpAction(xkb,&pActs[col]); + return fake; +} + +static XkbAction +XkbGetButtonAction(DeviceIntPtr kbd,DeviceIntPtr dev,int button) +{ +XkbAction fake; + if ((dev->button)&&(dev->button->xkb_acts)) { + if (dev->button->xkb_acts[button-1].any.type!=XkbSA_NoAction) { + fake= _FixUpAction(kbd->key->xkbInfo->desc, + &dev->button->xkb_acts[button-1]); + return fake; + } + } + fake.any.type= XkbSA_NoAction; + return fake; +} + +/***====================================================================***/ + +#define SYNTHETIC_KEYCODE 1 +#define BTN_ACT_FLAG 0x100 + +static int +_XkbFilterSetState( XkbSrvInfoPtr xkbi, + XkbFilterPtr filter, + unsigned keycode, + XkbAction *pAction) +{ + if (filter->keycode==0) { /* initial press */ + filter->keycode = keycode; + filter->active = 1; + filter->filterOthers = ((pAction->mods.mask&XkbSA_ClearLocks)!=0); + filter->priv = 0; + filter->filter = _XkbFilterSetState; + if (pAction->type==XkbSA_SetMods) { + filter->upAction = *pAction; + xkbi->setMods= pAction->mods.mask; + } + else { + xkbi->groupChange = XkbSAGroup(&pAction->group); + if (pAction->group.flags&XkbSA_GroupAbsolute) + xkbi->groupChange-= xkbi->state.base_group; + filter->upAction= *pAction; + XkbSASetGroup(&filter->upAction.group,xkbi->groupChange); + } + } + else if (filter->keycode==keycode) { + if (filter->upAction.type==XkbSA_SetMods) { + xkbi->clearMods = filter->upAction.mods.mask; + if (filter->upAction.mods.flags&XkbSA_ClearLocks) { + xkbi->state.locked_mods&= ~filter->upAction.mods.mask; + } + } + else { + if (filter->upAction.group.flags&XkbSA_ClearLocks) { + xkbi->state.locked_group = 0; + } + xkbi->groupChange = -XkbSAGroup(&filter->upAction.group); + } + filter->active = 0; + } + else { + filter->upAction.mods.flags&= ~XkbSA_ClearLocks; + filter->filterOthers = 0; + } + return 1; +} + +#define LATCH_KEY_DOWN 1 +#define LATCH_PENDING 2 +#define NO_LATCH 3 + +static int +_XkbFilterLatchState( XkbSrvInfoPtr xkbi, + XkbFilterPtr filter, + unsigned keycode, + XkbAction * pAction) +{ + + if (filter->keycode==0) { /* initial press */ + filter->keycode = keycode; + filter->active = 1; + filter->filterOthers = 1; + filter->priv = LATCH_KEY_DOWN; + filter->filter = _XkbFilterLatchState; + if (pAction->type==XkbSA_LatchMods) { + filter->upAction = *pAction; + xkbi->setMods = pAction->mods.mask; + } + else { + xkbi->groupChange = XkbSAGroup(&pAction->group); + if (pAction->group.flags&XkbSA_GroupAbsolute) + xkbi->groupChange-= xkbi->state.base_group; + filter->upAction= *pAction; + XkbSASetGroup(&filter->upAction.group,xkbi->groupChange); + } + } + else if ( pAction && (filter->priv==LATCH_PENDING) ) { + if (((1<<pAction->type)&XkbSA_BreakLatch)!=0) { + filter->active = 0; + if (filter->upAction.type==XkbSA_LatchMods) + xkbi->state.latched_mods&= ~filter->upAction.mods.mask; + else xkbi->state.latched_group-=XkbSAGroup(&filter->upAction.group); + } + else if ((pAction->type==filter->upAction.type)&& + (pAction->mods.flags==filter->upAction.mods.flags)&& + (pAction->mods.mask==filter->upAction.mods.mask)) { + if (filter->upAction.mods.flags&XkbSA_LatchToLock) { + XkbControlsPtr ctrls= xkbi->desc->ctrls; + if (filter->upAction.type==XkbSA_LatchMods) + pAction->mods.type= XkbSA_LockMods; + else pAction->group.type= XkbSA_LockGroup; + if (XkbAX_NeedFeedback(ctrls,XkbAX_StickyKeysFBMask)&& + (ctrls->enabled_ctrls&XkbStickyKeysMask)) { + XkbDDXAccessXBeep(xkbi->device,_BEEP_STICKY_LOCK, + XkbStickyKeysMask); + } + } + else { + if (filter->upAction.type==XkbSA_LatchMods) + pAction->mods.type= XkbSA_SetMods; + else pAction->group.type= XkbSA_SetGroup; + } + if (filter->upAction.type==XkbSA_LatchMods) + xkbi->state.latched_mods&= ~filter->upAction.mods.mask; + else xkbi->state.latched_group-=XkbSAGroup(&filter->upAction.group); + filter->active = 0; + } + } + else if (filter->keycode==keycode) { /* release */ + XkbControlsPtr ctrls= xkbi->desc->ctrls; + int needBeep; + int beepType= _BEEP_NONE; + + needBeep= ((ctrls->enabled_ctrls&XkbStickyKeysMask)&& + XkbAX_NeedFeedback(ctrls,XkbAX_StickyKeysFBMask)); + if (filter->upAction.type==XkbSA_LatchMods) { + xkbi->clearMods = filter->upAction.mods.mask; + if ((filter->upAction.mods.flags&XkbSA_ClearLocks)&& + (xkbi->clearMods&xkbi->state.locked_mods)==xkbi->clearMods) { + xkbi->state.locked_mods&= ~xkbi->clearMods; + filter->priv= NO_LATCH; + beepType= _BEEP_STICKY_UNLOCK; + } + } + else { + xkbi->groupChange = -XkbSAGroup(&filter->upAction.group); + if ((filter->upAction.group.flags&XkbSA_ClearLocks)&& + (xkbi->state.locked_group)) { + xkbi->state.locked_group = 0; + filter->priv = NO_LATCH; + beepType= _BEEP_STICKY_UNLOCK; + } + } + if (filter->priv==NO_LATCH) { + filter->active= 0; + } + else { + filter->priv= LATCH_PENDING; + if (filter->upAction.type==XkbSA_LatchMods) { + xkbi->state.latched_mods |= filter->upAction.mods.mask; + needBeep = xkbi->state.latched_mods ? needBeep : 0; + xkbi->state.latched_mods |= filter->upAction.mods.mask; + } + else { + xkbi->state.latched_group+= XkbSAGroup(&filter->upAction.group); + } + if (needBeep && (beepType==_BEEP_NONE)) + beepType= _BEEP_STICKY_LATCH; + } + if (needBeep && (beepType!=_BEEP_NONE)) + XkbDDXAccessXBeep(xkbi->device,beepType,XkbStickyKeysMask); + } + else if (filter->priv==LATCH_KEY_DOWN) { + filter->priv= NO_LATCH; + filter->filterOthers = 0; + } + return 1; +} + +static int +_XkbFilterLockState( XkbSrvInfoPtr xkbi, + XkbFilterPtr filter, + unsigned keycode, + XkbAction * pAction) +{ + if (pAction&&(pAction->type==XkbSA_LockGroup)) { + if (pAction->group.flags&XkbSA_GroupAbsolute) + xkbi->state.locked_group= XkbSAGroup(&pAction->group); + else xkbi->state.locked_group+= XkbSAGroup(&pAction->group); + return 1; + } + if (filter->keycode==0) { /* initial press */ + filter->keycode = keycode; + filter->active = 1; + filter->filterOthers = 0; + filter->priv = 0; + filter->filter = _XkbFilterLockState; + filter->upAction = *pAction; + xkbi->state.locked_mods^= pAction->mods.mask; + xkbi->setMods = pAction->mods.mask; + } + else if (filter->keycode==keycode) { + filter->active = 0; + xkbi->clearMods = filter->upAction.mods.mask; + } + return 1; +} + +#define ISO_KEY_DOWN 0 +#define NO_ISO_LOCK 1 + +static int +_XkbFilterISOLock( XkbSrvInfoPtr xkbi, + XkbFilterPtr filter, + unsigned keycode, + XkbAction * pAction) +{ + + if (filter->keycode==0) { /* initial press */ + CARD8 flags= pAction->iso.flags; + + filter->keycode = keycode; + filter->active = 1; + filter->filterOthers = 1; + filter->priv = ISO_KEY_DOWN; + filter->upAction = *pAction; + filter->filter = _XkbFilterISOLock; + if (flags&XkbSA_ISODfltIsGroup) { + xkbi->groupChange = XkbSAGroup(&pAction->iso); + xkbi->setMods = 0; + } + else { + xkbi->setMods = pAction->iso.mask; + xkbi->groupChange = 0; + } + if ((!(flags&XkbSA_ISONoAffectMods))&&(xkbi->state.base_mods)) { + filter->priv= NO_ISO_LOCK; + xkbi->state.locked_mods^= xkbi->state.base_mods; + } + if ((!(flags&XkbSA_ISONoAffectGroup))&&(xkbi->state.base_group)) { +/* 6/22/93 (ef) -- lock groups if group key is down first */ + } + if (!(flags&XkbSA_ISONoAffectPtr)) { +/* 6/22/93 (ef) -- lock mouse buttons if they're down */ + } + } + else if (filter->keycode==keycode) { + CARD8 flags= filter->upAction.iso.flags; + + if (flags&XkbSA_ISODfltIsGroup) { + xkbi->groupChange = -XkbSAGroup(&filter->upAction.iso); + xkbi->clearMods = 0; + if (filter->priv==ISO_KEY_DOWN) + xkbi->state.locked_group+= XkbSAGroup(&filter->upAction.iso); + } + else { + xkbi->clearMods= filter->upAction.iso.mask; + xkbi->groupChange= 0; + if (filter->priv==ISO_KEY_DOWN) + xkbi->state.locked_mods^= filter->upAction.iso.mask; + } + filter->active = 0; + } + else if (pAction) { + CARD8 flags= filter->upAction.iso.flags; + + switch (pAction->type) { + case XkbSA_SetMods: case XkbSA_LatchMods: + if (!(flags&XkbSA_ISONoAffectMods)) { + pAction->type= XkbSA_LockMods; + filter->priv= NO_ISO_LOCK; + } + break; + case XkbSA_SetGroup: case XkbSA_LatchGroup: + if (!(flags&XkbSA_ISONoAffectGroup)) { + pAction->type= XkbSA_LockGroup; + filter->priv= NO_ISO_LOCK; + } + break; + case XkbSA_PtrBtn: + if (!(flags&XkbSA_ISONoAffectPtr)) { + pAction->type= XkbSA_LockPtrBtn; + filter->priv= NO_ISO_LOCK; + } + break; + case XkbSA_SetControls: + if (!(flags&XkbSA_ISONoAffectCtrls)) { + pAction->type= XkbSA_LockControls; + filter->priv= NO_ISO_LOCK; + } + break; + } + } + return 1; +} + + +static CARD32 +_XkbPtrAccelExpire(OsTimerPtr timer,CARD32 now,pointer arg) +{ +XkbSrvInfoPtr xkbi= (XkbSrvInfoPtr)arg; +XkbControlsPtr ctrls= xkbi->desc->ctrls; +int dx,dy; + + if (xkbi->mouseKey==0) + return 0; + + if (xkbi->mouseKeysAccel) { + if ((xkbi->mouseKeysCounter)<ctrls->mk_time_to_max) { + double step; + xkbi->mouseKeysCounter++; + step= xkbi->mouseKeysCurveFactor* + pow((double)xkbi->mouseKeysCounter,xkbi->mouseKeysCurve); + if (xkbi->mouseKeysDX<0) + dx= floor( ((double)xkbi->mouseKeysDX)*step ); + else dx= ceil( ((double)xkbi->mouseKeysDX)*step ); + if (xkbi->mouseKeysDY<0) + dy= floor( ((double)xkbi->mouseKeysDY)*step ); + else dy= ceil( ((double)xkbi->mouseKeysDY)*step ); + } + else { + dx= xkbi->mouseKeysDX*ctrls->mk_max_speed; + dy= xkbi->mouseKeysDY*ctrls->mk_max_speed; + } + if (xkbi->mouseKeysFlags&XkbSA_MoveAbsoluteX) + dx= xkbi->mouseKeysDX; + if (xkbi->mouseKeysFlags&XkbSA_MoveAbsoluteY) + dy= xkbi->mouseKeysDY; + } + else { + dx= xkbi->mouseKeysDX; + dy= xkbi->mouseKeysDY; + } + XkbFakePointerMotion(xkbi->device, xkbi->mouseKeysFlags,dx,dy); + return xkbi->desc->ctrls->mk_interval; +} + +static int +_XkbFilterPointerMove( XkbSrvInfoPtr xkbi, + XkbFilterPtr filter, + unsigned keycode, + XkbAction * pAction) +{ +int x,y; +Bool accel; + + if (filter->keycode==0) { /* initial press */ + filter->keycode = keycode; + filter->active = 1; + filter->filterOthers = 0; + filter->priv=0; + filter->filter = _XkbFilterPointerMove; + filter->upAction= *pAction; + xkbi->mouseKeysCounter= 0; + xkbi->mouseKey= keycode; + accel= ((pAction->ptr.flags&XkbSA_NoAcceleration)==0); + x= XkbPtrActionX(&pAction->ptr); + y= XkbPtrActionY(&pAction->ptr); + XkbFakePointerMotion(xkbi->device, pAction->ptr.flags,x,y); + AccessXCancelRepeatKey(xkbi,keycode); + xkbi->mouseKeysAccel= accel&& + (xkbi->desc->ctrls->enabled_ctrls&XkbMouseKeysAccelMask); + xkbi->mouseKeysFlags= pAction->ptr.flags; + xkbi->mouseKeysDX= XkbPtrActionX(&pAction->ptr); + xkbi->mouseKeysDY= XkbPtrActionY(&pAction->ptr); + xkbi->mouseKeyTimer= TimerSet(xkbi->mouseKeyTimer, 0, + xkbi->desc->ctrls->mk_delay, + _XkbPtrAccelExpire,(pointer)xkbi); + } + else if (filter->keycode==keycode) { + filter->active = 0; + if (xkbi->mouseKey==keycode) { + xkbi->mouseKey= 0; + xkbi->mouseKeyTimer= TimerSet(xkbi->mouseKeyTimer, 0, 0, + NULL, NULL); + } + } + return 0; +} + +static int +_XkbFilterPointerBtn( XkbSrvInfoPtr xkbi, + XkbFilterPtr filter, + unsigned keycode, + XkbAction * pAction) +{ + if (filter->keycode==0) { /* initial press */ + int button= pAction->btn.button; + + if (button==XkbSA_UseDfltButton) + button = xkbi->desc->ctrls->mk_dflt_btn; + + filter->keycode = keycode; + filter->active = 1; + filter->filterOthers = 0; + filter->priv=0; + filter->filter = _XkbFilterPointerBtn; + filter->upAction= *pAction; + filter->upAction.btn.button= button; + switch (pAction->type) { + case XkbSA_LockPtrBtn: + if (((xkbi->lockedPtrButtons&(1<<button))==0)&& + ((pAction->btn.flags&XkbSA_LockNoLock)==0)) { + xkbi->lockedPtrButtons|= (1<<button); + AccessXCancelRepeatKey(xkbi,keycode); + XkbFakeDeviceButton(xkbi->device, 1, button); + filter->upAction.type= XkbSA_NoAction; + } + break; + case XkbSA_PtrBtn: + { + register int i,nClicks; + AccessXCancelRepeatKey(xkbi,keycode); + if (pAction->btn.count>0) { + nClicks= pAction->btn.count; + for (i=0;i<nClicks;i++) { + XkbFakeDeviceButton(xkbi->device, 1, button); + XkbFakeDeviceButton(xkbi->device, 0, button); + } + filter->upAction.type= XkbSA_NoAction; + } + else XkbFakeDeviceButton(xkbi->device, 1, button); + } + break; + case XkbSA_SetPtrDflt: + { + XkbControlsPtr ctrls= xkbi->desc->ctrls; + XkbControlsRec old; + xkbControlsNotify cn; + + old= *ctrls; + AccessXCancelRepeatKey(xkbi,keycode); + switch (pAction->dflt.affect) { + case XkbSA_AffectDfltBtn: + if (pAction->dflt.flags&XkbSA_DfltBtnAbsolute) + ctrls->mk_dflt_btn= + XkbSAPtrDfltValue(&pAction->dflt); + else { + ctrls->mk_dflt_btn+= + XkbSAPtrDfltValue(&pAction->dflt); + if (ctrls->mk_dflt_btn>5) + ctrls->mk_dflt_btn= 5; + else if (ctrls->mk_dflt_btn<1) + ctrls->mk_dflt_btn= 1; + } + break; + default: + ErrorF( + "Attempt to change unknown pointer default (%d) ignored\n", + pAction->dflt.affect); + break; + } + if (XkbComputeControlsNotify(xkbi->device, + &old,xkbi->desc->ctrls, + &cn,FALSE)) { + cn.keycode = keycode; + /* XXX: what about DeviceKeyPress? */ + cn.eventType = KeyPress; + cn.requestMajor = 0; + cn.requestMinor = 0; + XkbSendControlsNotify(xkbi->device,&cn); + } + } + break; + } + } + else if (filter->keycode==keycode) { + int button= filter->upAction.btn.button; + + switch (filter->upAction.type) { + case XkbSA_LockPtrBtn: + if (((filter->upAction.btn.flags&XkbSA_LockNoUnlock)!=0)|| + ((xkbi->lockedPtrButtons&(1<<button))==0)) { + break; + } + xkbi->lockedPtrButtons&= ~(1<<button); + + if (IsMaster(xkbi->device)) + { + XkbMergeLockedPtrBtns(xkbi->device); + /* One SD still has lock set, don't post event */ + if ((xkbi->lockedPtrButtons & (1 << button)) != 0) + break; + } + + /* fallthrough */ + case XkbSA_PtrBtn: + XkbFakeDeviceButton(xkbi->device, 0, button); + break; + } + filter->active = 0; + } + return 0; +} + +static int +_XkbFilterControls( XkbSrvInfoPtr xkbi, + XkbFilterPtr filter, + unsigned keycode, + XkbAction * pAction) +{ +XkbControlsRec old; +XkbControlsPtr ctrls; +DeviceIntPtr kbd; +unsigned int change; +XkbEventCauseRec cause; + + kbd= xkbi->device; + ctrls= xkbi->desc->ctrls; + old= *ctrls; + if (filter->keycode==0) { /* initial press */ + filter->keycode = keycode; + filter->active = 1; + filter->filterOthers = 0; + change= XkbActionCtrls(&pAction->ctrls); + filter->priv = change; + filter->filter = _XkbFilterControls; + filter->upAction = *pAction; + + if (pAction->type==XkbSA_LockControls) { + filter->priv= (ctrls->enabled_ctrls&change); + change&= ~ctrls->enabled_ctrls; + } + + if (change) { + xkbControlsNotify cn; + XkbSrvLedInfoPtr sli; + + ctrls->enabled_ctrls|= change; + if (XkbComputeControlsNotify(kbd,&old,ctrls,&cn,FALSE)) { + cn.keycode = keycode; + /* XXX: what about DeviceKeyPress? */ + cn.eventType = KeyPress; + cn.requestMajor = 0; + cn.requestMinor = 0; + XkbSendControlsNotify(kbd,&cn); + } + + XkbSetCauseKey(&cause,keycode,KeyPress); + + /* If sticky keys were disabled, clear all locks and latches */ + if ((old.enabled_ctrls&XkbStickyKeysMask)&& + (!(ctrls->enabled_ctrls&XkbStickyKeysMask))) { + XkbClearAllLatchesAndLocks(kbd,xkbi,FALSE,&cause); + } + sli= XkbFindSrvLedInfo(kbd,XkbDfltXIClass,XkbDfltXIId,0); + XkbUpdateIndicators(kbd,sli->usesControls,TRUE,NULL,&cause); + if (XkbAX_NeedFeedback(ctrls,XkbAX_FeatureFBMask)) + XkbDDXAccessXBeep(kbd,_BEEP_FEATURE_ON,change); + } + } + else if (filter->keycode==keycode) { + change= filter->priv; + if (change) { + xkbControlsNotify cn; + XkbSrvLedInfoPtr sli; + + ctrls->enabled_ctrls&= ~change; + if (XkbComputeControlsNotify(kbd,&old,ctrls,&cn,FALSE)) { + cn.keycode = keycode; + cn.eventType = KeyRelease; + cn.requestMajor = 0; + cn.requestMinor = 0; + XkbSendControlsNotify(kbd,&cn); + } + + XkbSetCauseKey(&cause,keycode,KeyRelease); + /* If sticky keys were disabled, clear all locks and latches */ + if ((old.enabled_ctrls&XkbStickyKeysMask)&& + (!(ctrls->enabled_ctrls&XkbStickyKeysMask))) { + XkbClearAllLatchesAndLocks(kbd,xkbi,FALSE,&cause); + } + sli= XkbFindSrvLedInfo(kbd,XkbDfltXIClass,XkbDfltXIId,0); + XkbUpdateIndicators(kbd,sli->usesControls,TRUE,NULL,&cause); + if (XkbAX_NeedFeedback(ctrls,XkbAX_FeatureFBMask)) + XkbDDXAccessXBeep(kbd,_BEEP_FEATURE_OFF,change); + } + filter->keycode= 0; + filter->active= 0; + } + return 1; +} + +static int +_XkbFilterActionMessage(XkbSrvInfoPtr xkbi, + XkbFilterPtr filter, + unsigned keycode, + XkbAction * pAction) +{ +XkbMessageAction * pMsg; +DeviceIntPtr kbd; + + kbd= xkbi->device; + if (filter->keycode==0) { /* initial press */ + pMsg= &pAction->msg; + if ((pMsg->flags&XkbSA_MessageOnRelease)|| + ((pMsg->flags&XkbSA_MessageGenKeyEvent)==0)) { + filter->keycode = keycode; + filter->active = 1; + filter->filterOthers = 0; + filter->priv = 0; + filter->filter = _XkbFilterActionMessage; + filter->upAction = *pAction; + } + if (pMsg->flags&XkbSA_MessageOnPress) { + xkbActionMessage msg; + + msg.keycode= keycode; + msg.press= 1; + msg.keyEventFollows=((pMsg->flags&XkbSA_MessageGenKeyEvent)!=0); + memcpy((char *)msg.message, + (char *)pMsg->message,XkbActionMessageLength); + XkbSendActionMessage(kbd,&msg); + } + return ((pAction->msg.flags&XkbSA_MessageGenKeyEvent)!=0); + } + else if (filter->keycode==keycode) { + pMsg= &filter->upAction.msg; + if (pMsg->flags&XkbSA_MessageOnRelease) { + xkbActionMessage msg; + + msg.keycode= keycode; + msg.press= 0; + msg.keyEventFollows=((pMsg->flags&XkbSA_MessageGenKeyEvent)!=0); + memcpy((char *)msg.message,(char *)pMsg->message, + XkbActionMessageLength); + XkbSendActionMessage(kbd,&msg); + } + filter->keycode= 0; + filter->active= 0; + return ((pMsg->flags&XkbSA_MessageGenKeyEvent)!=0); + } + return 0; +} + +static int +_XkbFilterRedirectKey( XkbSrvInfoPtr xkbi, + XkbFilterPtr filter, + unsigned keycode, + XkbAction * pAction) +{ +DeviceEvent ev; +int x,y; +XkbStateRec old; +unsigned mods,mask; +xkbDeviceInfoPtr xkbPrivPtr = XKBDEVICEINFO(xkbi->device); +ProcessInputProc backupproc; + + /* never actually used uninitialised, but gcc isn't smart enough + * to work that out. */ + memset(&old, 0, sizeof(old)); + memset(&ev, 0, sizeof(ev)); + + if ((filter->keycode!=0)&&(filter->keycode!=keycode)) + return 1; + + GetSpritePosition(xkbi->device, &x,&y); + ev.header = ET_Internal; + ev.length = sizeof(DeviceEvent); + ev.time = GetTimeInMillis(); + ev.root_x = x; + ev.root_y = y; + + if (filter->keycode==0) { /* initial press */ + if ((pAction->redirect.new_key<xkbi->desc->min_key_code)|| + (pAction->redirect.new_key>xkbi->desc->max_key_code)) { + return 1; + } + filter->keycode = keycode; + filter->active = 1; + filter->filterOthers = 0; + filter->priv = 0; + filter->filter = _XkbFilterRedirectKey; + filter->upAction = *pAction; + + ev.type = ET_KeyPress; + ev.detail.key = pAction->redirect.new_key; + + mask= XkbSARedirectVModsMask(&pAction->redirect); + mods= XkbSARedirectVMods(&pAction->redirect); + if (mask) XkbVirtualModsToReal(xkbi->desc,mask,&mask); + if (mods) XkbVirtualModsToReal(xkbi->desc,mods,&mods); + mask|= pAction->redirect.mods_mask; + mods|= pAction->redirect.mods; + + if ( mask || mods ) { + old= xkbi->state; + xkbi->state.base_mods&= ~mask; + xkbi->state.base_mods|= (mods&mask); + xkbi->state.latched_mods&= ~mask; + xkbi->state.latched_mods|= (mods&mask); + xkbi->state.locked_mods&= ~mask; + xkbi->state.locked_mods|= (mods&mask); + XkbComputeDerivedState(xkbi); + } + + UNWRAP_PROCESS_INPUT_PROC(xkbi->device,xkbPrivPtr, backupproc); + xkbi->device->public.processInputProc((InternalEvent*)&ev, xkbi->device); + COND_WRAP_PROCESS_INPUT_PROC(xkbi->device, xkbPrivPtr, + backupproc,xkbUnwrapProc); + + if ( mask || mods ) + xkbi->state= old; + } + else if (filter->keycode==keycode) { + + ev.type = ET_KeyRelease; + ev.detail.key = filter->upAction.redirect.new_key; + + mask= XkbSARedirectVModsMask(&filter->upAction.redirect); + mods= XkbSARedirectVMods(&filter->upAction.redirect); + if (mask) XkbVirtualModsToReal(xkbi->desc,mask,&mask); + if (mods) XkbVirtualModsToReal(xkbi->desc,mods,&mods); + mask|= filter->upAction.redirect.mods_mask; + mods|= filter->upAction.redirect.mods; + + if ( mask || mods ) { + old= xkbi->state; + xkbi->state.base_mods&= ~mask; + xkbi->state.base_mods|= (mods&mask); + xkbi->state.latched_mods&= ~mask; + xkbi->state.latched_mods|= (mods&mask); + xkbi->state.locked_mods&= ~mask; + xkbi->state.locked_mods|= (mods&mask); + XkbComputeDerivedState(xkbi); + } + + UNWRAP_PROCESS_INPUT_PROC(xkbi->device,xkbPrivPtr, backupproc); + xkbi->device->public.processInputProc((InternalEvent*)&ev, xkbi->device); + COND_WRAP_PROCESS_INPUT_PROC(xkbi->device, xkbPrivPtr, + backupproc,xkbUnwrapProc); + + if ( mask || mods ) + xkbi->state= old; + + filter->keycode= 0; + filter->active= 0; + } + return 0; +} + +static int +_XkbFilterSwitchScreen( XkbSrvInfoPtr xkbi, + XkbFilterPtr filter, + unsigned keycode, + XkbAction * pAction) +{ + DeviceIntPtr dev = xkbi->device; + if (dev == inputInfo.keyboard) + return 0; + + if (filter->keycode==0) { /* initial press */ + filter->keycode = keycode; + filter->active = 1; + filter->filterOthers = 0; + filter->filter = _XkbFilterSwitchScreen; + AccessXCancelRepeatKey(xkbi, keycode); + XkbDDXSwitchScreen(dev,keycode,pAction); + return 0; + } + else if (filter->keycode==keycode) { + filter->active= 0; + return 0; + } + return 1; +} + +static int +_XkbFilterXF86Private( XkbSrvInfoPtr xkbi, + XkbFilterPtr filter, + unsigned keycode, + XkbAction * pAction) +{ + DeviceIntPtr dev = xkbi->device; + if (dev == inputInfo.keyboard) + return 0; + + if (filter->keycode==0) { /* initial press */ + filter->keycode = keycode; + filter->active = 1; + filter->filterOthers = 0; + filter->filter = _XkbFilterXF86Private; + XkbDDXPrivate(dev,keycode,pAction); + return 0; + } + else if (filter->keycode==keycode) { + filter->active= 0; + return 0; + } + return 1; +} + + +static int +_XkbFilterDeviceBtn( XkbSrvInfoPtr xkbi, + XkbFilterPtr filter, + unsigned keycode, + XkbAction * pAction) +{ +DeviceIntPtr dev; +int button; + + if (xkbi->device == inputInfo.keyboard) + return 0; + + if (filter->keycode==0) { /* initial press */ + _XkbLookupButtonDevice(&dev, pAction->devbtn.device, serverClient, + DixUnknownAccess, &button); + if (!dev || !dev->public.on) + return 1; + + button= pAction->devbtn.button; + if ((button<1)||(button>dev->button->numButtons)) + return 1; + + filter->keycode = keycode; + filter->active = 1; + filter->filterOthers = 0; + filter->priv=0; + filter->filter = _XkbFilterDeviceBtn; + filter->upAction= *pAction; + switch (pAction->type) { + case XkbSA_LockDeviceBtn: + if ((pAction->devbtn.flags&XkbSA_LockNoLock)|| + BitIsOn(dev->button->down, button)) + return 0; + XkbFakeDeviceButton(dev,TRUE,button); + filter->upAction.type= XkbSA_NoAction; + break; + case XkbSA_DeviceBtn: + if (pAction->devbtn.count>0) { + int nClicks,i; + nClicks= pAction->btn.count; + for (i=0;i<nClicks;i++) { + XkbFakeDeviceButton(dev,TRUE,button); + XkbFakeDeviceButton(dev,FALSE,button); + } + filter->upAction.type= XkbSA_NoAction; + } + else XkbFakeDeviceButton(dev,TRUE,button); + break; + } + } + else if (filter->keycode==keycode) { + int button; + + filter->active= 0; + _XkbLookupButtonDevice(&dev, filter->upAction.devbtn.device, + serverClient, DixUnknownAccess, &button); + if (!dev || !dev->public.on) + return 1; + + button= filter->upAction.btn.button; + switch (filter->upAction.type) { + case XkbSA_LockDeviceBtn: + if ((filter->upAction.devbtn.flags&XkbSA_LockNoUnlock)|| + !BitIsOn(dev->button->down, button)) + return 0; + XkbFakeDeviceButton(dev,FALSE,button); + break; + case XkbSA_DeviceBtn: + XkbFakeDeviceButton(dev,FALSE,button); + break; + } + filter->active = 0; + } + return 0; +} + +static XkbFilterPtr +_XkbNextFreeFilter( + XkbSrvInfoPtr xkbi +) +{ +register int i; + + if (xkbi->szFilters==0) { + xkbi->szFilters = 4; + xkbi->filters = calloc(xkbi->szFilters, sizeof(XkbFilterRec)); + /* 6/21/93 (ef) -- XXX! deal with allocation failure */ + } + for (i=0;i<xkbi->szFilters;i++) { + if (!xkbi->filters[i].active) { + xkbi->filters[i].keycode = 0; + return &xkbi->filters[i]; + } + } + xkbi->szFilters*=2; + xkbi->filters= realloc(xkbi->filters, + xkbi->szFilters * sizeof(XkbFilterRec)); + /* 6/21/93 (ef) -- XXX! deal with allocation failure */ + memset(&xkbi->filters[xkbi->szFilters/2], 0, + (xkbi->szFilters/2)*sizeof(XkbFilterRec)); + return &xkbi->filters[xkbi->szFilters/2]; +} + +static int +_XkbApplyFilters(XkbSrvInfoPtr xkbi,unsigned kc,XkbAction *pAction) +{ +register int i,send; + + send= 1; + for (i=0;i<xkbi->szFilters;i++) { + if ((xkbi->filters[i].active)&&(xkbi->filters[i].filter)) + send= ((*xkbi->filters[i].filter)(xkbi,&xkbi->filters[i],kc,pAction) + && send); + } + return send; +} + +void +XkbHandleActions(DeviceIntPtr dev, DeviceIntPtr kbd, DeviceEvent* event) +{ +int key,bit,i; +XkbSrvInfoPtr xkbi; +KeyClassPtr keyc; +int changed,sendEvent; +Bool genStateNotify; +XkbAction act; +XkbFilterPtr filter; +Bool keyEvent; +Bool pressEvent; +ProcessInputProc backupproc; + +xkbDeviceInfoPtr xkbPrivPtr = XKBDEVICEINFO(dev); + + keyc= kbd->key; + xkbi= keyc->xkbInfo; + key= event->detail.key; + /* The state may change, so if we're not in the middle of sending a state + * notify, prepare for it */ + if ((xkbi->flags&_XkbStateNotifyInProgress)==0) { + xkbi->prev_state = xkbi->state; + xkbi->flags|= _XkbStateNotifyInProgress; + genStateNotify= TRUE; + } + else genStateNotify= FALSE; + + xkbi->clearMods = xkbi->setMods = 0; + xkbi->groupChange = 0; + + sendEvent = 1; + keyEvent= ((event->type == ET_KeyPress) || (event->type == ET_KeyRelease)); + pressEvent= ((event->type == ET_KeyPress)|| (event->type == ET_ButtonPress)); + + if (pressEvent) { + if (keyEvent) + act = XkbGetKeyAction(xkbi,&xkbi->state,key); + else { + act = XkbGetButtonAction(kbd,dev,key); + key|= BTN_ACT_FLAG; + } + sendEvent = _XkbApplyFilters(xkbi,key,&act); + if (sendEvent) { + switch (act.type) { + case XkbSA_SetMods: + case XkbSA_SetGroup: + filter = _XkbNextFreeFilter(xkbi); + sendEvent = _XkbFilterSetState(xkbi,filter,key,&act); + break; + case XkbSA_LatchMods: + case XkbSA_LatchGroup: + filter = _XkbNextFreeFilter(xkbi); + sendEvent=_XkbFilterLatchState(xkbi,filter,key,&act); + break; + case XkbSA_LockMods: + case XkbSA_LockGroup: + filter = _XkbNextFreeFilter(xkbi); + sendEvent=_XkbFilterLockState(xkbi,filter,key,&act); + break; + case XkbSA_ISOLock: + filter = _XkbNextFreeFilter(xkbi); + sendEvent=_XkbFilterISOLock(xkbi,filter,key,&act); + break; + case XkbSA_MovePtr: + filter = _XkbNextFreeFilter(xkbi); + sendEvent= _XkbFilterPointerMove(xkbi,filter,key,&act); + break; + case XkbSA_PtrBtn: + case XkbSA_LockPtrBtn: + case XkbSA_SetPtrDflt: + filter = _XkbNextFreeFilter(xkbi); + sendEvent= _XkbFilterPointerBtn(xkbi,filter,key,&act); + break; + case XkbSA_Terminate: + sendEvent= XkbDDXTerminateServer(dev,key,&act); + break; + case XkbSA_SwitchScreen: + filter = _XkbNextFreeFilter(xkbi); + sendEvent=_XkbFilterSwitchScreen(xkbi,filter,key,&act); + break; + case XkbSA_SetControls: + case XkbSA_LockControls: + filter = _XkbNextFreeFilter(xkbi); + sendEvent=_XkbFilterControls(xkbi,filter,key,&act); + break; + case XkbSA_ActionMessage: + filter = _XkbNextFreeFilter(xkbi); + sendEvent=_XkbFilterActionMessage(xkbi,filter,key,&act); + break; + case XkbSA_RedirectKey: + filter = _XkbNextFreeFilter(xkbi); + sendEvent= _XkbFilterRedirectKey(xkbi,filter,key,&act); + break; + case XkbSA_DeviceBtn: + case XkbSA_LockDeviceBtn: + filter = _XkbNextFreeFilter(xkbi); + sendEvent= _XkbFilterDeviceBtn(xkbi,filter,key,&act); + break; + case XkbSA_XFree86Private: + filter = _XkbNextFreeFilter(xkbi); + sendEvent= _XkbFilterXF86Private(xkbi,filter,key,&act); + break; + } + } + } + else { + if (!keyEvent) + key|= BTN_ACT_FLAG; + sendEvent = _XkbApplyFilters(xkbi,key,NULL); + } + + if (xkbi->groupChange!=0) + xkbi->state.base_group+= xkbi->groupChange; + if (xkbi->setMods) { + for (i=0,bit=1; xkbi->setMods; i++,bit<<=1 ) { + if (xkbi->setMods&bit) { + keyc->modifierKeyCount[i]++; + xkbi->state.base_mods|= bit; + xkbi->setMods&= ~bit; + } + } + } + if (xkbi->clearMods) { + for (i=0,bit=1; xkbi->clearMods; i++,bit<<=1 ) { + if (xkbi->clearMods&bit) { + keyc->modifierKeyCount[i]--; + if (keyc->modifierKeyCount[i]<=0) { + xkbi->state.base_mods&= ~bit; + keyc->modifierKeyCount[i] = 0; + } + xkbi->clearMods&= ~bit; + } + } + } + + if (sendEvent) { + DeviceIntPtr tmpdev; + if (keyEvent) + tmpdev = dev; + else + tmpdev = GetPairedDevice(dev); + + UNWRAP_PROCESS_INPUT_PROC(tmpdev,xkbPrivPtr, backupproc); + dev->public.processInputProc((InternalEvent*)event, tmpdev); + COND_WRAP_PROCESS_INPUT_PROC(tmpdev, xkbPrivPtr, + backupproc,xkbUnwrapProc); + } + else if (keyEvent) { + FixKeyState(event, dev); + } + + XkbComputeDerivedState(xkbi); + changed = XkbStateChangedFlags(&xkbi->prev_state,&xkbi->state); + if (genStateNotify) { + if (changed) { + xkbStateNotify sn; + sn.keycode= key; + sn.eventType= event->type; + sn.requestMajor = sn.requestMinor = 0; + sn.changed= changed; + XkbSendStateNotify(dev,&sn); + } + xkbi->flags&= ~_XkbStateNotifyInProgress; + } + changed= XkbIndicatorsToUpdate(dev,changed,FALSE); + if (changed) { + XkbEventCauseRec cause; + XkbSetCauseKey(&cause, key, event->type); + XkbUpdateIndicators(dev,changed,FALSE,NULL,&cause); + } + return; +} + +int +XkbLatchModifiers(DeviceIntPtr pXDev,CARD8 mask,CARD8 latches) +{ +XkbSrvInfoPtr xkbi; +XkbFilterPtr filter; +XkbAction act; +unsigned clear; + + if ( pXDev && pXDev->key && pXDev->key->xkbInfo ) { + xkbi = pXDev->key->xkbInfo; + clear= (mask&(~latches)); + xkbi->state.latched_mods&= ~clear; + /* Clear any pending latch to locks. + */ + act.type = XkbSA_NoAction; + _XkbApplyFilters(xkbi,SYNTHETIC_KEYCODE,&act); + act.type = XkbSA_LatchMods; + act.mods.flags = 0; + act.mods.mask = mask&latches; + filter = _XkbNextFreeFilter(xkbi); + _XkbFilterLatchState(xkbi,filter,SYNTHETIC_KEYCODE,&act); + _XkbFilterLatchState(xkbi,filter,SYNTHETIC_KEYCODE,(XkbAction *)NULL); + return Success; + } + return BadValue; +} + +int +XkbLatchGroup(DeviceIntPtr pXDev,int group) +{ +XkbSrvInfoPtr xkbi; +XkbFilterPtr filter; +XkbAction act; + + if ( pXDev && pXDev->key && pXDev->key->xkbInfo ) { + xkbi = pXDev->key->xkbInfo; + act.type = XkbSA_LatchGroup; + act.group.flags = 0; + XkbSASetGroup(&act.group,group); + filter = _XkbNextFreeFilter(xkbi); + _XkbFilterLatchState(xkbi,filter,SYNTHETIC_KEYCODE,&act); + _XkbFilterLatchState(xkbi,filter,SYNTHETIC_KEYCODE,(XkbAction *)NULL); + return Success; + } + return BadValue; +} + +/***====================================================================***/ + +void +XkbClearAllLatchesAndLocks( DeviceIntPtr dev, + XkbSrvInfoPtr xkbi, + Bool genEv, + XkbEventCausePtr cause) +{ +XkbStateRec os; +xkbStateNotify sn; + + sn.changed= 0; + os= xkbi->state; + if (os.latched_mods) { /* clear all latches */ + XkbLatchModifiers(dev,~0,0); + sn.changed|= XkbModifierLatchMask; + } + if (os.latched_group) { + XkbLatchGroup(dev,0); + sn.changed|= XkbGroupLatchMask; + } + if (os.locked_mods) { + xkbi->state.locked_mods= 0; + sn.changed|= XkbModifierLockMask; + } + if (os.locked_group) { + xkbi->state.locked_group= 0; + sn.changed|= XkbGroupLockMask; + } + if ( genEv && sn.changed) { + CARD32 changed; + + XkbComputeDerivedState(xkbi); + sn.keycode= cause->kc; + sn.eventType= cause->event; + sn.requestMajor= cause->mjr; + sn.requestMinor= cause->mnr; + sn.changed= XkbStateChangedFlags(&os,&xkbi->state); + XkbSendStateNotify(dev,&sn); + changed= XkbIndicatorsToUpdate(dev,sn.changed,FALSE); + if (changed) { + XkbUpdateIndicators(dev,changed,TRUE,NULL,cause); + } + } + return; +} + +/* + * The event is injected into the event processing, not the EQ. Thus, + * ensure that we restore the master after the event sequence to the + * original set of classes. Otherwise, the master remains on the XTEST + * classes and drops events that don't fit into the XTEST layout (e.g. + * events with more than 2 valuators). + * + * FIXME: EQ injection in the processing stage is not designed for, so this + * is a rather awkward hack. The event list returned by GetPointerEvents() + * and friends is always prefixed with a DCE if the last _posted_ device was + * different. For normal events, this sequence then resets the master during + * the processing stage. Since we inject the PointerKey events in the + * processing stage though, we need to manually reset to restore the + * previous order, because the events already in the EQ must be sent for the + * right device. + * So we post-fix the event list we get from GPE with a DCE back to the + * previous slave device. + * + * First one on drinking island wins! + */ +static void +InjectPointerKeyEvents(DeviceIntPtr dev, int type, int button, int flags, ValuatorMask *mask) +{ + ScreenPtr pScreen; + EventListPtr events; + int nevents, i; + DeviceIntPtr ptr, mpointer, lastSlave = NULL; + Bool saveWait; + + if (IsMaster(dev)) { + mpointer = GetMaster(dev, MASTER_POINTER); + lastSlave = mpointer->lastSlave; + ptr = GetXTestDevice(mpointer); + } else if (IsFloating(dev)) + ptr = dev; + else + return; + + + events = InitEventList(GetMaximumEventsNum() + 1); + OsBlockSignals(); + pScreen = miPointerGetScreen(ptr); + saveWait = miPointerSetWaitForUpdate(pScreen, FALSE); + nevents = GetPointerEvents(events, ptr, type, button, flags, mask); + if (IsMaster(dev) && (lastSlave && lastSlave != ptr)) + UpdateFromMaster(&events[nevents], lastSlave, DEVCHANGE_POINTER_EVENT, &nevents); + miPointerSetWaitForUpdate(pScreen, saveWait); + OsReleaseSignals(); + + for (i = 0; i < nevents; i++) + mieqProcessDeviceEvent(ptr, (InternalEvent*)events[i].event, NULL); + + FreeEventList(events, GetMaximumEventsNum()); + +} + +static void +XkbFakePointerMotion(DeviceIntPtr dev, unsigned flags,int x,int y) +{ + ValuatorMask mask; + int gpe_flags = 0; + + /* ignore attached SDs */ + if (!IsMaster(dev) && !IsFloating(dev)) + return; + + if (flags & XkbSA_MoveAbsoluteX || flags & XkbSA_MoveAbsoluteY) + gpe_flags = POINTER_ABSOLUTE; + else + gpe_flags = POINTER_RELATIVE; + + valuator_mask_set_range(&mask, 0, 2, (int[]){x, y}); + + InjectPointerKeyEvents(dev, MotionNotify, 0, gpe_flags, &mask); +} + +void +XkbFakeDeviceButton(DeviceIntPtr dev,Bool press,int button) +{ + DeviceIntPtr ptr; + int down; + + /* If dev is a slave device, and the SD is attached, do nothing. If we'd + * post through the attached master pointer we'd get duplicate events. + * + * if dev is a master keyboard, post through the XTEST device + * + * if dev is a floating slave, post through the device itself. + */ + + if (IsMaster(dev)) { + DeviceIntPtr mpointer = GetMaster(dev, MASTER_POINTER); + ptr = GetXTestDevice(mpointer); + } else if (IsFloating(dev)) + ptr = dev; + else + return; + + down = button_is_down(ptr, button, BUTTON_PROCESSED); + if (press == down) + return; + + InjectPointerKeyEvents(dev, press ? ButtonPress : ButtonRelease, + button, 0, NULL); +} diff --git a/xorg-server/xkb/xkbInit.c b/xorg-server/xkb/xkbInit.c index 6defefa50..3d3febb4f 100644 --- a/xorg-server/xkb/xkbInit.c +++ b/xorg-server/xkb/xkbInit.c @@ -1,768 +1,768 @@ -/************************************************************
-Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc.
-
-Permission 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 that both that copyright
-notice and this permission notice appear in supporting
-documentation, and that the name of Silicon Graphics not be
-used in advertising or publicity pertaining to distribution
-of the software without specific prior written permission.
-Silicon Graphics makes no representation about the suitability
-of this software for any purpose. It is provided "as is"
-without any express or implied warranty.
-
-SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
-SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
-AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
-GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
-DAMAGES OR ANY 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 THIS SOFTWARE.
-
-********************************************************/
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#include <xkb-config.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <ctype.h>
-#include <unistd.h>
-#include <math.h>
-#include <X11/X.h>
-#include <X11/Xproto.h>
-#include <X11/keysym.h>
-#include <X11/Xatom.h>
-#include "misc.h"
-#include "inputstr.h"
-#include "opaque.h"
-#include "property.h"
-#include "scrnintstr.h"
-#define XKBSRV_NEED_FILE_FUNCS
-#include <xkbsrv.h>
-#include "xkbgeom.h"
-#include <X11/extensions/XKMformat.h>
-#include "xkbfile.h"
-#include "xkb.h"
-
-#define CREATE_ATOM(s) MakeAtom(s,sizeof(s)-1,1)
-
-#if defined(__alpha) || defined(__alpha__)
-#define LED_COMPOSE 2
-#define LED_CAPS 3
-#define LED_SCROLL 4
-#define LED_NUM 5
-#define PHYS_LEDS 0x1f
-#else
-#ifdef sun
-#define LED_NUM 1
-#define LED_SCROLL 2
-#define LED_COMPOSE 3
-#define LED_CAPS 4
-#define PHYS_LEDS 0x0f
-#else
-#define LED_CAPS 1
-#define LED_NUM 2
-#define LED_SCROLL 3
-#define PHYS_LEDS 0x07
-#endif
-#endif
-
-#define MAX_TOC 16
-typedef struct _SrvXkmInfo {
- DeviceIntPtr dev;
- FILE * file;
- XkbDescPtr xkb;
-} SrvXkmInfo;
-
-
-/***====================================================================***/
-
-#ifndef XKB_DFLT_RULES_PROP
-#define XKB_DFLT_RULES_PROP TRUE
-#endif
-
-char * XkbBaseDirectory= XKB_BASE_DIRECTORY;
-char * XkbBinDirectory= XKB_BIN_DIRECTORY;
-static int XkbWantAccessX= 0;
-
-static char * XkbRulesDflt= NULL;
-static char * XkbModelDflt= NULL;
-static char * XkbLayoutDflt= NULL;
-static char * XkbVariantDflt= NULL;
-static char * XkbOptionsDflt= NULL;
-
-static char * XkbRulesUsed= NULL;
-static char * XkbModelUsed= NULL;
-static char * XkbLayoutUsed= NULL;
-static char * XkbVariantUsed= NULL;
-static char * XkbOptionsUsed= NULL;
-
-static XkbDescPtr xkb_cached_map = NULL;
-
-static Bool XkbWantRulesProp= XKB_DFLT_RULES_PROP;
-
-/***====================================================================***/
-
-/**
- * Get the current default XKB rules.
- * Caller must free the data in rmlvo.
- */
-void
-XkbGetRulesDflts(XkbRMLVOSet *rmlvo)
-{
- if (XkbRulesDflt) rmlvo->rules = XkbRulesDflt;
- else rmlvo->rules = XKB_DFLT_RULES;
- if (XkbModelDflt) rmlvo->model= XkbModelDflt;
- else rmlvo->model= XKB_DFLT_MODEL;
- if (XkbLayoutDflt) rmlvo->layout= XkbLayoutDflt;
- else rmlvo->layout= XKB_DFLT_LAYOUT;
- if (XkbVariantDflt) rmlvo->variant= XkbVariantDflt;
- else rmlvo->variant= XKB_DFLT_VARIANT;
- if (XkbOptionsDflt) rmlvo->options= XkbOptionsDflt;
- else rmlvo->options= XKB_DFLT_OPTIONS;
-
- rmlvo->rules = strdup(rmlvo->rules);
- rmlvo->model = strdup(rmlvo->model);
- rmlvo->layout = strdup(rmlvo->layout);
- rmlvo->variant = strdup(rmlvo->variant);
- rmlvo->options = strdup(rmlvo->options);
-}
-
-void
-XkbFreeRMLVOSet(XkbRMLVOSet *rmlvo, Bool freeRMLVO)
-{
- if (!rmlvo)
- return;
-
- free(rmlvo->rules);
- free(rmlvo->model);
- free(rmlvo->layout);
- free(rmlvo->variant);
- free(rmlvo->options);
-
- if (freeRMLVO)
- free(rmlvo);
- else
- memset(rmlvo, 0, sizeof(XkbRMLVOSet));
-}
-
-static Bool
-XkbWriteRulesProp(ClientPtr client, pointer closure)
-{
-int len,out;
-Atom name;
-char * pval;
-
- len= (XkbRulesUsed?strlen(XkbRulesUsed):0);
- len+= (XkbModelUsed?strlen(XkbModelUsed):0);
- len+= (XkbLayoutUsed?strlen(XkbLayoutUsed):0);
- len+= (XkbVariantUsed?strlen(XkbVariantUsed):0);
- len+= (XkbOptionsUsed?strlen(XkbOptionsUsed):0);
- if (len<1)
- return TRUE;
-
- len+= 5; /* trailing NULs */
-
- name= MakeAtom(_XKB_RF_NAMES_PROP_ATOM,strlen(_XKB_RF_NAMES_PROP_ATOM),1);
- if (name==None) {
- ErrorF("[xkb] Atom error: %s not created\n",_XKB_RF_NAMES_PROP_ATOM);
- return TRUE;
- }
- pval= (char*) malloc(len);
- if (!pval) {
- ErrorF("[xkb] Allocation error: %s proprerty not created\n",
- _XKB_RF_NAMES_PROP_ATOM);
- return TRUE;
- }
- out= 0;
- if (XkbRulesUsed) {
- strcpy(&pval[out],XkbRulesUsed);
- out+= strlen(XkbRulesUsed);
- }
- pval[out++]= '\0';
- if (XkbModelUsed) {
- strcpy(&pval[out],XkbModelUsed);
- out+= strlen(XkbModelUsed);
- }
- pval[out++]= '\0';
- if (XkbLayoutUsed) {
- strcpy(&pval[out],XkbLayoutUsed);
- out+= strlen(XkbLayoutUsed);
- }
- pval[out++]= '\0';
- if (XkbVariantUsed) {
- strcpy(&pval[out],XkbVariantUsed);
- out+= strlen(XkbVariantUsed);
- }
- pval[out++]= '\0';
- if (XkbOptionsUsed) {
- strcpy(&pval[out],XkbOptionsUsed);
- out+= strlen(XkbOptionsUsed);
- }
- pval[out++]= '\0';
- if (out!=len) {
- ErrorF("[xkb] Internal Error! bad size (%d!=%d) for _XKB_RULES_NAMES\n",
- out,len);
- }
- dixChangeWindowProperty(serverClient, screenInfo.screens[0]->root, name, XA_STRING, 8,
- PropModeReplace, len, pval, TRUE);
- free(pval);
- return TRUE;
-}
-
-static void
-XkbSetRulesUsed(XkbRMLVOSet *rmlvo)
-{
- free(XkbRulesUsed);
- XkbRulesUsed= (rmlvo->rules?_XkbDupString(rmlvo->rules):NULL);
- free(XkbModelUsed);
- XkbModelUsed= (rmlvo->model?_XkbDupString(rmlvo->model):NULL);
- free(XkbLayoutUsed);
- XkbLayoutUsed= (rmlvo->layout?_XkbDupString(rmlvo->layout):NULL);
- free(XkbVariantUsed);
- XkbVariantUsed= (rmlvo->variant?_XkbDupString(rmlvo->variant):NULL);
- free(XkbOptionsUsed);
- XkbOptionsUsed= (rmlvo->options?_XkbDupString(rmlvo->options):NULL);
- if (XkbWantRulesProp)
- QueueWorkProc(XkbWriteRulesProp,NULL,NULL);
- return;
-}
-
-void
-XkbSetRulesDflts(XkbRMLVOSet *rmlvo)
-{
- if (rmlvo->rules) {
- free(XkbRulesDflt);
- XkbRulesDflt= _XkbDupString(rmlvo->rules);
- }
- if (rmlvo->model) {
- free(XkbModelDflt);
- XkbModelDflt= _XkbDupString(rmlvo->model);
- }
- if (rmlvo->layout) {
- free(XkbLayoutDflt);
- XkbLayoutDflt= _XkbDupString(rmlvo->layout);
- }
- if (rmlvo->variant) {
- free(XkbVariantDflt);
- XkbVariantDflt= _XkbDupString(rmlvo->variant);
- }
- if (rmlvo->options) {
- free(XkbOptionsDflt);
- XkbOptionsDflt= _XkbDupString(rmlvo->options);
- }
- return;
-}
-
-void
-XkbDeleteRulesDflts(void)
-{
- free(XkbRulesDflt);
- XkbRulesDflt = NULL;
- free(XkbModelDflt);
- XkbModelDflt = NULL;
- free(XkbLayoutDflt);
- XkbLayoutDflt = NULL;
- free(XkbVariantDflt);
- XkbVariantDflt = NULL;
- free(XkbOptionsDflt);
- XkbOptionsDflt = NULL;
-
- XkbFreeKeyboard(xkb_cached_map, XkbAllComponentsMask, TRUE);
- xkb_cached_map = NULL;
-}
-
-#define DIFFERS(a, b) (strcmp((a) ? (a) : "", (b) ? (b) : "") != 0)
-
-static Bool
-XkbCompareUsedRMLVO(XkbRMLVOSet *rmlvo)
-{
- if (DIFFERS(rmlvo->rules, XkbRulesUsed) ||
- DIFFERS(rmlvo->model, XkbModelUsed) ||
- DIFFERS(rmlvo->layout, XkbLayoutUsed) ||
- DIFFERS(rmlvo->variant, XkbVariantUsed) ||
- DIFFERS(rmlvo->options, XkbOptionsUsed))
- return FALSE;
- return TRUE;
-}
-
-#undef DIFFERS
-
-/***====================================================================***/
-
-#include "xkbDflts.h"
-
-static Bool
-XkbInitKeyTypes(XkbDescPtr xkb)
-{
- if (xkb->defined & XkmTypesMask)
- return TRUE;
-
- initTypeNames(NULL);
- if (XkbAllocClientMap(xkb,XkbKeyTypesMask,num_dflt_types)!=Success)
- return FALSE;
- if (XkbCopyKeyTypes(dflt_types,xkb->map->types,num_dflt_types)!=
- Success) {
- return FALSE;
- }
- xkb->map->size_types= xkb->map->num_types= num_dflt_types;
- return TRUE;
-}
-
-static void
-XkbInitRadioGroups(XkbSrvInfoPtr xkbi)
-{
- xkbi->nRadioGroups = 0;
- xkbi->radioGroups = NULL;
- return;
-}
-
-
-static Status
-XkbInitCompatStructs(XkbDescPtr xkb)
-{
-register int i;
-XkbCompatMapPtr compat;
-
- if (xkb->defined & XkmCompatMapMask)
- return TRUE;
-
- if (XkbAllocCompatMap(xkb,XkbAllCompatMask,num_dfltSI)!=Success)
- return BadAlloc;
- compat = xkb->compat;
- if (compat->sym_interpret) {
- compat->num_si = num_dfltSI;
- memcpy((char *)compat->sym_interpret,(char *)dfltSI,sizeof(dfltSI));
- }
- for (i=0;i<XkbNumKbdGroups;i++) {
- compat->groups[i]= compatMap.groups[i];
- if (compat->groups[i].vmods!=0) {
- unsigned mask;
- mask= XkbMaskForVMask(xkb,compat->groups[i].vmods);
- compat->groups[i].mask= compat->groups[i].real_mods|mask;
- }
- else compat->groups[i].mask= compat->groups[i].real_mods;
- }
- return Success;
-}
-
-static void
-XkbInitSemantics(XkbDescPtr xkb)
-{
- XkbInitKeyTypes(xkb);
- XkbInitCompatStructs(xkb);
- return;
-}
-
-/***====================================================================***/
-
-static Status
-XkbInitNames(XkbSrvInfoPtr xkbi)
-{
-XkbDescPtr xkb;
-XkbNamesPtr names;
-Status rtrn;
-Atom unknown;
-
- xkb= xkbi->desc;
- if ((rtrn=XkbAllocNames(xkb,XkbAllNamesMask,0,0))!=Success)
- return rtrn;
- unknown= CREATE_ATOM("unknown");
- names = xkb->names;
- if (names->keycodes==None) names->keycodes= unknown;
- if (names->geometry==None) names->geometry= unknown;
- if (names->phys_symbols==None) names->phys_symbols= unknown;
- if (names->symbols==None) names->symbols= unknown;
- if (names->types==None) names->types= unknown;
- if (names->compat==None) names->compat= unknown;
- if (!(xkb->defined & XkmVirtualModsMask)) {
- if (names->vmods[vmod_NumLock]==None)
- names->vmods[vmod_NumLock]= CREATE_ATOM("NumLock");
- if (names->vmods[vmod_Alt]==None)
- names->vmods[vmod_Alt]= CREATE_ATOM("Alt");
- if (names->vmods[vmod_AltGr]==None)
- names->vmods[vmod_AltGr]= CREATE_ATOM("ModeSwitch");
- }
-
- if (!(xkb->defined & XkmIndicatorsMask) ||
- !(xkb->defined & XkmGeometryMask)) {
- initIndicatorNames(NULL,xkb);
- if (names->indicators[LED_CAPS-1]==None)
- names->indicators[LED_CAPS-1] = CREATE_ATOM("Caps Lock");
- if (names->indicators[LED_NUM-1]==None)
- names->indicators[LED_NUM-1] = CREATE_ATOM("Num Lock");
- if (names->indicators[LED_SCROLL-1]==None)
- names->indicators[LED_SCROLL-1] = CREATE_ATOM("Scroll Lock");
-#ifdef LED_COMPOSE
- if (names->indicators[LED_COMPOSE-1]==None)
- names->indicators[LED_COMPOSE-1] = CREATE_ATOM("Compose");
-#endif
- }
-
- if (xkb->geom!=NULL)
- names->geometry= xkb->geom->name;
- else names->geometry= unknown;
-
- return Success;
-}
-
-static Status
-XkbInitIndicatorMap(XkbSrvInfoPtr xkbi)
-{
-XkbDescPtr xkb;
-XkbIndicatorPtr map;
-XkbSrvLedInfoPtr sli;
-
- xkb= xkbi->desc;
- if (XkbAllocIndicatorMaps(xkb)!=Success)
- return BadAlloc;
-
- if (!(xkb->defined & XkmIndicatorsMask)) {
- map= xkb->indicators;
- map->phys_indicators = PHYS_LEDS;
- map->maps[LED_CAPS-1].flags= XkbIM_NoExplicit;
- map->maps[LED_CAPS-1].which_mods= XkbIM_UseLocked;
- map->maps[LED_CAPS-1].mods.mask= LockMask;
- map->maps[LED_CAPS-1].mods.real_mods= LockMask;
-
- map->maps[LED_NUM-1].flags= XkbIM_NoExplicit;
- map->maps[LED_NUM-1].which_mods= XkbIM_UseLocked;
- map->maps[LED_NUM-1].mods.mask= 0;
- map->maps[LED_NUM-1].mods.real_mods= 0;
- map->maps[LED_NUM-1].mods.vmods= vmod_NumLockMask;
-
- map->maps[LED_SCROLL-1].flags= XkbIM_NoExplicit;
- map->maps[LED_SCROLL-1].which_mods= XkbIM_UseLocked;
- map->maps[LED_SCROLL-1].mods.mask= Mod3Mask;
- map->maps[LED_SCROLL-1].mods.real_mods= Mod3Mask;
- }
-
- sli= XkbFindSrvLedInfo(xkbi->device,XkbDfltXIClass,XkbDfltXIId,0);
- if (sli)
- XkbCheckIndicatorMaps(xkbi->device,sli,XkbAllIndicatorsMask);
-
- return Success;
-}
-
-static Status
-XkbInitControls(DeviceIntPtr pXDev,XkbSrvInfoPtr xkbi)
-{
-XkbDescPtr xkb;
-XkbControlsPtr ctrls;
-
- xkb= xkbi->desc;
- /* 12/31/94 (ef) -- XXX! Should check if controls loaded from file */
- if (XkbAllocControls(xkb,XkbAllControlsMask)!=Success)
- FatalError("Couldn't allocate keyboard controls\n");
- ctrls= xkb->ctrls;
- if (!(xkb->defined & XkmSymbolsMask))
- ctrls->num_groups = 1;
- ctrls->groups_wrap = XkbSetGroupInfo(1,XkbWrapIntoRange,0);
- ctrls->internal.mask = 0;
- ctrls->internal.real_mods = 0;
- ctrls->internal.vmods = 0;
- ctrls->ignore_lock.mask = 0;
- ctrls->ignore_lock.real_mods = 0;
- ctrls->ignore_lock.vmods = 0;
- ctrls->enabled_ctrls = XkbAccessXTimeoutMask|XkbRepeatKeysMask|
- XkbMouseKeysAccelMask|XkbAudibleBellMask|
- XkbIgnoreGroupLockMask;
- if (XkbWantAccessX)
- ctrls->enabled_ctrls|= XkbAccessXKeysMask;
- AccessXInit(pXDev);
- return Success;
-}
-
-_X_EXPORT Bool
-InitKeyboardDeviceStruct(DeviceIntPtr dev, XkbRMLVOSet *rmlvo,
- BellProcPtr bell_func, KbdCtrlProcPtr ctrl_func)
-{
- int i;
- unsigned int check;
- XkbSrvInfoPtr xkbi;
- XkbDescPtr xkb;
- XkbSrvLedInfoPtr sli;
- XkbChangesRec changes;
- XkbEventCauseRec cause;
- XkbRMLVOSet rmlvo_dflts = { NULL };
-
- if (dev->key || dev->kbdfeed)
- return FALSE;
-
- if (!rmlvo)
- {
- rmlvo = &rmlvo_dflts;
- XkbGetRulesDflts(rmlvo);
- }
-
-
- memset(&changes, 0, sizeof(changes));
- XkbSetCauseUnknown(&cause);
-
- dev->key = calloc(1, sizeof(*dev->key));
- if (!dev->key) {
- ErrorF("XKB: Failed to allocate key class\n");
- return FALSE;
- }
- dev->key->sourceid = dev->id;
-
- dev->kbdfeed = calloc(1, sizeof(*dev->kbdfeed));
- if (!dev->kbdfeed) {
- ErrorF("XKB: Failed to allocate key feedback class\n");
- goto unwind_key;
- }
-
- xkbi = calloc(1, sizeof(*xkbi));
- if (!xkbi) {
- ErrorF("XKB: Failed to allocate XKB info\n");
- goto unwind_kbdfeed;
- }
- dev->key->xkbInfo = xkbi;
-
- if (xkb_cached_map && !XkbCompareUsedRMLVO(rmlvo)) {
- XkbFreeKeyboard(xkb_cached_map, XkbAllComponentsMask, TRUE);
- xkb_cached_map = NULL;
- }
-
- if (xkb_cached_map)
- LogMessageVerb(X_INFO, 4, "XKB: Reusing cached keymap\n");
- else {
- xkb_cached_map = XkbCompileKeymap(dev, rmlvo);
- if (!xkb_cached_map) {
- ErrorF("XKB: Failed to compile keymap\n");
- goto unwind_info;
- }
- }
-
- xkb = XkbAllocKeyboard();
- if (!xkb) {
- ErrorF("XKB: Failed to allocate keyboard description\n");
- goto unwind_info;
- }
-
- if (!XkbCopyKeymap(xkb, xkb_cached_map)) {
- ErrorF("XKB: Failed to copy keymap\n");
- goto unwind_desc;
- }
- xkb->defined = xkb_cached_map->defined;
- xkb->flags = xkb_cached_map->flags;
- xkb->device_spec = xkb_cached_map->device_spec;
- xkbi->desc = xkb;
-
- if (xkb->min_key_code == 0)
- xkb->min_key_code = 8;
- if (xkb->max_key_code == 0)
- xkb->max_key_code = 255;
-
- i = XkbNumKeys(xkb) / 3 + 1;
- if (XkbAllocClientMap(xkb, XkbAllClientInfoMask, 0) != Success)
- goto unwind_desc;
- if (XkbAllocServerMap(xkb, XkbAllServerInfoMask, i) != Success)
- goto unwind_desc;
-
- xkbi->dfltPtrDelta = 1;
- xkbi->device = dev;
-
- XkbInitSemantics(xkb);
- XkbInitNames(xkbi);
- XkbInitRadioGroups(xkbi);
-
- XkbInitControls(dev, xkbi);
-
- XkbInitIndicatorMap(xkbi);
-
- XkbUpdateActions(dev, xkb->min_key_code, XkbNumKeys(xkb), &changes,
- &check, &cause);
-
- InitFocusClassDeviceStruct(dev);
-
- xkbi->kbdProc = ctrl_func;
- dev->kbdfeed->BellProc = bell_func;
- dev->kbdfeed->CtrlProc = XkbDDXKeybdCtrlProc;
-
- dev->kbdfeed->ctrl = defaultKeyboardControl;
- if (dev->kbdfeed->ctrl.autoRepeat)
- xkb->ctrls->enabled_ctrls |= XkbRepeatKeysMask;
-
- memcpy(dev->kbdfeed->ctrl.autoRepeats, xkb->ctrls->per_key_repeat,
- XkbPerKeyBitArraySize);
-
- sli = XkbFindSrvLedInfo(dev, XkbDfltXIClass, XkbDfltXIId, 0);
- if (sli)
- XkbCheckIndicatorMaps(dev, sli, XkbAllIndicatorsMask);
- else
- DebugF("XKB: No indicator feedback in XkbFinishInit!\n");
-
- dev->kbdfeed->CtrlProc(dev,&dev->kbdfeed->ctrl);
-
- XkbSetRulesDflts(rmlvo);
- XkbSetRulesUsed(rmlvo);
- XkbFreeRMLVOSet(&rmlvo_dflts, FALSE);
-
- return TRUE;
-
-unwind_desc:
- XkbFreeKeyboard(xkb, 0, TRUE);
-unwind_info:
- free(xkbi);
- dev->key->xkbInfo = NULL;
-unwind_kbdfeed:
- free(dev->kbdfeed);
- dev->kbdfeed = NULL;
-unwind_key:
- free(dev->key);
- dev->key = NULL;
- return FALSE;
-}
-
-
-/***====================================================================***/
-
- /*
- * Be very careful about what does and doesn't get freed by this
- * function. To reduce fragmentation, XkbInitDevice allocates a
- * single huge block per device and divides it up into most of the
- * fixed-size structures for the device. Don't free anything that
- * is part of this larger block.
- */
-void
-XkbFreeInfo(XkbSrvInfoPtr xkbi)
-{
- free(xkbi->radioGroups);
- xkbi->radioGroups = NULL;
- if (xkbi->mouseKeyTimer) {
- TimerFree(xkbi->mouseKeyTimer);
- xkbi->mouseKeyTimer= NULL;
- }
- if (xkbi->slowKeysTimer) {
- TimerFree(xkbi->slowKeysTimer);
- xkbi->slowKeysTimer= NULL;
- }
- if (xkbi->bounceKeysTimer) {
- TimerFree(xkbi->bounceKeysTimer);
- xkbi->bounceKeysTimer= NULL;
- }
- if (xkbi->repeatKeyTimer) {
- TimerFree(xkbi->repeatKeyTimer);
- xkbi->repeatKeyTimer= NULL;
- }
- if (xkbi->krgTimer) {
- TimerFree(xkbi->krgTimer);
- xkbi->krgTimer= NULL;
- }
- xkbi->beepType= _BEEP_NONE;
- if (xkbi->beepTimer) {
- TimerFree(xkbi->beepTimer);
- xkbi->beepTimer= NULL;
- }
- if (xkbi->desc) {
- XkbFreeKeyboard(xkbi->desc,XkbAllComponentsMask,TRUE);
- xkbi->desc= NULL;
- }
- free(xkbi);
- return;
-}
-
-/***====================================================================***/
-
-extern int XkbDfltRepeatDelay;
-extern int XkbDfltRepeatInterval;
-
-extern unsigned short XkbDfltAccessXTimeout;
-extern unsigned int XkbDfltAccessXTimeoutMask;
-extern unsigned int XkbDfltAccessXFeedback;
-extern unsigned char XkbDfltAccessXOptions;
-
-int
-XkbProcessArguments(int argc,char *argv[],int i)
-{
- if (strncmp(argv[i], "-xkbdir", 7) == 0) {
- if(++i < argc) {
-#if !defined(WIN32) && !defined(__CYGWIN__)
- if (getuid() != geteuid()) {
- LogMessage(X_WARNING, "-xkbdir is not available for setuid X servers\n");
- return -1;
- } else
-#endif
- {
- if (strlen(argv[i]) < PATH_MAX) {
- XkbBaseDirectory= argv[i];
- return 2;
- } else {
- LogMessage(X_ERROR, "-xkbdir pathname too long\n");
- return -1;
- }
- }
- }
- else {
- return -1;
- }
- }
- else if ((strncmp(argv[i],"-accessx",8)==0)||
- (strncmp(argv[i],"+accessx",8)==0)) {
- int j=1;
- if (argv[i][0]=='-')
- XkbWantAccessX= 0;
- else {
- XkbWantAccessX= 1;
-
- if ( ((i+1)<argc) && (isdigit(argv[i+1][0])) ) {
- XkbDfltAccessXTimeout = atoi(argv[++i]);
- j++;
-
- if ( ((i+1)<argc) && (isdigit(argv[i+1][0])) ) {
- /*
- * presumption that the reasonably useful range of
- * values fits in 0..MAXINT since SunOS 4 doesn't
- * have strtoul.
- */
- XkbDfltAccessXTimeoutMask=(unsigned int)
- strtol(argv[++i],NULL,16);
- j++;
- }
- if ( ((i+1)<argc) && (isdigit(argv[i+1][0])) ) {
- if (argv[++i][0] == '1' )
- XkbDfltAccessXFeedback=XkbAccessXFeedbackMask;
- else
- XkbDfltAccessXFeedback=0;
- j++;
- }
- if ( ((i+1)<argc) && (isdigit(argv[i+1][0])) ) {
- XkbDfltAccessXOptions=(unsigned char)
- strtol(argv[++i],NULL,16);
- j++;
- }
- }
- }
- return j;
- }
- if ((strcmp(argv[i], "-ardelay") == 0) ||
- (strcmp (argv[i], "-ar1") == 0)) { /* -ardelay int */
- if (++i >= argc) UseMsg ();
- XkbDfltRepeatDelay = (long)atoi(argv[i]);
- return 2;
- }
- if ((strcmp(argv[i], "-arinterval") == 0) ||
- (strcmp (argv[i], "-ar2") == 0)) { /* -arinterval int */
- if (++i >= argc) UseMsg ();
- XkbDfltRepeatInterval = (long)atoi(argv[i]);
- return 2;
- }
- return 0;
-}
-
-void
-XkbUseMsg(void)
-{
- ErrorF("[+-]accessx [ timeout [ timeout_mask [ feedback [ options_mask] ] ] ]\n");
- ErrorF(" enable/disable accessx key sequences\n");
- ErrorF("-ardelay set XKB autorepeat delay\n");
- ErrorF("-arinterval set XKB autorepeat interval\n");
-}
+/************************************************************ +Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc. + +Permission 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 that both that copyright +notice and this permission notice appear in supporting +documentation, and that the name of Silicon Graphics not be +used in advertising or publicity pertaining to distribution +of the software without specific prior written permission. +Silicon Graphics makes no representation about the suitability +of this software for any purpose. It is provided "as is" +without any express or implied warranty. + +SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS +SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON +GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL +DAMAGES OR ANY 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 THIS SOFTWARE. + +********************************************************/ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include <xkb-config.h> + +#include <stdio.h> +#include <stdlib.h> +#include <ctype.h> +#include <unistd.h> +#include <math.h> +#include <X11/X.h> +#include <X11/Xproto.h> +#include <X11/keysym.h> +#include <X11/Xatom.h> +#include "misc.h" +#include "inputstr.h" +#include "opaque.h" +#include "property.h" +#include "scrnintstr.h" +#define XKBSRV_NEED_FILE_FUNCS +#include <xkbsrv.h> +#include "xkbgeom.h" +#include <X11/extensions/XKMformat.h> +#include "xkbfile.h" +#include "xkb.h" + +#define CREATE_ATOM(s) MakeAtom(s,sizeof(s)-1,1) + +#if defined(__alpha) || defined(__alpha__) +#define LED_COMPOSE 2 +#define LED_CAPS 3 +#define LED_SCROLL 4 +#define LED_NUM 5 +#define PHYS_LEDS 0x1f +#else +#ifdef sun +#define LED_NUM 1 +#define LED_SCROLL 2 +#define LED_COMPOSE 3 +#define LED_CAPS 4 +#define PHYS_LEDS 0x0f +#else +#define LED_CAPS 1 +#define LED_NUM 2 +#define LED_SCROLL 3 +#define PHYS_LEDS 0x07 +#endif +#endif + +#define MAX_TOC 16 +typedef struct _SrvXkmInfo { + DeviceIntPtr dev; + FILE * file; + XkbDescPtr xkb; +} SrvXkmInfo; + + +/***====================================================================***/ + +#ifndef XKB_DFLT_RULES_PROP +#define XKB_DFLT_RULES_PROP TRUE +#endif + +char * XkbBaseDirectory= XKB_BASE_DIRECTORY; +char * XkbBinDirectory= XKB_BIN_DIRECTORY; +static int XkbWantAccessX= 0; + +static char * XkbRulesDflt= NULL; +static char * XkbModelDflt= NULL; +static char * XkbLayoutDflt= NULL; +static char * XkbVariantDflt= NULL; +static char * XkbOptionsDflt= NULL; + +static char * XkbRulesUsed= NULL; +static char * XkbModelUsed= NULL; +static char * XkbLayoutUsed= NULL; +static char * XkbVariantUsed= NULL; +static char * XkbOptionsUsed= NULL; + +static XkbDescPtr xkb_cached_map = NULL; + +static Bool XkbWantRulesProp= XKB_DFLT_RULES_PROP; + +/***====================================================================***/ + +/** + * Get the current default XKB rules. + * Caller must free the data in rmlvo. + */ +void +XkbGetRulesDflts(XkbRMLVOSet *rmlvo) +{ + if (XkbRulesDflt) rmlvo->rules = XkbRulesDflt; + else rmlvo->rules = XKB_DFLT_RULES; + if (XkbModelDflt) rmlvo->model= XkbModelDflt; + else rmlvo->model= XKB_DFLT_MODEL; + if (XkbLayoutDflt) rmlvo->layout= XkbLayoutDflt; + else rmlvo->layout= XKB_DFLT_LAYOUT; + if (XkbVariantDflt) rmlvo->variant= XkbVariantDflt; + else rmlvo->variant= XKB_DFLT_VARIANT; + if (XkbOptionsDflt) rmlvo->options= XkbOptionsDflt; + else rmlvo->options= XKB_DFLT_OPTIONS; + + rmlvo->rules = strdup(rmlvo->rules); + rmlvo->model = strdup(rmlvo->model); + rmlvo->layout = strdup(rmlvo->layout); + rmlvo->variant = strdup(rmlvo->variant); + rmlvo->options = strdup(rmlvo->options); +} + +void +XkbFreeRMLVOSet(XkbRMLVOSet *rmlvo, Bool freeRMLVO) +{ + if (!rmlvo) + return; + + free(rmlvo->rules); + free(rmlvo->model); + free(rmlvo->layout); + free(rmlvo->variant); + free(rmlvo->options); + + if (freeRMLVO) + free(rmlvo); + else + memset(rmlvo, 0, sizeof(XkbRMLVOSet)); +} + +static Bool +XkbWriteRulesProp(ClientPtr client, pointer closure) +{ +int len,out; +Atom name; +char * pval; + + len= (XkbRulesUsed?strlen(XkbRulesUsed):0); + len+= (XkbModelUsed?strlen(XkbModelUsed):0); + len+= (XkbLayoutUsed?strlen(XkbLayoutUsed):0); + len+= (XkbVariantUsed?strlen(XkbVariantUsed):0); + len+= (XkbOptionsUsed?strlen(XkbOptionsUsed):0); + if (len<1) + return TRUE; + + len+= 5; /* trailing NULs */ + + name= MakeAtom(_XKB_RF_NAMES_PROP_ATOM,strlen(_XKB_RF_NAMES_PROP_ATOM),1); + if (name==None) { + ErrorF("[xkb] Atom error: %s not created\n",_XKB_RF_NAMES_PROP_ATOM); + return TRUE; + } + pval= (char*) malloc(len); + if (!pval) { + ErrorF("[xkb] Allocation error: %s proprerty not created\n", + _XKB_RF_NAMES_PROP_ATOM); + return TRUE; + } + out= 0; + if (XkbRulesUsed) { + strcpy(&pval[out],XkbRulesUsed); + out+= strlen(XkbRulesUsed); + } + pval[out++]= '\0'; + if (XkbModelUsed) { + strcpy(&pval[out],XkbModelUsed); + out+= strlen(XkbModelUsed); + } + pval[out++]= '\0'; + if (XkbLayoutUsed) { + strcpy(&pval[out],XkbLayoutUsed); + out+= strlen(XkbLayoutUsed); + } + pval[out++]= '\0'; + if (XkbVariantUsed) { + strcpy(&pval[out],XkbVariantUsed); + out+= strlen(XkbVariantUsed); + } + pval[out++]= '\0'; + if (XkbOptionsUsed) { + strcpy(&pval[out],XkbOptionsUsed); + out+= strlen(XkbOptionsUsed); + } + pval[out++]= '\0'; + if (out!=len) { + ErrorF("[xkb] Internal Error! bad size (%d!=%d) for _XKB_RULES_NAMES\n", + out,len); + } + dixChangeWindowProperty(serverClient, screenInfo.screens[0]->root, name, XA_STRING, 8, + PropModeReplace, len, pval, TRUE); + free(pval); + return TRUE; +} + +static void +XkbSetRulesUsed(XkbRMLVOSet *rmlvo) +{ + free(XkbRulesUsed); + XkbRulesUsed= (rmlvo->rules?Xstrdup(rmlvo->rules):NULL); + free(XkbModelUsed); + XkbModelUsed= (rmlvo->model?Xstrdup(rmlvo->model):NULL); + free(XkbLayoutUsed); + XkbLayoutUsed= (rmlvo->layout?Xstrdup(rmlvo->layout):NULL); + free(XkbVariantUsed); + XkbVariantUsed= (rmlvo->variant?Xstrdup(rmlvo->variant):NULL); + free(XkbOptionsUsed); + XkbOptionsUsed= (rmlvo->options?Xstrdup(rmlvo->options):NULL); + if (XkbWantRulesProp) + QueueWorkProc(XkbWriteRulesProp,NULL,NULL); + return; +} + +void +XkbSetRulesDflts(XkbRMLVOSet *rmlvo) +{ + if (rmlvo->rules) { + free(XkbRulesDflt); + XkbRulesDflt= Xstrdup(rmlvo->rules); + } + if (rmlvo->model) { + free(XkbModelDflt); + XkbModelDflt= Xstrdup(rmlvo->model); + } + if (rmlvo->layout) { + free(XkbLayoutDflt); + XkbLayoutDflt= Xstrdup(rmlvo->layout); + } + if (rmlvo->variant) { + free(XkbVariantDflt); + XkbVariantDflt= Xstrdup(rmlvo->variant); + } + if (rmlvo->options) { + free(XkbOptionsDflt); + XkbOptionsDflt= Xstrdup(rmlvo->options); + } + return; +} + +void +XkbDeleteRulesDflts(void) +{ + free(XkbRulesDflt); + XkbRulesDflt = NULL; + free(XkbModelDflt); + XkbModelDflt = NULL; + free(XkbLayoutDflt); + XkbLayoutDflt = NULL; + free(XkbVariantDflt); + XkbVariantDflt = NULL; + free(XkbOptionsDflt); + XkbOptionsDflt = NULL; + + XkbFreeKeyboard(xkb_cached_map, XkbAllComponentsMask, TRUE); + xkb_cached_map = NULL; +} + +#define DIFFERS(a, b) (strcmp((a) ? (a) : "", (b) ? (b) : "") != 0) + +static Bool +XkbCompareUsedRMLVO(XkbRMLVOSet *rmlvo) +{ + if (DIFFERS(rmlvo->rules, XkbRulesUsed) || + DIFFERS(rmlvo->model, XkbModelUsed) || + DIFFERS(rmlvo->layout, XkbLayoutUsed) || + DIFFERS(rmlvo->variant, XkbVariantUsed) || + DIFFERS(rmlvo->options, XkbOptionsUsed)) + return FALSE; + return TRUE; +} + +#undef DIFFERS + +/***====================================================================***/ + +#include "xkbDflts.h" + +static Bool +XkbInitKeyTypes(XkbDescPtr xkb) +{ + if (xkb->defined & XkmTypesMask) + return TRUE; + + initTypeNames(NULL); + if (XkbAllocClientMap(xkb,XkbKeyTypesMask,num_dflt_types)!=Success) + return FALSE; + if (XkbCopyKeyTypes(dflt_types,xkb->map->types,num_dflt_types)!= + Success) { + return FALSE; + } + xkb->map->size_types= xkb->map->num_types= num_dflt_types; + return TRUE; +} + +static void +XkbInitRadioGroups(XkbSrvInfoPtr xkbi) +{ + xkbi->nRadioGroups = 0; + xkbi->radioGroups = NULL; + return; +} + + +static Status +XkbInitCompatStructs(XkbDescPtr xkb) +{ +register int i; +XkbCompatMapPtr compat; + + if (xkb->defined & XkmCompatMapMask) + return TRUE; + + if (XkbAllocCompatMap(xkb,XkbAllCompatMask,num_dfltSI)!=Success) + return BadAlloc; + compat = xkb->compat; + if (compat->sym_interpret) { + compat->num_si = num_dfltSI; + memcpy((char *)compat->sym_interpret,(char *)dfltSI,sizeof(dfltSI)); + } + for (i=0;i<XkbNumKbdGroups;i++) { + compat->groups[i]= compatMap.groups[i]; + if (compat->groups[i].vmods!=0) { + unsigned mask; + mask= XkbMaskForVMask(xkb,compat->groups[i].vmods); + compat->groups[i].mask= compat->groups[i].real_mods|mask; + } + else compat->groups[i].mask= compat->groups[i].real_mods; + } + return Success; +} + +static void +XkbInitSemantics(XkbDescPtr xkb) +{ + XkbInitKeyTypes(xkb); + XkbInitCompatStructs(xkb); + return; +} + +/***====================================================================***/ + +static Status +XkbInitNames(XkbSrvInfoPtr xkbi) +{ +XkbDescPtr xkb; +XkbNamesPtr names; +Status rtrn; +Atom unknown; + + xkb= xkbi->desc; + if ((rtrn=XkbAllocNames(xkb,XkbAllNamesMask,0,0))!=Success) + return rtrn; + unknown= CREATE_ATOM("unknown"); + names = xkb->names; + if (names->keycodes==None) names->keycodes= unknown; + if (names->geometry==None) names->geometry= unknown; + if (names->phys_symbols==None) names->phys_symbols= unknown; + if (names->symbols==None) names->symbols= unknown; + if (names->types==None) names->types= unknown; + if (names->compat==None) names->compat= unknown; + if (!(xkb->defined & XkmVirtualModsMask)) { + if (names->vmods[vmod_NumLock]==None) + names->vmods[vmod_NumLock]= CREATE_ATOM("NumLock"); + if (names->vmods[vmod_Alt]==None) + names->vmods[vmod_Alt]= CREATE_ATOM("Alt"); + if (names->vmods[vmod_AltGr]==None) + names->vmods[vmod_AltGr]= CREATE_ATOM("ModeSwitch"); + } + + if (!(xkb->defined & XkmIndicatorsMask) || + !(xkb->defined & XkmGeometryMask)) { + initIndicatorNames(NULL,xkb); + if (names->indicators[LED_CAPS-1]==None) + names->indicators[LED_CAPS-1] = CREATE_ATOM("Caps Lock"); + if (names->indicators[LED_NUM-1]==None) + names->indicators[LED_NUM-1] = CREATE_ATOM("Num Lock"); + if (names->indicators[LED_SCROLL-1]==None) + names->indicators[LED_SCROLL-1] = CREATE_ATOM("Scroll Lock"); +#ifdef LED_COMPOSE + if (names->indicators[LED_COMPOSE-1]==None) + names->indicators[LED_COMPOSE-1] = CREATE_ATOM("Compose"); +#endif + } + + if (xkb->geom!=NULL) + names->geometry= xkb->geom->name; + else names->geometry= unknown; + + return Success; +} + +static Status +XkbInitIndicatorMap(XkbSrvInfoPtr xkbi) +{ +XkbDescPtr xkb; +XkbIndicatorPtr map; +XkbSrvLedInfoPtr sli; + + xkb= xkbi->desc; + if (XkbAllocIndicatorMaps(xkb)!=Success) + return BadAlloc; + + if (!(xkb->defined & XkmIndicatorsMask)) { + map= xkb->indicators; + map->phys_indicators = PHYS_LEDS; + map->maps[LED_CAPS-1].flags= XkbIM_NoExplicit; + map->maps[LED_CAPS-1].which_mods= XkbIM_UseLocked; + map->maps[LED_CAPS-1].mods.mask= LockMask; + map->maps[LED_CAPS-1].mods.real_mods= LockMask; + + map->maps[LED_NUM-1].flags= XkbIM_NoExplicit; + map->maps[LED_NUM-1].which_mods= XkbIM_UseLocked; + map->maps[LED_NUM-1].mods.mask= 0; + map->maps[LED_NUM-1].mods.real_mods= 0; + map->maps[LED_NUM-1].mods.vmods= vmod_NumLockMask; + + map->maps[LED_SCROLL-1].flags= XkbIM_NoExplicit; + map->maps[LED_SCROLL-1].which_mods= XkbIM_UseLocked; + map->maps[LED_SCROLL-1].mods.mask= Mod3Mask; + map->maps[LED_SCROLL-1].mods.real_mods= Mod3Mask; + } + + sli= XkbFindSrvLedInfo(xkbi->device,XkbDfltXIClass,XkbDfltXIId,0); + if (sli) + XkbCheckIndicatorMaps(xkbi->device,sli,XkbAllIndicatorsMask); + + return Success; +} + +static Status +XkbInitControls(DeviceIntPtr pXDev,XkbSrvInfoPtr xkbi) +{ +XkbDescPtr xkb; +XkbControlsPtr ctrls; + + xkb= xkbi->desc; + /* 12/31/94 (ef) -- XXX! Should check if controls loaded from file */ + if (XkbAllocControls(xkb,XkbAllControlsMask)!=Success) + FatalError("Couldn't allocate keyboard controls\n"); + ctrls= xkb->ctrls; + if (!(xkb->defined & XkmSymbolsMask)) + ctrls->num_groups = 1; + ctrls->groups_wrap = XkbSetGroupInfo(1,XkbWrapIntoRange,0); + ctrls->internal.mask = 0; + ctrls->internal.real_mods = 0; + ctrls->internal.vmods = 0; + ctrls->ignore_lock.mask = 0; + ctrls->ignore_lock.real_mods = 0; + ctrls->ignore_lock.vmods = 0; + ctrls->enabled_ctrls = XkbAccessXTimeoutMask|XkbRepeatKeysMask| + XkbMouseKeysAccelMask|XkbAudibleBellMask| + XkbIgnoreGroupLockMask; + if (XkbWantAccessX) + ctrls->enabled_ctrls|= XkbAccessXKeysMask; + AccessXInit(pXDev); + return Success; +} + +_X_EXPORT Bool +InitKeyboardDeviceStruct(DeviceIntPtr dev, XkbRMLVOSet *rmlvo, + BellProcPtr bell_func, KbdCtrlProcPtr ctrl_func) +{ + int i; + unsigned int check; + XkbSrvInfoPtr xkbi; + XkbDescPtr xkb; + XkbSrvLedInfoPtr sli; + XkbChangesRec changes; + XkbEventCauseRec cause; + XkbRMLVOSet rmlvo_dflts = { NULL }; + + if (dev->key || dev->kbdfeed) + return FALSE; + + if (!rmlvo) + { + rmlvo = &rmlvo_dflts; + XkbGetRulesDflts(rmlvo); + } + + + memset(&changes, 0, sizeof(changes)); + XkbSetCauseUnknown(&cause); + + dev->key = calloc(1, sizeof(*dev->key)); + if (!dev->key) { + ErrorF("XKB: Failed to allocate key class\n"); + return FALSE; + } + dev->key->sourceid = dev->id; + + dev->kbdfeed = calloc(1, sizeof(*dev->kbdfeed)); + if (!dev->kbdfeed) { + ErrorF("XKB: Failed to allocate key feedback class\n"); + goto unwind_key; + } + + xkbi = calloc(1, sizeof(*xkbi)); + if (!xkbi) { + ErrorF("XKB: Failed to allocate XKB info\n"); + goto unwind_kbdfeed; + } + dev->key->xkbInfo = xkbi; + + if (xkb_cached_map && !XkbCompareUsedRMLVO(rmlvo)) { + XkbFreeKeyboard(xkb_cached_map, XkbAllComponentsMask, TRUE); + xkb_cached_map = NULL; + } + + if (xkb_cached_map) + LogMessageVerb(X_INFO, 4, "XKB: Reusing cached keymap\n"); + else { + xkb_cached_map = XkbCompileKeymap(dev, rmlvo); + if (!xkb_cached_map) { + ErrorF("XKB: Failed to compile keymap\n"); + goto unwind_info; + } + } + + xkb = XkbAllocKeyboard(); + if (!xkb) { + ErrorF("XKB: Failed to allocate keyboard description\n"); + goto unwind_info; + } + + if (!XkbCopyKeymap(xkb, xkb_cached_map)) { + ErrorF("XKB: Failed to copy keymap\n"); + goto unwind_desc; + } + xkb->defined = xkb_cached_map->defined; + xkb->flags = xkb_cached_map->flags; + xkb->device_spec = xkb_cached_map->device_spec; + xkbi->desc = xkb; + + if (xkb->min_key_code == 0) + xkb->min_key_code = 8; + if (xkb->max_key_code == 0) + xkb->max_key_code = 255; + + i = XkbNumKeys(xkb) / 3 + 1; + if (XkbAllocClientMap(xkb, XkbAllClientInfoMask, 0) != Success) + goto unwind_desc; + if (XkbAllocServerMap(xkb, XkbAllServerInfoMask, i) != Success) + goto unwind_desc; + + xkbi->dfltPtrDelta = 1; + xkbi->device = dev; + + XkbInitSemantics(xkb); + XkbInitNames(xkbi); + XkbInitRadioGroups(xkbi); + + XkbInitControls(dev, xkbi); + + XkbInitIndicatorMap(xkbi); + + XkbUpdateActions(dev, xkb->min_key_code, XkbNumKeys(xkb), &changes, + &check, &cause); + + InitFocusClassDeviceStruct(dev); + + xkbi->kbdProc = ctrl_func; + dev->kbdfeed->BellProc = bell_func; + dev->kbdfeed->CtrlProc = XkbDDXKeybdCtrlProc; + + dev->kbdfeed->ctrl = defaultKeyboardControl; + if (dev->kbdfeed->ctrl.autoRepeat) + xkb->ctrls->enabled_ctrls |= XkbRepeatKeysMask; + + memcpy(dev->kbdfeed->ctrl.autoRepeats, xkb->ctrls->per_key_repeat, + XkbPerKeyBitArraySize); + + sli = XkbFindSrvLedInfo(dev, XkbDfltXIClass, XkbDfltXIId, 0); + if (sli) + XkbCheckIndicatorMaps(dev, sli, XkbAllIndicatorsMask); + else + DebugF("XKB: No indicator feedback in XkbFinishInit!\n"); + + dev->kbdfeed->CtrlProc(dev,&dev->kbdfeed->ctrl); + + XkbSetRulesDflts(rmlvo); + XkbSetRulesUsed(rmlvo); + XkbFreeRMLVOSet(&rmlvo_dflts, FALSE); + + return TRUE; + +unwind_desc: + XkbFreeKeyboard(xkb, 0, TRUE); +unwind_info: + free(xkbi); + dev->key->xkbInfo = NULL; +unwind_kbdfeed: + free(dev->kbdfeed); + dev->kbdfeed = NULL; +unwind_key: + free(dev->key); + dev->key = NULL; + return FALSE; +} + + +/***====================================================================***/ + + /* + * Be very careful about what does and doesn't get freed by this + * function. To reduce fragmentation, XkbInitDevice allocates a + * single huge block per device and divides it up into most of the + * fixed-size structures for the device. Don't free anything that + * is part of this larger block. + */ +void +XkbFreeInfo(XkbSrvInfoPtr xkbi) +{ + free(xkbi->radioGroups); + xkbi->radioGroups = NULL; + if (xkbi->mouseKeyTimer) { + TimerFree(xkbi->mouseKeyTimer); + xkbi->mouseKeyTimer= NULL; + } + if (xkbi->slowKeysTimer) { + TimerFree(xkbi->slowKeysTimer); + xkbi->slowKeysTimer= NULL; + } + if (xkbi->bounceKeysTimer) { + TimerFree(xkbi->bounceKeysTimer); + xkbi->bounceKeysTimer= NULL; + } + if (xkbi->repeatKeyTimer) { + TimerFree(xkbi->repeatKeyTimer); + xkbi->repeatKeyTimer= NULL; + } + if (xkbi->krgTimer) { + TimerFree(xkbi->krgTimer); + xkbi->krgTimer= NULL; + } + xkbi->beepType= _BEEP_NONE; + if (xkbi->beepTimer) { + TimerFree(xkbi->beepTimer); + xkbi->beepTimer= NULL; + } + if (xkbi->desc) { + XkbFreeKeyboard(xkbi->desc,XkbAllComponentsMask,TRUE); + xkbi->desc= NULL; + } + free(xkbi); + return; +} + +/***====================================================================***/ + +extern int XkbDfltRepeatDelay; +extern int XkbDfltRepeatInterval; + +extern unsigned short XkbDfltAccessXTimeout; +extern unsigned int XkbDfltAccessXTimeoutMask; +extern unsigned int XkbDfltAccessXFeedback; +extern unsigned char XkbDfltAccessXOptions; + +int +XkbProcessArguments(int argc,char *argv[],int i) +{ + if (strncmp(argv[i], "-xkbdir", 7) == 0) { + if(++i < argc) { +#if !defined(WIN32) && !defined(__CYGWIN__) + if (getuid() != geteuid()) { + LogMessage(X_WARNING, "-xkbdir is not available for setuid X servers\n"); + return -1; + } else +#endif + { + if (strlen(argv[i]) < PATH_MAX) { + XkbBaseDirectory= argv[i]; + return 2; + } else { + LogMessage(X_ERROR, "-xkbdir pathname too long\n"); + return -1; + } + } + } + else { + return -1; + } + } + else if ((strncmp(argv[i],"-accessx",8)==0)|| + (strncmp(argv[i],"+accessx",8)==0)) { + int j=1; + if (argv[i][0]=='-') + XkbWantAccessX= 0; + else { + XkbWantAccessX= 1; + + if ( ((i+1)<argc) && (isdigit(argv[i+1][0])) ) { + XkbDfltAccessXTimeout = atoi(argv[++i]); + j++; + + if ( ((i+1)<argc) && (isdigit(argv[i+1][0])) ) { + /* + * presumption that the reasonably useful range of + * values fits in 0..MAXINT since SunOS 4 doesn't + * have strtoul. + */ + XkbDfltAccessXTimeoutMask=(unsigned int) + strtol(argv[++i],NULL,16); + j++; + } + if ( ((i+1)<argc) && (isdigit(argv[i+1][0])) ) { + if (argv[++i][0] == '1' ) + XkbDfltAccessXFeedback=XkbAccessXFeedbackMask; + else + XkbDfltAccessXFeedback=0; + j++; + } + if ( ((i+1)<argc) && (isdigit(argv[i+1][0])) ) { + XkbDfltAccessXOptions=(unsigned char) + strtol(argv[++i],NULL,16); + j++; + } + } + } + return j; + } + if ((strcmp(argv[i], "-ardelay") == 0) || + (strcmp (argv[i], "-ar1") == 0)) { /* -ardelay int */ + if (++i >= argc) UseMsg (); + XkbDfltRepeatDelay = (long)atoi(argv[i]); + return 2; + } + if ((strcmp(argv[i], "-arinterval") == 0) || + (strcmp (argv[i], "-ar2") == 0)) { /* -arinterval int */ + if (++i >= argc) UseMsg (); + XkbDfltRepeatInterval = (long)atoi(argv[i]); + return 2; + } + return 0; +} + +void +XkbUseMsg(void) +{ + ErrorF("[+-]accessx [ timeout [ timeout_mask [ feedback [ options_mask] ] ] ]\n"); + ErrorF(" enable/disable accessx key sequences\n"); + ErrorF("-ardelay set XKB autorepeat delay\n"); + ErrorF("-arinterval set XKB autorepeat interval\n"); +} diff --git a/xorg-server/xkb/xkbfmisc.c b/xorg-server/xkb/xkbfmisc.c index 382b6ebba..dea347335 100644 --- a/xorg-server/xkb/xkbfmisc.c +++ b/xorg-server/xkb/xkbfmisc.c @@ -1,441 +1,441 @@ -/************************************************************
- Copyright (c) 1995 by Silicon Graphics Computer Systems, Inc.
-
- Permission 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 that both that copyright
- notice and this permission notice appear in supporting
- documentation, and that the name of Silicon Graphics not be
- used in advertising or publicity pertaining to distribution
- of the software without specific prior written permission.
- Silicon Graphics makes no representation about the suitability
- of this software for any purpose. It is provided "as is"
- without any express or implied warranty.
-
- SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
- SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
- AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
- GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
- DAMAGES OR ANY 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 THIS SOFTWARE.
-
- ********************************************************/
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#include <stdio.h>
-#include <ctype.h>
-#include <stdlib.h>
-
-#include <X11/Xos.h>
-#include <X11/Xfuncs.h>
-#include <X11/extensions/XKMformat.h>
-
-#include <X11/X.h>
-#include <X11/keysym.h>
-#include <X11/Xproto.h>
-#include "misc.h"
-#include "inputstr.h"
-#include "dix.h"
-#include "xkbstr.h"
-#define XKBSRV_NEED_FILE_FUNCS 1
-#include <xkbsrv.h>
-#include "xkbgeom.h"
-#include "xkb.h"
-
-unsigned
-_XkbKSCheckCase(KeySym ks)
-{
-unsigned set,rtrn;
-
- set= (ks & (~0xff)) >> 8;
- rtrn= 0;
- switch (set) {
- case 0: /* latin 1 */
- if (((ks>=XK_A)&&(ks<=XK_Z))||
- ((ks>=XK_Agrave)&&(ks<=XK_THORN)&&(ks!=XK_multiply))) {
- rtrn|= _XkbKSUpper;
- }
- if (((ks>=XK_a)&&(ks<=XK_z))||
- ((ks>=XK_agrave)&&(ks<=XK_ydiaeresis))) {
- rtrn|= _XkbKSLower;
- }
- break;
- case 1: /* latin 2 */
- if (((ks>=XK_Aogonek)&&(ks<=XK_Zabovedot)&&(ks!=XK_breve))||
- ((ks>=XK_Racute)&&(ks<=XK_Tcedilla))) {
- rtrn|= _XkbKSUpper;
- }
- if (((ks>=XK_aogonek)&&(ks<=XK_zabovedot)&&(ks!=XK_caron))||
- ((ks>=XK_racute)&&(ks<=XK_tcedilla))) {
- rtrn|= _XkbKSLower;
- }
- break;
- case 2: /* latin 3 */
- if (((ks>=XK_Hstroke)&&(ks<=XK_Jcircumflex))||
- ((ks>=XK_Cabovedot)&&(ks<=XK_Scircumflex))) {
- rtrn|= _XkbKSUpper;
- }
- if (((ks>=XK_hstroke)&&(ks<=XK_jcircumflex))||
- ((ks>=XK_cabovedot)&&(ks<=XK_scircumflex))) {
- rtrn|= _XkbKSLower;
- }
- break;
- case 3: /* latin 4 */
- if (((ks>=XK_Rcedilla)&&(ks<=XK_Tslash))||
- (ks==XK_ENG)||
- ((ks>=XK_Amacron)&&(ks<=XK_Umacron))) {
- rtrn|= _XkbKSUpper;
- }
- if (((ks>=XK_rcedilla)&&(ks<=XK_tslash))||
- (ks==XK_eng)||
- ((ks>=XK_amacron)&&(ks<=XK_umacron))) {
- rtrn|= _XkbKSLower;
- }
- break;
- case 18: /* latin 8 */
- if ((ks==XK_Babovedot)||
- ((ks>=XK_Dabovedot)&&(ks<=XK_Wacute))||
- ((ks>=XK_Ygrave)&&(ks<=XK_Fabovedot))||
- (ks==XK_Mabovedot)||
- (ks==XK_Pabovedot)||
- (ks==XK_Sabovedot)||
- (ks==XK_Wdiaeresis)||
- ((ks>=XK_Wcircumflex)&&(ks<=XK_Ycircumflex))) {
- rtrn|= _XkbKSUpper;
- }
- if ((ks==XK_babovedot)||
- (ks==XK_dabovedot)||
- (ks==XK_fabovedot)||
- (ks==XK_mabovedot)||
- ((ks>=XK_wgrave)&&(ks<=XK_wacute))||
- (ks==XK_ygrave)||
- ((ks>=XK_wdiaeresis)&&(ks<=XK_ycircumflex))) {
- rtrn|= _XkbKSLower;
- }
- break;
- case 19: /* latin 9 */
- if ((ks==XK_OE)||(ks==XK_Ydiaeresis)) {
- rtrn|= _XkbKSUpper;
- }
- if (ks==XK_oe) {
- rtrn|= _XkbKSLower;
- }
- break;
- }
- return rtrn;
-}
-
-/***===================================================================***/
-
-static Bool
-XkbWriteSectionFromName(FILE *file,char *sectionName,char *name)
-{
- fprintf(file," xkb_%-20s { include \"%s\" };\n",sectionName,name);
- return TRUE;
-}
-
-#define NEED_DESC(n) ((!n)||((n)[0]=='+')||((n)[0]=='|')||(strchr((n),'%')))
-#define COMPLETE(n) ((n)&&(!NEED_DESC(n)))
-
-/* ARGSUSED */
-static void
-_AddIncl( FILE * file,
- XkbDescPtr xkb,
- Bool topLevel,
- Bool showImplicit,
- int index,
- void * priv)
-{
- if ((priv)&&(strcmp((char *)priv,"%")!=0))
- fprintf(file," include \"%s\"\n",(char *)priv);
- return;
-}
-
-Bool
-XkbWriteXKBKeymapForNames( FILE * file,
- XkbComponentNamesPtr names,
- XkbDescPtr xkb,
- unsigned want,
- unsigned need)
-{
-const char * tmp;
-unsigned complete;
-XkbNamesPtr old_names;
-int multi_section;
-unsigned wantNames,wantConfig,wantDflts;
-
- complete= 0;
- if (COMPLETE(names->keycodes)) complete|= XkmKeyNamesMask;
- if (COMPLETE(names->types)) complete|= XkmTypesMask;
- if (COMPLETE(names->compat)) complete|= XkmCompatMapMask;
- if (COMPLETE(names->symbols)) complete|= XkmSymbolsMask;
- if (COMPLETE(names->geometry)) complete|= XkmGeometryMask;
- want|= (complete|need);
- if (want&XkmSymbolsMask)
- want|= XkmKeyNamesMask|XkmTypesMask;
-
- if (want==0)
- return FALSE;
-
- if (xkb) {
- old_names = xkb->names;
-
- xkb->defined = 0;
- /* Wow would it ever be neat if we didn't need this noise. */
- if (xkb->names && xkb->names->keys)
- xkb->defined |= XkmKeyNamesMask;
- if (xkb->map && xkb->map->types)
- xkb->defined |= XkmTypesMask;
- if (xkb->compat)
- xkb->defined |= XkmCompatMapMask;
- if (xkb->map && xkb->map->num_syms)
- xkb->defined |= XkmSymbolsMask;
- if (xkb->indicators)
- xkb->defined |= XkmIndicatorsMask;
- if (xkb->geom)
- xkb->defined |= XkmGeometryMask;
- }
- else {
- old_names= NULL;
- }
-
- wantConfig= want&(~complete);
- if (xkb!=NULL) {
- if (wantConfig&XkmTypesMask) {
- if ((!xkb->map) || (xkb->map->num_types<XkbNumRequiredTypes))
- wantConfig&= ~XkmTypesMask;
- }
- if (wantConfig&XkmCompatMapMask) {
- if ((!xkb->compat) || (xkb->compat->num_si<1))
- wantConfig&= ~XkmCompatMapMask;
- }
- if (wantConfig&XkmSymbolsMask) {
- if ((!xkb->map) || (!xkb->map->key_sym_map))
- wantConfig&= ~XkmSymbolsMask;
- }
- if (wantConfig&XkmIndicatorsMask) {
- if (!xkb->indicators)
- wantConfig&= ~XkmIndicatorsMask;
- }
- if (wantConfig&XkmKeyNamesMask) {
- if ((!xkb->names)||(!xkb->names->keys))
- wantConfig&= ~XkmKeyNamesMask;
- }
- if ((wantConfig&XkmGeometryMask)&&(!xkb->geom))
- wantConfig&= ~XkmGeometryMask;
- }
- else {
- wantConfig= 0;
- }
- complete|= wantConfig;
-
- wantDflts= 0;
- wantNames= want&(~complete);
- if ((xkb!=NULL) && (old_names!=NULL)) {
- if (wantNames&XkmTypesMask) {
- if (old_names->types!=None) {
- tmp= NameForAtom(old_names->types);
- names->types= _XkbDupString(tmp);
- }
- else {
- wantDflts|= XkmTypesMask;
- }
- complete|= XkmTypesMask;
- }
- if (wantNames&XkmCompatMapMask) {
- if (old_names->compat!=None) {
- tmp= NameForAtom(old_names->compat);
- names->compat= _XkbDupString(tmp);
- }
- else wantDflts|= XkmCompatMapMask;
- complete|= XkmCompatMapMask;
- }
- if (wantNames&XkmSymbolsMask) {
- if (old_names->symbols==None)
- return FALSE;
- tmp= NameForAtom(old_names->symbols);
- names->symbols= _XkbDupString(tmp);
- complete|= XkmSymbolsMask;
- }
- if (wantNames&XkmKeyNamesMask) {
- if (old_names->keycodes!=None) {
- tmp= NameForAtom(old_names->keycodes);
- names->keycodes= _XkbDupString(tmp);
- }
- else wantDflts|= XkmKeyNamesMask;
- complete|= XkmKeyNamesMask;
- }
- if (wantNames&XkmGeometryMask) {
- if (old_names->geometry==None)
- return FALSE;
- tmp= NameForAtom(old_names->geometry);
- names->geometry= _XkbDupString(tmp);
- complete|= XkmGeometryMask;
- wantNames&= ~XkmGeometryMask;
- }
- }
- if (complete&XkmCompatMapMask)
- complete|= XkmIndicatorsMask|XkmVirtualModsMask;
- else if (complete&(XkmSymbolsMask|XkmTypesMask))
- complete|= XkmVirtualModsMask;
- if (need & (~complete))
- return FALSE;
- if ((complete&XkmSymbolsMask)&&((XkmKeyNamesMask|XkmTypesMask)&(~complete)))
- return FALSE;
-
- multi_section= 1;
- if (((complete&XkmKeymapRequired)==XkmKeymapRequired)&&
- ((complete&(~XkmKeymapLegal))==0)) {
- fprintf(file,"xkb_keymap \"default\" {\n");
- }
- else if (((complete&XkmSemanticsRequired)==XkmSemanticsRequired)&&
- ((complete&(~XkmSemanticsLegal))==0)) {
- fprintf(file,"xkb_semantics \"default\" {\n");
- }
- else if (((complete&XkmLayoutRequired)==XkmLayoutRequired)&&
- ((complete&(~XkmLayoutLegal))==0)) {
- fprintf(file,"xkb_layout \"default\" {\n");
- }
- else if (XkmSingleSection(complete&(~XkmVirtualModsMask))) {
- multi_section= 0;
- }
- else {
- return FALSE;
- }
-
- wantNames= complete&(~(wantConfig|wantDflts));
- if (wantConfig&XkmKeyNamesMask)
- XkbWriteXKBKeycodes(file,xkb,FALSE,FALSE,_AddIncl,names->keycodes);
- else if (wantDflts&XkmKeyNamesMask)
- fprintf(stderr,"Default symbols not implemented yet!\n");
- else if (wantNames&XkmKeyNamesMask)
- XkbWriteSectionFromName(file,"keycodes",names->keycodes);
-
- if (wantConfig&XkmTypesMask)
- XkbWriteXKBKeyTypes(file,xkb,FALSE,FALSE,_AddIncl,names->types);
- else if (wantDflts&XkmTypesMask)
- fprintf(stderr,"Default types not implemented yet!\n");
- else if (wantNames&XkmTypesMask)
- XkbWriteSectionFromName(file,"types",names->types);
-
- if (wantConfig&XkmCompatMapMask)
- XkbWriteXKBCompatMap(file,xkb,FALSE,FALSE,_AddIncl,names->compat);
- else if (wantDflts&XkmCompatMapMask)
- fprintf(stderr,"Default interps not implemented yet!\n");
- else if (wantNames&XkmCompatMapMask)
- XkbWriteSectionFromName(file,"compatibility",names->compat);
-
- if (wantConfig&XkmSymbolsMask)
- XkbWriteXKBSymbols(file,xkb,FALSE,FALSE,_AddIncl,names->symbols);
- else if (wantNames&XkmSymbolsMask)
- XkbWriteSectionFromName(file,"symbols",names->symbols);
-
- if (wantConfig&XkmGeometryMask)
- XkbWriteXKBGeometry(file,xkb,FALSE,FALSE,_AddIncl,names->geometry);
- else if (wantNames&XkmGeometryMask)
- XkbWriteSectionFromName(file,"geometry",names->geometry);
-
- if (multi_section)
- fprintf(file,"};\n");
- return TRUE;
-}
-
-/***====================================================================***/
-
-int
-XkbFindKeycodeByName(XkbDescPtr xkb,char *name,Bool use_aliases)
-{
-register int i;
-
- if ((!xkb)||(!xkb->names)||(!xkb->names->keys))
- return 0;
- for (i=xkb->min_key_code;i<=xkb->max_key_code;i++) {
- if (strncmp(xkb->names->keys[i].name,name,XkbKeyNameLength)==0)
- return i;
- }
- if (!use_aliases)
- return 0;
- if (xkb->geom && xkb->geom->key_aliases) {
- XkbKeyAliasPtr a;
- a= xkb->geom->key_aliases;
- for (i=0;i<xkb->geom->num_key_aliases;i++,a++) {
- if (strncmp(name,a->alias,XkbKeyNameLength)==0)
- return XkbFindKeycodeByName(xkb,a->real,FALSE);
- }
- }
- if (xkb->names && xkb->names->key_aliases) {
- XkbKeyAliasPtr a;
- a= xkb->names->key_aliases;
- for (i=0;i<xkb->names->num_key_aliases;i++,a++) {
- if (strncmp(name,a->alias,XkbKeyNameLength)==0)
- return XkbFindKeycodeByName(xkb,a->real,FALSE);
- }
- }
- return 0;
-}
-
-
-unsigned
-XkbConvertGetByNameComponents(Bool toXkm,unsigned orig)
-{
-unsigned rtrn;
-
- rtrn= 0;
- if (toXkm) {
- if (orig&XkbGBN_TypesMask) rtrn|= XkmTypesMask;
- if (orig&XkbGBN_CompatMapMask) rtrn|= XkmCompatMapMask;
- if (orig&XkbGBN_SymbolsMask) rtrn|= XkmSymbolsMask;
- if (orig&XkbGBN_IndicatorMapMask) rtrn|= XkmIndicatorsMask;
- if (orig&XkbGBN_KeyNamesMask) rtrn|= XkmKeyNamesMask;
- if (orig&XkbGBN_GeometryMask) rtrn|= XkmGeometryMask;
- }
- else {
- if (orig&XkmTypesMask) rtrn|= XkbGBN_TypesMask;
- if (orig&XkmCompatMapMask) rtrn|= XkbGBN_CompatMapMask;
- if (orig&XkmSymbolsMask) rtrn|= XkbGBN_SymbolsMask;
- if (orig&XkmIndicatorsMask) rtrn|= XkbGBN_IndicatorMapMask;
- if (orig&XkmKeyNamesMask) rtrn|= XkbGBN_KeyNamesMask;
- if (orig&XkmGeometryMask) rtrn|= XkbGBN_GeometryMask;
- if (orig!=0) rtrn|= XkbGBN_OtherNamesMask;
- }
- return rtrn;
-}
-
-/***====================================================================***/
-
-#define UNMATCHABLE(c) (((c)=='(')||((c)==')')||((c)=='/'))
-
-Bool
-XkbNameMatchesPattern(char *name,char *ptrn)
-{
- while (ptrn[0]!='\0') {
- if (name[0]=='\0') {
- if (ptrn[0]=='*') {
- ptrn++;
- continue;
- }
- return FALSE;
- }
- if (ptrn[0]=='?') {
- if (UNMATCHABLE(name[0]))
- return FALSE;
- }
- else if (ptrn[0]=='*') {
- if ((!UNMATCHABLE(name[0]))&&XkbNameMatchesPattern(name+1,ptrn))
- return TRUE;
- return XkbNameMatchesPattern(name,ptrn+1);
- }
- else if (ptrn[0]!=name[0])
- return FALSE;
- name++;
- ptrn++;
- }
- /* if we get here, the pattern is exhausted (-:just like me:-) */
- return name[0]=='\0';
-}
+/************************************************************ + Copyright (c) 1995 by Silicon Graphics Computer Systems, Inc. + + Permission 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 that both that copyright + notice and this permission notice appear in supporting + documentation, and that the name of Silicon Graphics not be + used in advertising or publicity pertaining to distribution + of the software without specific prior written permission. + Silicon Graphics makes no representation about the suitability + of this software for any purpose. It is provided "as is" + without any express or implied warranty. + + SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS + SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON + GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL + DAMAGES OR ANY 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 THIS SOFTWARE. + + ********************************************************/ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include <stdio.h> +#include <ctype.h> +#include <stdlib.h> + +#include <X11/Xos.h> +#include <X11/Xfuncs.h> +#include <X11/extensions/XKMformat.h> + +#include <X11/X.h> +#include <X11/keysym.h> +#include <X11/Xproto.h> +#include "misc.h" +#include "inputstr.h" +#include "dix.h" +#include "xkbstr.h" +#define XKBSRV_NEED_FILE_FUNCS 1 +#include <xkbsrv.h> +#include "xkbgeom.h" +#include "xkb.h" + +unsigned +_XkbKSCheckCase(KeySym ks) +{ +unsigned set,rtrn; + + set= (ks & (~0xff)) >> 8; + rtrn= 0; + switch (set) { + case 0: /* latin 1 */ + if (((ks>=XK_A)&&(ks<=XK_Z))|| + ((ks>=XK_Agrave)&&(ks<=XK_THORN)&&(ks!=XK_multiply))) { + rtrn|= _XkbKSUpper; + } + if (((ks>=XK_a)&&(ks<=XK_z))|| + ((ks>=XK_agrave)&&(ks<=XK_ydiaeresis))) { + rtrn|= _XkbKSLower; + } + break; + case 1: /* latin 2 */ + if (((ks>=XK_Aogonek)&&(ks<=XK_Zabovedot)&&(ks!=XK_breve))|| + ((ks>=XK_Racute)&&(ks<=XK_Tcedilla))) { + rtrn|= _XkbKSUpper; + } + if (((ks>=XK_aogonek)&&(ks<=XK_zabovedot)&&(ks!=XK_caron))|| + ((ks>=XK_racute)&&(ks<=XK_tcedilla))) { + rtrn|= _XkbKSLower; + } + break; + case 2: /* latin 3 */ + if (((ks>=XK_Hstroke)&&(ks<=XK_Jcircumflex))|| + ((ks>=XK_Cabovedot)&&(ks<=XK_Scircumflex))) { + rtrn|= _XkbKSUpper; + } + if (((ks>=XK_hstroke)&&(ks<=XK_jcircumflex))|| + ((ks>=XK_cabovedot)&&(ks<=XK_scircumflex))) { + rtrn|= _XkbKSLower; + } + break; + case 3: /* latin 4 */ + if (((ks>=XK_Rcedilla)&&(ks<=XK_Tslash))|| + (ks==XK_ENG)|| + ((ks>=XK_Amacron)&&(ks<=XK_Umacron))) { + rtrn|= _XkbKSUpper; + } + if (((ks>=XK_rcedilla)&&(ks<=XK_tslash))|| + (ks==XK_eng)|| + ((ks>=XK_amacron)&&(ks<=XK_umacron))) { + rtrn|= _XkbKSLower; + } + break; + case 18: /* latin 8 */ + if ((ks==XK_Babovedot)|| + ((ks>=XK_Dabovedot)&&(ks<=XK_Wacute))|| + ((ks>=XK_Ygrave)&&(ks<=XK_Fabovedot))|| + (ks==XK_Mabovedot)|| + (ks==XK_Pabovedot)|| + (ks==XK_Sabovedot)|| + (ks==XK_Wdiaeresis)|| + ((ks>=XK_Wcircumflex)&&(ks<=XK_Ycircumflex))) { + rtrn|= _XkbKSUpper; + } + if ((ks==XK_babovedot)|| + (ks==XK_dabovedot)|| + (ks==XK_fabovedot)|| + (ks==XK_mabovedot)|| + ((ks>=XK_wgrave)&&(ks<=XK_wacute))|| + (ks==XK_ygrave)|| + ((ks>=XK_wdiaeresis)&&(ks<=XK_ycircumflex))) { + rtrn|= _XkbKSLower; + } + break; + case 19: /* latin 9 */ + if ((ks==XK_OE)||(ks==XK_Ydiaeresis)) { + rtrn|= _XkbKSUpper; + } + if (ks==XK_oe) { + rtrn|= _XkbKSLower; + } + break; + } + return rtrn; +} + +/***===================================================================***/ + +static Bool +XkbWriteSectionFromName(FILE *file,char *sectionName,char *name) +{ + fprintf(file," xkb_%-20s { include \"%s\" };\n",sectionName,name); + return TRUE; +} + +#define NEED_DESC(n) ((!n)||((n)[0]=='+')||((n)[0]=='|')||(strchr((n),'%'))) +#define COMPLETE(n) ((n)&&(!NEED_DESC(n))) + +/* ARGSUSED */ +static void +_AddIncl( FILE * file, + XkbDescPtr xkb, + Bool topLevel, + Bool showImplicit, + int index, + void * priv) +{ + if ((priv)&&(strcmp((char *)priv,"%")!=0)) + fprintf(file," include \"%s\"\n",(char *)priv); + return; +} + +Bool +XkbWriteXKBKeymapForNames( FILE * file, + XkbComponentNamesPtr names, + XkbDescPtr xkb, + unsigned want, + unsigned need) +{ +const char * tmp; +unsigned complete; +XkbNamesPtr old_names; +int multi_section; +unsigned wantNames,wantConfig,wantDflts; + + complete= 0; + if (COMPLETE(names->keycodes)) complete|= XkmKeyNamesMask; + if (COMPLETE(names->types)) complete|= XkmTypesMask; + if (COMPLETE(names->compat)) complete|= XkmCompatMapMask; + if (COMPLETE(names->symbols)) complete|= XkmSymbolsMask; + if (COMPLETE(names->geometry)) complete|= XkmGeometryMask; + want|= (complete|need); + if (want&XkmSymbolsMask) + want|= XkmKeyNamesMask|XkmTypesMask; + + if (want==0) + return FALSE; + + if (xkb) { + old_names = xkb->names; + + xkb->defined = 0; + /* Wow would it ever be neat if we didn't need this noise. */ + if (xkb->names && xkb->names->keys) + xkb->defined |= XkmKeyNamesMask; + if (xkb->map && xkb->map->types) + xkb->defined |= XkmTypesMask; + if (xkb->compat) + xkb->defined |= XkmCompatMapMask; + if (xkb->map && xkb->map->num_syms) + xkb->defined |= XkmSymbolsMask; + if (xkb->indicators) + xkb->defined |= XkmIndicatorsMask; + if (xkb->geom) + xkb->defined |= XkmGeometryMask; + } + else { + old_names= NULL; + } + + wantConfig= want&(~complete); + if (xkb!=NULL) { + if (wantConfig&XkmTypesMask) { + if ((!xkb->map) || (xkb->map->num_types<XkbNumRequiredTypes)) + wantConfig&= ~XkmTypesMask; + } + if (wantConfig&XkmCompatMapMask) { + if ((!xkb->compat) || (xkb->compat->num_si<1)) + wantConfig&= ~XkmCompatMapMask; + } + if (wantConfig&XkmSymbolsMask) { + if ((!xkb->map) || (!xkb->map->key_sym_map)) + wantConfig&= ~XkmSymbolsMask; + } + if (wantConfig&XkmIndicatorsMask) { + if (!xkb->indicators) + wantConfig&= ~XkmIndicatorsMask; + } + if (wantConfig&XkmKeyNamesMask) { + if ((!xkb->names)||(!xkb->names->keys)) + wantConfig&= ~XkmKeyNamesMask; + } + if ((wantConfig&XkmGeometryMask)&&(!xkb->geom)) + wantConfig&= ~XkmGeometryMask; + } + else { + wantConfig= 0; + } + complete|= wantConfig; + + wantDflts= 0; + wantNames= want&(~complete); + if ((xkb!=NULL) && (old_names!=NULL)) { + if (wantNames&XkmTypesMask) { + if (old_names->types!=None) { + tmp= NameForAtom(old_names->types); + names->types= Xstrdup(tmp); + } + else { + wantDflts|= XkmTypesMask; + } + complete|= XkmTypesMask; + } + if (wantNames&XkmCompatMapMask) { + if (old_names->compat!=None) { + tmp= NameForAtom(old_names->compat); + names->compat= Xstrdup(tmp); + } + else wantDflts|= XkmCompatMapMask; + complete|= XkmCompatMapMask; + } + if (wantNames&XkmSymbolsMask) { + if (old_names->symbols==None) + return FALSE; + tmp= NameForAtom(old_names->symbols); + names->symbols= Xstrdup(tmp); + complete|= XkmSymbolsMask; + } + if (wantNames&XkmKeyNamesMask) { + if (old_names->keycodes!=None) { + tmp= NameForAtom(old_names->keycodes); + names->keycodes= Xstrdup(tmp); + } + else wantDflts|= XkmKeyNamesMask; + complete|= XkmKeyNamesMask; + } + if (wantNames&XkmGeometryMask) { + if (old_names->geometry==None) + return FALSE; + tmp= NameForAtom(old_names->geometry); + names->geometry= Xstrdup(tmp); + complete|= XkmGeometryMask; + wantNames&= ~XkmGeometryMask; + } + } + if (complete&XkmCompatMapMask) + complete|= XkmIndicatorsMask|XkmVirtualModsMask; + else if (complete&(XkmSymbolsMask|XkmTypesMask)) + complete|= XkmVirtualModsMask; + if (need & (~complete)) + return FALSE; + if ((complete&XkmSymbolsMask)&&((XkmKeyNamesMask|XkmTypesMask)&(~complete))) + return FALSE; + + multi_section= 1; + if (((complete&XkmKeymapRequired)==XkmKeymapRequired)&& + ((complete&(~XkmKeymapLegal))==0)) { + fprintf(file,"xkb_keymap \"default\" {\n"); + } + else if (((complete&XkmSemanticsRequired)==XkmSemanticsRequired)&& + ((complete&(~XkmSemanticsLegal))==0)) { + fprintf(file,"xkb_semantics \"default\" {\n"); + } + else if (((complete&XkmLayoutRequired)==XkmLayoutRequired)&& + ((complete&(~XkmLayoutLegal))==0)) { + fprintf(file,"xkb_layout \"default\" {\n"); + } + else if (XkmSingleSection(complete&(~XkmVirtualModsMask))) { + multi_section= 0; + } + else { + return FALSE; + } + + wantNames= complete&(~(wantConfig|wantDflts)); + if (wantConfig&XkmKeyNamesMask) + XkbWriteXKBKeycodes(file,xkb,FALSE,FALSE,_AddIncl,names->keycodes); + else if (wantDflts&XkmKeyNamesMask) + fprintf(stderr,"Default symbols not implemented yet!\n"); + else if (wantNames&XkmKeyNamesMask) + XkbWriteSectionFromName(file,"keycodes",names->keycodes); + + if (wantConfig&XkmTypesMask) + XkbWriteXKBKeyTypes(file,xkb,FALSE,FALSE,_AddIncl,names->types); + else if (wantDflts&XkmTypesMask) + fprintf(stderr,"Default types not implemented yet!\n"); + else if (wantNames&XkmTypesMask) + XkbWriteSectionFromName(file,"types",names->types); + + if (wantConfig&XkmCompatMapMask) + XkbWriteXKBCompatMap(file,xkb,FALSE,FALSE,_AddIncl,names->compat); + else if (wantDflts&XkmCompatMapMask) + fprintf(stderr,"Default interps not implemented yet!\n"); + else if (wantNames&XkmCompatMapMask) + XkbWriteSectionFromName(file,"compatibility",names->compat); + + if (wantConfig&XkmSymbolsMask) + XkbWriteXKBSymbols(file,xkb,FALSE,FALSE,_AddIncl,names->symbols); + else if (wantNames&XkmSymbolsMask) + XkbWriteSectionFromName(file,"symbols",names->symbols); + + if (wantConfig&XkmGeometryMask) + XkbWriteXKBGeometry(file,xkb,FALSE,FALSE,_AddIncl,names->geometry); + else if (wantNames&XkmGeometryMask) + XkbWriteSectionFromName(file,"geometry",names->geometry); + + if (multi_section) + fprintf(file,"};\n"); + return TRUE; +} + +/***====================================================================***/ + +int +XkbFindKeycodeByName(XkbDescPtr xkb,char *name,Bool use_aliases) +{ +register int i; + + if ((!xkb)||(!xkb->names)||(!xkb->names->keys)) + return 0; + for (i=xkb->min_key_code;i<=xkb->max_key_code;i++) { + if (strncmp(xkb->names->keys[i].name,name,XkbKeyNameLength)==0) + return i; + } + if (!use_aliases) + return 0; + if (xkb->geom && xkb->geom->key_aliases) { + XkbKeyAliasPtr a; + a= xkb->geom->key_aliases; + for (i=0;i<xkb->geom->num_key_aliases;i++,a++) { + if (strncmp(name,a->alias,XkbKeyNameLength)==0) + return XkbFindKeycodeByName(xkb,a->real,FALSE); + } + } + if (xkb->names && xkb->names->key_aliases) { + XkbKeyAliasPtr a; + a= xkb->names->key_aliases; + for (i=0;i<xkb->names->num_key_aliases;i++,a++) { + if (strncmp(name,a->alias,XkbKeyNameLength)==0) + return XkbFindKeycodeByName(xkb,a->real,FALSE); + } + } + return 0; +} + + +unsigned +XkbConvertGetByNameComponents(Bool toXkm,unsigned orig) +{ +unsigned rtrn; + + rtrn= 0; + if (toXkm) { + if (orig&XkbGBN_TypesMask) rtrn|= XkmTypesMask; + if (orig&XkbGBN_CompatMapMask) rtrn|= XkmCompatMapMask; + if (orig&XkbGBN_SymbolsMask) rtrn|= XkmSymbolsMask; + if (orig&XkbGBN_IndicatorMapMask) rtrn|= XkmIndicatorsMask; + if (orig&XkbGBN_KeyNamesMask) rtrn|= XkmKeyNamesMask; + if (orig&XkbGBN_GeometryMask) rtrn|= XkmGeometryMask; + } + else { + if (orig&XkmTypesMask) rtrn|= XkbGBN_TypesMask; + if (orig&XkmCompatMapMask) rtrn|= XkbGBN_CompatMapMask; + if (orig&XkmSymbolsMask) rtrn|= XkbGBN_SymbolsMask; + if (orig&XkmIndicatorsMask) rtrn|= XkbGBN_IndicatorMapMask; + if (orig&XkmKeyNamesMask) rtrn|= XkbGBN_KeyNamesMask; + if (orig&XkmGeometryMask) rtrn|= XkbGBN_GeometryMask; + if (orig!=0) rtrn|= XkbGBN_OtherNamesMask; + } + return rtrn; +} + +/***====================================================================***/ + +#define UNMATCHABLE(c) (((c)=='(')||((c)==')')||((c)=='/')) + +Bool +XkbNameMatchesPattern(char *name,char *ptrn) +{ + while (ptrn[0]!='\0') { + if (name[0]=='\0') { + if (ptrn[0]=='*') { + ptrn++; + continue; + } + return FALSE; + } + if (ptrn[0]=='?') { + if (UNMATCHABLE(name[0])) + return FALSE; + } + else if (ptrn[0]=='*') { + if ((!UNMATCHABLE(name[0]))&&XkbNameMatchesPattern(name+1,ptrn)) + return TRUE; + return XkbNameMatchesPattern(name,ptrn+1); + } + else if (ptrn[0]!=name[0]) + return FALSE; + name++; + ptrn++; + } + /* if we get here, the pattern is exhausted (-:just like me:-) */ + return name[0]=='\0'; +} diff --git a/xorg-server/xkb/xkmread.c b/xorg-server/xkb/xkmread.c index 81f09fe3b..e8b97dcda 100644 --- a/xorg-server/xkb/xkmread.c +++ b/xorg-server/xkb/xkmread.c @@ -1,1241 +1,1228 @@ -/************************************************************
- Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc.
-
- Permission 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 that both that copyright
- notice and this permission notice appear in supporting
- documentation, and that the name of Silicon Graphics not be
- used in advertising or publicity pertaining to distribution
- of the software without specific prior written permission.
- Silicon Graphics makes no representation about the suitability
- of this software for any purpose. It is provided "as is"
- without any express or implied warranty.
-
- SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
- SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
- AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
- GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
- DAMAGES OR ANY 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 THIS SOFTWARE.
-
- ********************************************************/
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#include <stdio.h>
-
-#include <X11/Xos.h>
-#include <X11/Xfuncs.h>
-
-#include <X11/X.h>
-#include <X11/Xproto.h>
-#include <X11/keysym.h>
-#include <X11/extensions/XKMformat.h>
-#include "misc.h"
-#include "inputstr.h"
-#include "xkbstr.h"
-#include "xkbsrv.h"
-#include "xkbgeom.h"
-
-Atom
-XkbInternAtom(char *str,Bool only_if_exists)
-{
- if (str==NULL)
- return None;
- return MakeAtom(str,strlen(str),!only_if_exists);
-}
-
-char *
-_XkbDupString(const char *str)
-{
-char *new;
-
- if (str==NULL)
- return NULL;
- new= calloc(strlen(str)+1,sizeof(char));
- if (new)
- strcpy(new,str);
- return new;
-}
-
-/***====================================================================***/
-
-static void *
-XkmInsureSize(void *oldPtr,int oldCount,int *newCountRtrn,int elemSize)
-{
-int newCount= *newCountRtrn;
-
- if (oldPtr==NULL) {
- if (newCount==0)
- return NULL;
- oldPtr= calloc(newCount,elemSize);
- }
- else if (oldCount<newCount) {
- oldPtr= realloc(oldPtr,newCount*elemSize);
- if (oldPtr!=NULL) {
- char *tmp= (char *)oldPtr;
- memset(&tmp[oldCount*elemSize], 0, (newCount-oldCount)*elemSize);
- }
- }
- else if (newCount<oldCount) {
- *newCountRtrn= oldCount;
- }
- return oldPtr;
-}
-
-#define XkmInsureTypedSize(p,o,n,t) ((p)=((t *)XkmInsureSize((char *)(p),(o),(n),sizeof(t))))
-
-static CARD8
-XkmGetCARD8(FILE *file,int *pNRead)
-{
-int tmp;
- tmp= getc(file);
- if (pNRead&&(tmp!=EOF))
- (*pNRead)+= 1;
- return tmp;
-}
-
-static CARD16
-XkmGetCARD16(FILE *file,int *pNRead)
-{
-CARD16 val;
-
- if ((fread(&val,2,1,file)==1)&&(pNRead))
- (*pNRead)+= 2;
- return val;
-}
-
-static CARD32
-XkmGetCARD32(FILE *file,int *pNRead)
-{
-CARD32 val;
-
- if ((fread(&val,4,1,file)==1)&&(pNRead))
- (*pNRead)+= 4;
- return val;
-}
-
-static int
-XkmSkipPadding(FILE *file,unsigned pad)
-{
-register int i,nRead=0;
-
- for (i=0;i<pad;i++) {
- if (getc(file)!=EOF)
- nRead++;
- }
- return nRead;
-}
-
-static int
-XkmGetCountedString(FILE *file,char *str,int max_len)
-{
-int count,nRead=0;
-
- count= XkmGetCARD16(file,&nRead);
- if (count>0) {
- int tmp;
- if (count>max_len) {
- tmp= fread(str,1,max_len,file);
- while (tmp<count) {
- if ((getc(file))!=EOF)
- tmp++;
- else break;
- }
- }
- else {
- tmp= fread(str,1,count,file);
- }
- nRead+= tmp;
- }
- if (count>=max_len) str[max_len-1]= '\0';
- else str[count]= '\0';
- count= XkbPaddedSize(nRead)-nRead;
- if (count>0)
- nRead+= XkmSkipPadding(file,count);
- return nRead;
-}
-
-/***====================================================================***/
-
-static int
-ReadXkmVirtualMods(FILE *file,XkbDescPtr xkb,XkbChangesPtr changes)
-{
-register unsigned int i,bit;
-unsigned int bound,named,tmp;
-int nRead=0;
-
- if (XkbAllocServerMap(xkb,XkbVirtualModsMask,0)!=Success) {
- _XkbLibError(_XkbErrBadAlloc,"ReadXkmVirtualMods",0);
- return -1;
- }
- bound= XkmGetCARD16(file,&nRead);
- named= XkmGetCARD16(file,&nRead);
- for (i=tmp=0,bit=1;i<XkbNumVirtualMods;i++,bit<<=1) {
- if (bound&bit) {
- xkb->server->vmods[i]= XkmGetCARD8(file,&nRead);
- if (changes)
- changes->map.vmods|= bit;
- tmp++;
- }
- }
- if ((i= XkbPaddedSize(tmp)-tmp)>0)
- nRead+= XkmSkipPadding(file,i);
- if (XkbAllocNames(xkb,XkbVirtualModNamesMask,0,0)!=Success) {
- _XkbLibError(_XkbErrBadAlloc,"ReadXkmVirtualMods",0);
- return -1;
- }
- for (i=0,bit=1;i<XkbNumVirtualMods;i++,bit<<=1) {
- char name[100];
- if (named&bit) {
- if (nRead+=XkmGetCountedString(file,name,100)) {
- xkb->names->vmods[i]= XkbInternAtom(name,FALSE);
- if (changes)
- changes->names.changed_vmods|= bit;
- }
- }
- }
- return nRead;
-}
-
-/***====================================================================***/
-
-static int
-ReadXkmKeycodes(FILE *file,XkbDescPtr xkb,XkbChangesPtr changes)
-{
-register int i;
-unsigned minKC,maxKC,nAl;
-int nRead=0;
-char name[100];
-XkbKeyNamePtr pN;
-
- name[0]= '\0';
- nRead+= XkmGetCountedString(file,name,100);
- minKC= XkmGetCARD8(file,&nRead);
- maxKC= XkmGetCARD8(file,&nRead);
- if (xkb->min_key_code==0) {
- xkb->min_key_code= minKC;
- xkb->max_key_code= maxKC;
- }
- else {
- if (minKC<xkb->min_key_code)
- xkb->min_key_code= minKC;
- if (maxKC>xkb->max_key_code) {
- _XkbLibError(_XkbErrBadValue,"ReadXkmKeycodes",maxKC);
- return -1;
- }
- }
- nAl= XkmGetCARD8(file,&nRead);
- nRead+= XkmSkipPadding(file,1);
-
-#define WANTED (XkbKeycodesNameMask|XkbKeyNamesMask|XkbKeyAliasesMask)
- if (XkbAllocNames(xkb,WANTED,0,nAl)!=Success) {
- _XkbLibError(_XkbErrBadAlloc,"ReadXkmKeycodes",0);
- return -1;
- }
- if (name[0]!='\0') {
- xkb->names->keycodes= XkbInternAtom(name,FALSE);
- }
-
- for (pN=&xkb->names->keys[minKC],i=minKC;i<=(int)maxKC;i++,pN++) {
- if (fread(pN,1,XkbKeyNameLength,file)!=XkbKeyNameLength) {
- _XkbLibError(_XkbErrBadLength,"ReadXkmKeycodes",0);
- return -1;
- }
- nRead+= XkbKeyNameLength;
- }
- if (nAl>0) {
- XkbKeyAliasPtr pAl;
- for (pAl= xkb->names->key_aliases,i=0;i<nAl;i++,pAl++) {
- int tmp;
- tmp= fread(pAl,1,2*XkbKeyNameLength,file);
- if (tmp!=2*XkbKeyNameLength) {
- _XkbLibError(_XkbErrBadLength,"ReadXkmKeycodes",0);
- return -1;
- }
- nRead+= 2*XkbKeyNameLength;
- }
- if (changes)
- changes->names.changed|= XkbKeyAliasesMask;
- }
- if (changes)
- changes->names.changed|= XkbKeyNamesMask;
- return nRead;
-}
-
-/***====================================================================***/
-
-static int
-ReadXkmKeyTypes(FILE *file,XkbDescPtr xkb,XkbChangesPtr changes)
-{
-register unsigned i,n;
-unsigned num_types;
-int nRead=0;
-int tmp;
-XkbKeyTypePtr type;
-xkmKeyTypeDesc wire;
-XkbKTMapEntryPtr entry;
-xkmKTMapEntryDesc wire_entry;
-char buf[100];
-
- if ((tmp= XkmGetCountedString(file,buf,100))<1) {
- _XkbLibError(_XkbErrBadLength,"ReadXkmKeyTypes",0);
- return -1;
- }
- nRead+= tmp;
- if (buf[0]!='\0') {
- if (XkbAllocNames(xkb,XkbTypesNameMask,0,0)!=Success) {
- _XkbLibError(_XkbErrBadAlloc,"ReadXkmKeyTypes",0);
- return -1;
- }
- xkb->names->types= XkbInternAtom(buf,FALSE);
- }
- num_types= XkmGetCARD16(file,&nRead);
- nRead+= XkmSkipPadding(file,2);
- if (num_types<1)
- return nRead;
- if (XkbAllocClientMap(xkb,XkbKeyTypesMask,num_types)!=Success) {
- _XkbLibError(_XkbErrBadAlloc,"ReadXkmKeyTypes",0);
- return nRead;
- }
- xkb->map->num_types= num_types;
- if (num_types<XkbNumRequiredTypes) {
- _XkbLibError(_XkbErrMissingReqTypes,"ReadXkmKeyTypes",0);
- return -1;
- }
- type= xkb->map->types;
- for (i=0;i<num_types;i++,type++) {
- if ((int)fread(&wire,SIZEOF(xkmKeyTypeDesc),1,file)<1) {
- _XkbLibError(_XkbErrBadLength,"ReadXkmKeyTypes",0);
- return -1;
- }
- nRead+= SIZEOF(xkmKeyTypeDesc);
- if (((i==XkbOneLevelIndex)&&(wire.numLevels!=1))||
- (((i==XkbTwoLevelIndex)||(i==XkbAlphabeticIndex)||
- ((i)==XkbKeypadIndex))&&(wire.numLevels!=2))) {
- _XkbLibError(_XkbErrBadTypeWidth,"ReadXkmKeyTypes",i);
- return -1;
- }
- tmp= wire.nMapEntries;
- XkmInsureTypedSize(type->map,type->map_count,&tmp,XkbKTMapEntryRec);
- if ((wire.nMapEntries>0)&&(type->map==NULL)) {
- _XkbLibError(_XkbErrBadValue,"ReadXkmKeyTypes",wire.nMapEntries);
- return -1;
- }
- for (n=0,entry= type->map;n<wire.nMapEntries;n++,entry++) {
- if (fread(&wire_entry,SIZEOF(xkmKTMapEntryDesc),1,file)<(int)1) {
- _XkbLibError(_XkbErrBadLength,"ReadXkmKeyTypes",0);
- return -1;
- }
- nRead+= SIZEOF(xkmKTMapEntryDesc);
- entry->active= (wire_entry.virtualMods==0);
- entry->level= wire_entry.level;
- entry->mods.mask= wire_entry.realMods;
- entry->mods.real_mods= wire_entry.realMods;
- entry->mods.vmods= wire_entry.virtualMods;
- }
- nRead+= XkmGetCountedString(file,buf,100);
- if (((i==XkbOneLevelIndex)&&(strcmp(buf,"ONE_LEVEL")!=0))||
- ((i==XkbTwoLevelIndex)&&(strcmp(buf,"TWO_LEVEL")!=0))||
- ((i==XkbAlphabeticIndex)&&(strcmp(buf,"ALPHABETIC")!=0))||
- ((i==XkbKeypadIndex)&&(strcmp(buf,"KEYPAD")!=0))) {
- _XkbLibError(_XkbErrBadTypeName,"ReadXkmKeyTypes",0);
- return -1;
- }
- if (buf[0]!='\0') {
- type->name= XkbInternAtom(buf,FALSE);
- }
- else type->name= None;
-
- if (wire.preserve) {
- xkmModsDesc p_entry;
- XkbModsPtr pre;
- XkmInsureTypedSize(type->preserve,type->map_count,&tmp,
- XkbModsRec);
- if (type->preserve==NULL) {
- _XkbLibError(_XkbErrBadMatch,"ReadXkmKeycodes",0);
- return -1;
- }
- for (n=0,pre=type->preserve;n<wire.nMapEntries;n++,pre++) {
- if (fread(&p_entry,SIZEOF(xkmModsDesc),1,file)<1) {
- _XkbLibError(_XkbErrBadLength,"ReadXkmKeycodes",0);
- return -1;
- }
- nRead+= SIZEOF(xkmModsDesc);
- pre->mask= p_entry.realMods;
- pre->real_mods= p_entry.realMods;
- pre->vmods= p_entry.virtualMods;
- }
- }
- if (wire.nLevelNames>0) {
- int width= wire.numLevels;
- if (wire.nLevelNames>(unsigned)width) {
- _XkbLibError(_XkbErrBadMatch,"ReadXkmKeycodes",0);
- return -1;
- }
- XkmInsureTypedSize(type->level_names,type->num_levels,&width,Atom);
- if (type->level_names!=NULL) {
- for (n=0;n<wire.nLevelNames;n++) {
- if ((tmp=XkmGetCountedString(file,buf,100))<1)
- return -1;
- nRead+= tmp;
- if (strlen(buf)==0)
- type->level_names[n]= None;
- else type->level_names[n]= XkbInternAtom(buf,0);
- }
- }
- }
- type->mods.mask= wire.realMods;
- type->mods.real_mods= wire.realMods;
- type->mods.vmods= wire.virtualMods;
- type->num_levels= wire.numLevels;
- type->map_count= wire.nMapEntries;
- }
- if (changes) {
- changes->map.changed|= XkbKeyTypesMask;
- changes->map.first_type= 0;
- changes->map.num_types= xkb->map->num_types;
- }
- return nRead;
-}
-
-/***====================================================================***/
-
-static int
-ReadXkmCompatMap(FILE *file,XkbDescPtr xkb,XkbChangesPtr changes)
-{
-register int i;
-unsigned num_si,groups;
-char name[100];
-XkbSymInterpretPtr interp;
-xkmSymInterpretDesc wire;
-unsigned tmp;
-int nRead=0;
-XkbCompatMapPtr compat;
-XkbAction *act;
-
- if ((tmp= XkmGetCountedString(file,name,100))<1) {
- _XkbLibError(_XkbErrBadLength,"ReadXkmCompatMap",0);
- return -1;
- }
- nRead+= tmp;
- if (name[0]!='\0') {
- if (XkbAllocNames(xkb,XkbCompatNameMask,0,0)!=Success) {
- _XkbLibError(_XkbErrBadAlloc,"ReadXkmCompatMap",0);
- return -1;
- }
- xkb->names->compat= XkbInternAtom(name,FALSE);
- }
- num_si= XkmGetCARD16(file,&nRead);
- groups= XkmGetCARD8(file,&nRead);
- nRead+= XkmSkipPadding(file,1);
- if (XkbAllocCompatMap(xkb,XkbAllCompatMask,num_si)!=Success)
- return -1;
- compat= xkb->compat;
- compat->num_si= num_si;
- interp= compat->sym_interpret;
- for (i=0;i<num_si;i++,interp++) {
- tmp= fread(&wire,SIZEOF(xkmSymInterpretDesc),1,file);
- nRead+= tmp*SIZEOF(xkmSymInterpretDesc);
- interp->sym= wire.sym;
- interp->mods= wire.mods;
- interp->match= wire.match;
- interp->virtual_mod= wire.virtualMod;
- interp->flags= wire.flags;
- interp->act.type= wire.actionType;
- act = (XkbAction *) &interp->act;
-
- switch (interp->act.type) {
- case XkbSA_SetMods:
- case XkbSA_LatchMods:
- case XkbSA_LockMods:
- act->mods.flags = wire.actionData[0];
- act->mods.mask = wire.actionData[1];
- act->mods.real_mods = wire.actionData[2];
- act->mods.vmods1 = wire.actionData[3];
- act->mods.vmods2 = wire.actionData[4];
- break;
- case XkbSA_SetGroup:
- case XkbSA_LatchGroup:
- case XkbSA_LockGroup:
- act->group.flags = wire.actionData[0];
- act->group.group_XXX = wire.actionData[1];
- break;
- case XkbSA_MovePtr:
- act->ptr.flags = wire.actionData[0];
- act->ptr.high_XXX = wire.actionData[1];
- act->ptr.low_XXX = wire.actionData[2];
- act->ptr.high_YYY = wire.actionData[3];
- act->ptr.low_YYY = wire.actionData[4];
- break;
- case XkbSA_PtrBtn:
- case XkbSA_LockPtrBtn:
- act->btn.flags = wire.actionData[0];
- act->btn.count = wire.actionData[1];
- act->btn.button = wire.actionData[2];
- break;
- case XkbSA_DeviceBtn:
- case XkbSA_LockDeviceBtn:
- act->devbtn.flags = wire.actionData[0];
- act->devbtn.count = wire.actionData[1];
- act->devbtn.button = wire.actionData[2];
- act->devbtn.device = wire.actionData[3];
- break;
- case XkbSA_SetPtrDflt:
- act->dflt.flags = wire.actionData[0];
- act->dflt.affect = wire.actionData[1];
- act->dflt.valueXXX = wire.actionData[2];
- break;
- case XkbSA_ISOLock:
- act->iso.flags = wire.actionData[0];
- act->iso.mask = wire.actionData[1];
- act->iso.real_mods = wire.actionData[2];
- act->iso.group_XXX = wire.actionData[3];
- act->iso.affect = wire.actionData[4];
- act->iso.vmods1 = wire.actionData[5];
- act->iso.vmods2 = wire.actionData[6];
- break;
- case XkbSA_SwitchScreen:
- act->screen.flags = wire.actionData[0];
- act->screen.screenXXX = wire.actionData[1];
- break;
- case XkbSA_SetControls:
- case XkbSA_LockControls:
- act->ctrls.flags = wire.actionData[0];
- act->ctrls.ctrls3 = wire.actionData[1];
- act->ctrls.ctrls2 = wire.actionData[2];
- act->ctrls.ctrls1 = wire.actionData[3];
- act->ctrls.ctrls0 = wire.actionData[4];
- break;
- case XkbSA_RedirectKey:
- act->redirect.new_key = wire.actionData[0];
- act->redirect.mods_mask = wire.actionData[1];
- act->redirect.mods = wire.actionData[2];
- act->redirect.vmods_mask0 = wire.actionData[3];
- act->redirect.vmods_mask1 = wire.actionData[4];
- act->redirect.vmods0 = wire.actionData[4];
- act->redirect.vmods1 = wire.actionData[5];
- break;
- case XkbSA_DeviceValuator:
- act->devval.device = wire.actionData[0];
- act->devval.v1_what = wire.actionData[1];
- act->devval.v1_ndx = wire.actionData[2];
- act->devval.v1_value = wire.actionData[3];
- act->devval.v2_what = wire.actionData[4];
- act->devval.v2_ndx = wire.actionData[5];
- act->devval.v2_what = wire.actionData[6];
- break;
-
- case XkbSA_XFree86Private:
- /* copy the kind of action */
- memcpy(act->any.data, wire.actionData, XkbAnyActionDataSize);
- break ;
-
- case XkbSA_Terminate:
- /* no args, kinda (note: untrue for xfree86). */
- break;
- case XkbSA_ActionMessage:
- /* unsupported. */
- break;
- }
- }
- if ((num_si>0)&&(changes)) {
- changes->compat.first_si= 0;
- changes->compat.num_si= num_si;
- }
- if (groups) {
- register unsigned bit;
- for (i=0,bit=1;i<XkbNumKbdGroups;i++,bit<<=1) {
- xkmModsDesc md;
- if (groups&bit) {
- tmp= fread(&md,SIZEOF(xkmModsDesc),1,file);
- nRead+= tmp*SIZEOF(xkmModsDesc);
- xkb->compat->groups[i].real_mods= md.realMods;
- xkb->compat->groups[i].vmods= md.virtualMods;
- if (md.virtualMods != 0) {
- unsigned mask;
- if (XkbVirtualModsToReal(xkb,md.virtualMods,&mask))
- xkb->compat->groups[i].mask= md.realMods|mask;
- }
- else xkb->compat->groups[i].mask= md.realMods;
- }
- }
- if (changes)
- changes->compat.changed_groups|= groups;
- }
- return nRead;
-}
-
-static int
-ReadXkmIndicators(FILE *file,XkbDescPtr xkb,XkbChangesPtr changes)
-{
-register unsigned nLEDs;
-xkmIndicatorMapDesc wire;
-char buf[100];
-unsigned tmp;
-int nRead=0;
-
- if ((xkb->indicators==NULL)&&(XkbAllocIndicatorMaps(xkb)!=Success)) {
- _XkbLibError(_XkbErrBadAlloc,"indicator rec",0);
- return -1;
- }
- if (XkbAllocNames(xkb,XkbIndicatorNamesMask,0,0)!=Success) {
- _XkbLibError(_XkbErrBadAlloc,"indicator names",0);
- return -1;
- }
- nLEDs= XkmGetCARD8(file,&nRead);
- nRead+= XkmSkipPadding(file,3);
- xkb->indicators->phys_indicators= XkmGetCARD32(file,&nRead);
- while (nLEDs-->0) {
- Atom name;
- XkbIndicatorMapPtr map;
-
- if ((tmp=XkmGetCountedString(file,buf,100))<1) {
- _XkbLibError(_XkbErrBadLength,"ReadXkmIndicators",0);
- return -1;
- }
- nRead+= tmp;
- if (buf[0]!='\0')
- name= XkbInternAtom(buf,FALSE);
- else name= None;
- if ((tmp=fread(&wire,SIZEOF(xkmIndicatorMapDesc),1,file))<1) {
- _XkbLibError(_XkbErrBadLength,"ReadXkmIndicators",0);
- return -1;
- }
- nRead+= tmp*SIZEOF(xkmIndicatorMapDesc);
- if (xkb->names) {
- xkb->names->indicators[wire.indicator-1]= name;
- if (changes)
- changes->names.changed_indicators|= (1<<(wire.indicator-1));
- }
- map= &xkb->indicators->maps[wire.indicator-1];
- map->flags= wire.flags;
- map->which_groups= wire.which_groups;
- map->groups= wire.groups;
- map->which_mods= wire.which_mods;
- map->mods.mask= wire.real_mods;
- map->mods.real_mods= wire.real_mods;
- map->mods.vmods= wire.vmods;
- map->ctrls= wire.ctrls;
- }
- return nRead;
-}
-
-static XkbKeyTypePtr
-FindTypeForKey(XkbDescPtr xkb,Atom name,unsigned width,KeySym *syms)
-{
- if ((!xkb)||(!xkb->map))
- return NULL;
- if (name!=None) {
- register unsigned i;
- for (i=0;i<xkb->map->num_types;i++) {
- if (xkb->map->types[i].name==name) {
- if (xkb->map->types[i].num_levels!=width)
- DebugF("Group width mismatch between key and type\n");
- return &xkb->map->types[i];
- }
- }
- }
- if ((width<2)||((syms!=NULL)&&(syms[1]==NoSymbol)))
- return &xkb->map->types[XkbOneLevelIndex];
- if (syms!=NULL) {
- if (XkbKSIsLower(syms[0])&&XkbKSIsUpper(syms[1]))
- return &xkb->map->types[XkbAlphabeticIndex];
- else if (XkbKSIsKeypad(syms[0])||XkbKSIsKeypad(syms[1]))
- return &xkb->map->types[XkbKeypadIndex];
- }
- return &xkb->map->types[XkbTwoLevelIndex];
-}
-
-static int
-ReadXkmSymbols(FILE *file,XkbDescPtr xkb)
-{
-register int i,g,s,totalVModMaps;
-xkmKeySymMapDesc wireMap;
-char buf[100];
-unsigned minKC,maxKC,groupNames,tmp;
-int nRead=0;
-
- if ((tmp=XkmGetCountedString(file,buf,100))<1)
- return -1;
- nRead+= tmp;
- minKC= XkmGetCARD8(file,&nRead);
- maxKC= XkmGetCARD8(file,&nRead);
- groupNames= XkmGetCARD8(file,&nRead);
- totalVModMaps= XkmGetCARD8(file,&nRead);
- if (XkbAllocNames(xkb,
- XkbSymbolsNameMask|XkbPhysSymbolsNameMask|XkbGroupNamesMask,
- 0,0)!=Success) {
- _XkbLibError(_XkbErrBadAlloc,"physical names",0);
- return -1;
- }
- if ((buf[0]!='\0')&&(xkb->names)) {
- Atom name;
- name= XkbInternAtom(buf,0);
- xkb->names->symbols= name;
- xkb->names->phys_symbols= name;
- }
- for (i=0,g=1;i<XkbNumKbdGroups;i++,g<<=1) {
- if (groupNames&g) {
- if ((tmp=XkmGetCountedString(file,buf,100))<1)
- return -1;
- nRead+= tmp;
-
- if (!xkb->names)
- continue;
-
- if (buf[0]!='\0') {
- Atom name;
- name= XkbInternAtom(buf,0);
- xkb->names->groups[i]= name;
- }
- else xkb->names->groups[i]= None;
- }
- }
- if (XkbAllocServerMap(xkb,XkbAllServerInfoMask,0)!=Success) {
- _XkbLibError(_XkbErrBadAlloc,"server map",0);
- return -1;
- }
- if (XkbAllocClientMap(xkb,XkbAllClientInfoMask,0)!=Success) {
- _XkbLibError(_XkbErrBadAlloc,"client map",0);
- return -1;
- }
- if (XkbAllocControls(xkb,XkbAllControlsMask)!=Success) {
- _XkbLibError(_XkbErrBadAlloc,"controls",0);
- return -1;
- }
- if ((xkb->map==NULL)||(xkb->server==NULL))
- return -1;
- if (xkb->min_key_code<8) xkb->min_key_code= minKC;
- if (xkb->max_key_code<8) xkb->max_key_code= maxKC;
- if ((minKC>=8)&&(minKC<xkb->min_key_code))
- xkb->min_key_code= minKC;
- if ((maxKC>=8)&&(maxKC>xkb->max_key_code)) {
- _XkbLibError(_XkbErrBadValue,"keys in symbol map",maxKC);
- return -1;
- }
- for (i=minKC;i<=(int)maxKC;i++) {
- Atom typeName[XkbNumKbdGroups];
- XkbKeyTypePtr type[XkbNumKbdGroups];
- if ((tmp=fread(&wireMap,SIZEOF(xkmKeySymMapDesc),1,file))<1) {
- _XkbLibError(_XkbErrBadLength,"ReadXkmSymbols",0);
- return -1;
- }
- nRead+= tmp*SIZEOF(xkmKeySymMapDesc);
- memset((char *)typeName, 0, XkbNumKbdGroups*sizeof(Atom));
- memset((char *)type, 0, XkbNumKbdGroups*sizeof(XkbKeyTypePtr));
- if (wireMap.flags&XkmKeyHasTypes) {
- register int g;
- for (g=0;g<XkbNumKbdGroups;g++) {
- if ((wireMap.flags&(1<<g))&&
- ((tmp=XkmGetCountedString(file,buf,100))>0)) {
- typeName[g]= XkbInternAtom(buf,1);
- nRead+= tmp;
- }
- type[g]=FindTypeForKey(xkb,typeName[g],wireMap.width,NULL);
- if (type[g]==NULL) {
- _XkbLibError(_XkbErrMissingTypes,"ReadXkmSymbols",0);
- return -1;
- }
- if (typeName[g]==type[g]->name)
- xkb->server->explicit[i]|= (1<<g);
- }
- }
- if (wireMap.flags&XkmRepeatingKey) {
- xkb->ctrls->per_key_repeat[i/8]|= (1<<(i%8));
- xkb->server->explicit[i]|= XkbExplicitAutoRepeatMask;
- }
- else if (wireMap.flags&XkmNonRepeatingKey) {
- xkb->ctrls->per_key_repeat[i/8]&= ~(1<<(i%8));
- xkb->server->explicit[i]|= XkbExplicitAutoRepeatMask;
- }
- xkb->map->modmap[i]= wireMap.modifier_map;
- if (XkbNumGroups(wireMap.num_groups)>0) {
- KeySym *sym;
- int nSyms;
-
- if (XkbNumGroups(wireMap.num_groups)>xkb->ctrls->num_groups)
- xkb->ctrls->num_groups= wireMap.num_groups;
- nSyms= XkbNumGroups(wireMap.num_groups)*wireMap.width;
- sym= XkbResizeKeySyms(xkb,i,nSyms);
- if (!sym)
- return -1;
- for (s=0;s<nSyms;s++) {
- *sym++= XkmGetCARD32(file,&nRead);
- }
- if (wireMap.flags&XkmKeyHasActions) {
- XkbAction * act;
- act= XkbResizeKeyActions(xkb,i,nSyms);
- for (s=0;s<nSyms;s++,act++) {
- tmp=fread(act,SIZEOF(xkmActionDesc),1,file);
- nRead+= tmp*SIZEOF(xkmActionDesc);
- }
- xkb->server->explicit[i]|= XkbExplicitInterpretMask;
- }
- }
- for (g=0;g<XkbNumGroups(wireMap.num_groups);g++) {
- if (((xkb->server->explicit[i]&(1<<g))==0)||(type[g]==NULL)) {
- KeySym *tmpSyms;
- tmpSyms= XkbKeySymsPtr(xkb,i)+(wireMap.width*g);
- type[g]= FindTypeForKey(xkb,None,wireMap.width,tmpSyms);
- }
- xkb->map->key_sym_map[i].kt_index[g]= type[g]-(&xkb->map->types[0]);
- }
- xkb->map->key_sym_map[i].group_info= wireMap.num_groups;
- xkb->map->key_sym_map[i].width= wireMap.width;
- if (wireMap.flags&XkmKeyHasBehavior) {
- xkmBehaviorDesc b;
- tmp= fread(&b,SIZEOF(xkmBehaviorDesc),1,file);
- nRead+= tmp*SIZEOF(xkmBehaviorDesc);
- xkb->server->behaviors[i].type= b.type;
- xkb->server->behaviors[i].data= b.data;
- xkb->server->explicit[i]|= XkbExplicitBehaviorMask;
- }
- }
- if (totalVModMaps>0) {
- xkmVModMapDesc v;
- for (i=0;i<totalVModMaps;i++) {
- tmp= fread(&v,SIZEOF(xkmVModMapDesc),1,file);
- nRead+= tmp*SIZEOF(xkmVModMapDesc);
- if (tmp>0)
- xkb->server->vmodmap[v.key]= v.vmods;
- }
- }
- return nRead;
-}
-
-static int
-ReadXkmGeomDoodad(
- FILE * file,
- XkbGeometryPtr geom,
- XkbSectionPtr section)
-{
-XkbDoodadPtr doodad;
-xkmDoodadDesc doodadWire;
-char buf[100];
-unsigned tmp;
-int nRead=0;
-
- nRead+= XkmGetCountedString(file,buf,100);
- tmp= fread(&doodadWire,SIZEOF(xkmDoodadDesc),1,file);
- nRead+= SIZEOF(xkmDoodadDesc)*tmp;
- doodad= XkbAddGeomDoodad(geom,section,XkbInternAtom(buf,FALSE));
- if (!doodad)
- return nRead;
- doodad->any.type= doodadWire.any.type;
- doodad->any.priority= doodadWire.any.priority;
- doodad->any.top= doodadWire.any.top;
- doodad->any.left= doodadWire.any.left;
- switch (doodadWire.any.type) {
- case XkbOutlineDoodad:
- case XkbSolidDoodad:
- doodad->shape.angle= doodadWire.shape.angle;
- doodad->shape.color_ndx= doodadWire.shape.color_ndx;
- doodad->shape.shape_ndx= doodadWire.shape.shape_ndx;
- break;
- case XkbTextDoodad:
- doodad->text.angle= doodadWire.text.angle;
- doodad->text.width= doodadWire.text.width;
- doodad->text.height= doodadWire.text.height;
- doodad->text.color_ndx= doodadWire.text.color_ndx;
- nRead+= XkmGetCountedString(file,buf,100);
- doodad->text.text= _XkbDupString(buf);
- nRead+= XkmGetCountedString(file,buf,100);
- doodad->text.font= _XkbDupString(buf);
- break;
- case XkbIndicatorDoodad:
- doodad->indicator.shape_ndx= doodadWire.indicator.shape_ndx;
- doodad->indicator.on_color_ndx= doodadWire.indicator.on_color_ndx;
- doodad->indicator.off_color_ndx= doodadWire.indicator.off_color_ndx;
- break;
- case XkbLogoDoodad:
- doodad->logo.angle= doodadWire.logo.angle;
- doodad->logo.color_ndx= doodadWire.logo.color_ndx;
- doodad->logo.shape_ndx= doodadWire.logo.shape_ndx;
- nRead+= XkmGetCountedString(file,buf,100);
- doodad->logo.logo_name= _XkbDupString(buf);
- break;
- default:
- /* report error? */
- return nRead;
- }
- return nRead;
-}
-
-static int
-ReadXkmGeomOverlay( FILE * file,
- XkbGeometryPtr geom,
- XkbSectionPtr section)
-{
-char buf[100];
-unsigned tmp;
-int nRead=0;
-XkbOverlayPtr ol;
-XkbOverlayRowPtr row;
-xkmOverlayDesc olWire;
-xkmOverlayRowDesc rowWire;
-register int r;
-
- nRead+= XkmGetCountedString(file,buf,100);
- tmp= fread(&olWire,SIZEOF(xkmOverlayDesc),1,file);
- nRead+= tmp*SIZEOF(xkmOverlayDesc);
- ol= XkbAddGeomOverlay(section,XkbInternAtom(buf,FALSE),
- olWire.num_rows);
- if (!ol)
- return nRead;
- for (r=0;r<olWire.num_rows;r++) {
- int k;
- xkmOverlayKeyDesc keyWire;
- tmp= fread(&rowWire,SIZEOF(xkmOverlayRowDesc),1,file);
- nRead+= tmp*SIZEOF(xkmOverlayRowDesc);
- row= XkbAddGeomOverlayRow(ol,rowWire.row_under,rowWire.num_keys);
- if (!row) {
- _XkbLibError(_XkbErrBadAlloc,"ReadXkmGeomOverlay",0);
- return nRead;
- }
- for (k=0;k<rowWire.num_keys;k++) {
- tmp= fread(&keyWire,SIZEOF(xkmOverlayKeyDesc),1,file);
- nRead+= tmp*SIZEOF(xkmOverlayKeyDesc);
- memcpy(row->keys[k].over.name,keyWire.over,XkbKeyNameLength);
- memcpy(row->keys[k].under.name,keyWire.under,XkbKeyNameLength);
- }
- row->num_keys= rowWire.num_keys;
- }
- return nRead;
-}
-
-static int
-ReadXkmGeomSection( FILE * file,
- XkbGeometryPtr geom)
-{
-register int i;
-XkbSectionPtr section;
-xkmSectionDesc sectionWire;
-unsigned tmp;
-int nRead= 0;
-char buf[100];
-Atom nameAtom;
-
- nRead+= XkmGetCountedString(file,buf,100);
- nameAtom= XkbInternAtom(buf,FALSE);
- tmp= fread(§ionWire,SIZEOF(xkmSectionDesc),1,file);
- nRead+= SIZEOF(xkmSectionDesc)*tmp;
- section= XkbAddGeomSection(geom,nameAtom,sectionWire.num_rows,
- sectionWire.num_doodads,
- sectionWire.num_overlays);
- if (!section) {
- _XkbLibError(_XkbErrBadAlloc,"ReadXkmGeomSection",0);
- return nRead;
- }
- section->top= sectionWire.top;
- section->left= sectionWire.left;
- section->width= sectionWire.width;
- section->height= sectionWire.height;
- section->angle= sectionWire.angle;
- section->priority= sectionWire.priority;
- if (sectionWire.num_rows>0) {
- register int k;
- XkbRowPtr row;
- xkmRowDesc rowWire;
- XkbKeyPtr key;
- xkmKeyDesc keyWire;
-
- for (i=0;i<sectionWire.num_rows;i++) {
- tmp= fread(&rowWire,SIZEOF(xkmRowDesc),1,file);
- nRead+= SIZEOF(xkmRowDesc)*tmp;
- row= XkbAddGeomRow(section,rowWire.num_keys);
- if (!row) {
- _XkbLibError(_XkbErrBadAlloc,"ReadXkmKeycodes",0);
- return nRead;
- }
- row->top= rowWire.top;
- row->left= rowWire.left;
- row->vertical= rowWire.vertical;
- for (k=0;k<rowWire.num_keys;k++) {
- tmp= fread(&keyWire,SIZEOF(xkmKeyDesc),1,file);
- nRead+= SIZEOF(xkmKeyDesc)*tmp;
- key= XkbAddGeomKey(row);
- if (!key) {
- _XkbLibError(_XkbErrBadAlloc,"ReadXkmGeomSection",0);
- return nRead;
- }
- memcpy(key->name.name,keyWire.name,XkbKeyNameLength);
- key->gap= keyWire.gap;
- key->shape_ndx= keyWire.shape_ndx;
- key->color_ndx= keyWire.color_ndx;
- }
- }
- }
- if (sectionWire.num_doodads>0) {
- for (i=0;i<sectionWire.num_doodads;i++) {
- tmp= ReadXkmGeomDoodad(file,geom,section);
- nRead+= tmp;
- if (tmp<1)
- return nRead;
- }
- }
- if (sectionWire.num_overlays>0) {
- for (i=0;i<sectionWire.num_overlays;i++) {
- tmp= ReadXkmGeomOverlay(file,geom,section);
- nRead+= tmp;
- if (tmp<1)
- return nRead;
- }
- }
- return nRead;
-}
-
-static int
-ReadXkmGeometry(FILE *file,XkbDescPtr xkb)
-{
-register int i;
-char buf[100];
-unsigned tmp;
-int nRead= 0;
-xkmGeometryDesc wireGeom;
-XkbGeometryPtr geom;
-XkbGeometrySizesRec sizes;
-
- nRead+= XkmGetCountedString(file,buf,100);
- tmp= fread(&wireGeom,SIZEOF(xkmGeometryDesc),1,file);
- nRead+= tmp*SIZEOF(xkmGeometryDesc);
- sizes.which= XkbGeomAllMask;
- sizes.num_properties= wireGeom.num_properties;
- sizes.num_colors= wireGeom.num_colors;
- sizes.num_shapes= wireGeom.num_shapes;
- sizes.num_sections= wireGeom.num_sections;
- sizes.num_doodads= wireGeom.num_doodads;
- sizes.num_key_aliases= wireGeom.num_key_aliases;
- if (XkbAllocGeometry(xkb,&sizes)!=Success) {
- _XkbLibError(_XkbErrBadAlloc,"ReadXkmGeometry",0);
- return nRead;
- }
- geom= xkb->geom;
- geom->name= XkbInternAtom(buf,FALSE);
- geom->width_mm= wireGeom.width_mm;
- geom->height_mm= wireGeom.height_mm;
- nRead+= XkmGetCountedString(file,buf,100);
- geom->label_font= _XkbDupString(buf);
- if (wireGeom.num_properties>0) {
- char val[1024];
- for (i=0;i<wireGeom.num_properties;i++) {
- nRead+= XkmGetCountedString(file,buf,100);
- nRead+= XkmGetCountedString(file,val,1024);
- if (XkbAddGeomProperty(geom,buf,val)==NULL) {
- _XkbLibError(_XkbErrBadAlloc,"ReadXkmGeometry",0);
- return nRead;
- }
- }
- }
- if (wireGeom.num_colors>0) {
- for (i=0;i<wireGeom.num_colors;i++) {
- nRead+= XkmGetCountedString(file,buf,100);
- if (XkbAddGeomColor(geom,buf,i)==NULL) {
- _XkbLibError(_XkbErrBadAlloc,"ReadXkmGeometry",0);
- return nRead;
- }
- }
- }
- geom->base_color= &geom->colors[wireGeom.base_color_ndx];
- geom->label_color= &geom->colors[wireGeom.label_color_ndx];
- if (wireGeom.num_shapes>0) {
- XkbShapePtr shape;
- xkmShapeDesc shapeWire;
- Atom nameAtom;
- for (i=0;i<wireGeom.num_shapes;i++) {
- register int n;
- XkbOutlinePtr ol;
- xkmOutlineDesc olWire;
- nRead+= XkmGetCountedString(file,buf,100);
- nameAtom= XkbInternAtom(buf,FALSE);
- tmp= fread(&shapeWire,SIZEOF(xkmShapeDesc),1,file);
- nRead+= tmp*SIZEOF(xkmShapeDesc);
- shape= XkbAddGeomShape(geom,nameAtom,shapeWire.num_outlines);
- if (!shape) {
- _XkbLibError(_XkbErrBadAlloc,"ReadXkmGeometry",0);
- return nRead;
- }
- for (n=0;n<shapeWire.num_outlines;n++) {
- register int p;
- xkmPointDesc ptWire;
- tmp= fread(&olWire,SIZEOF(xkmOutlineDesc),1,file);
- nRead+= tmp*SIZEOF(xkmOutlineDesc);
- ol= XkbAddGeomOutline(shape,olWire.num_points);
- if (!ol) {
- _XkbLibError(_XkbErrBadAlloc,"ReadXkmGeometry",0);
- return nRead;
- }
- ol->num_points= olWire.num_points;
- ol->corner_radius= olWire.corner_radius;
- for (p=0;p<olWire.num_points;p++) {
- tmp= fread(&ptWire,SIZEOF(xkmPointDesc),1,file);
- nRead+= tmp*SIZEOF(xkmPointDesc);
- ol->points[p].x= ptWire.x;
- ol->points[p].y= ptWire.y;
- if (ptWire.x<shape->bounds.x1) shape->bounds.x1= ptWire.x;
- if (ptWire.x>shape->bounds.x2) shape->bounds.x2= ptWire.x;
- if (ptWire.y<shape->bounds.y1) shape->bounds.y1= ptWire.y;
- if (ptWire.y>shape->bounds.y2) shape->bounds.y2= ptWire.y;
- }
- }
- if (shapeWire.primary_ndx!=XkbNoShape)
- shape->primary= &shape->outlines[shapeWire.primary_ndx];
- if (shapeWire.approx_ndx!=XkbNoShape)
- shape->approx= &shape->outlines[shapeWire.approx_ndx];
- }
- }
- if (wireGeom.num_sections>0) {
- for (i=0;i<wireGeom.num_sections;i++) {
- tmp= ReadXkmGeomSection(file,geom);
- nRead+= tmp;
- if (tmp==0)
- return nRead;
- }
- }
- if (wireGeom.num_doodads>0) {
- for (i=0;i<wireGeom.num_doodads;i++) {
- tmp= ReadXkmGeomDoodad(file,geom,NULL);
- nRead+= tmp;
- if (tmp==0)
- return nRead;
- }
- }
- if ((wireGeom.num_key_aliases>0)&&(geom->key_aliases)) {
- int sz= XkbKeyNameLength*2;
- int num= wireGeom.num_key_aliases;
- if (fread(geom->key_aliases,sz,num,file)!=num) {
- _XkbLibError(_XkbErrBadLength,"ReadXkmGeometry",0);
- return -1;
- }
- nRead+= (num*sz);
- geom->num_key_aliases= num;
- }
- return nRead;
-}
-
-Bool
-XkmProbe(FILE *file)
-{
-unsigned hdr,tmp;
-int nRead=0;
-
- hdr= (('x'<<24)|('k'<<16)|('m'<<8)|XkmFileVersion);
- tmp= XkmGetCARD32(file,&nRead);
- if (tmp!=hdr) {
- if ((tmp&(~0xff))==(hdr&(~0xff))) {
- _XkbLibError(_XkbErrBadFileVersion,"XkmProbe",tmp&0xff);
- }
- return 0;
- }
- return 1;
-}
-
-static Bool
-XkmReadTOC(FILE *file,xkmFileInfo* file_info,int max_toc,xkmSectionInfo *toc)
-{
-unsigned hdr,tmp;
-int nRead=0;
-unsigned i,size_toc;
-
- hdr= (('x'<<24)|('k'<<16)|('m'<<8)|XkmFileVersion);
- tmp= XkmGetCARD32(file,&nRead);
- if (tmp!=hdr) {
- if ((tmp&(~0xff))==(hdr&(~0xff))) {
- _XkbLibError(_XkbErrBadFileVersion,"XkmReadTOC",tmp&0xff);
- }
- else {
- _XkbLibError(_XkbErrBadFileType,"XkmReadTOC",tmp);
- }
- return 0;
- }
- fread(file_info,SIZEOF(xkmFileInfo),1,file);
- size_toc= file_info->num_toc;
- if (size_toc>max_toc) {
- DebugF("Warning! Too many TOC entries; last %d ignored\n",
- size_toc-max_toc);
- size_toc= max_toc;
- }
- for (i=0;i<size_toc;i++) {
- fread(&toc[i],SIZEOF(xkmSectionInfo),1,file);
- }
- return 1;
-}
-
-/***====================================================================***/
-
-#define MAX_TOC 16
-unsigned
-XkmReadFile(FILE *file,unsigned need,unsigned want,XkbDescPtr *xkb)
-{
-register unsigned i;
-xkmSectionInfo toc[MAX_TOC],tmpTOC;
-xkmFileInfo fileInfo;
-unsigned tmp,nRead=0;
-unsigned which= need|want;
-
- if (!XkmReadTOC(file,&fileInfo,MAX_TOC,toc))
- return which;
- if ((fileInfo.present&need)!=need) {
- _XkbLibError(_XkbErrIllegalContents,"XkmReadFile",
- need&(~fileInfo.present));
- return which;
- }
- if (*xkb==NULL)
- *xkb= XkbAllocKeyboard();
- for (i=0;i<fileInfo.num_toc;i++) {
- fseek(file,toc[i].offset,SEEK_SET);
- tmp= fread(&tmpTOC,SIZEOF(xkmSectionInfo),1,file);
- nRead= tmp*SIZEOF(xkmSectionInfo);
- if ((tmpTOC.type!=toc[i].type)||(tmpTOC.format!=toc[i].format)||
- (tmpTOC.size!=toc[i].size)||(tmpTOC.offset!=toc[i].offset)) {
- return which;
- }
- if ((which&(1<<tmpTOC.type))==0) {
- continue;
- }
- switch (tmpTOC.type) {
- case XkmVirtualModsIndex:
- tmp= ReadXkmVirtualMods(file,*xkb,NULL);
- break;
- case XkmTypesIndex:
- tmp= ReadXkmKeyTypes(file,*xkb,NULL);
- break;
- case XkmCompatMapIndex:
- tmp= ReadXkmCompatMap(file,*xkb,NULL);
- break;
- case XkmKeyNamesIndex:
- tmp= ReadXkmKeycodes(file,*xkb,NULL);
- break;
- case XkmIndicatorsIndex:
- tmp= ReadXkmIndicators(file,*xkb,NULL);
- break;
- case XkmSymbolsIndex:
- tmp= ReadXkmSymbols(file,*xkb);
- break;
- case XkmGeometryIndex:
- tmp= ReadXkmGeometry(file,*xkb);
- break;
- default:
- _XkbLibError(_XkbErrBadImplementation,
- XkbConfigText(tmpTOC.type,XkbMessage),0);
- tmp= 0;
- break;
- }
- if (tmp>0) {
- nRead+= tmp;
- which&= ~(1<<toc[i].type);
- (*xkb)->defined|= (1<<toc[i].type);
- }
- if (nRead!=tmpTOC.size) {
- _XkbLibError(_XkbErrBadLength,XkbConfigText(tmpTOC.type,XkbMessage),
- nRead-tmpTOC.size);
- }
- }
- return which;
-}
+/************************************************************ + Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc. + + Permission 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 that both that copyright + notice and this permission notice appear in supporting + documentation, and that the name of Silicon Graphics not be + used in advertising or publicity pertaining to distribution + of the software without specific prior written permission. + Silicon Graphics makes no representation about the suitability + of this software for any purpose. It is provided "as is" + without any express or implied warranty. + + SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS + SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON + GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL + DAMAGES OR ANY 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 THIS SOFTWARE. + + ********************************************************/ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include <stdio.h> + +#include <X11/Xos.h> +#include <X11/Xfuncs.h> + +#include <X11/X.h> +#include <X11/Xproto.h> +#include <X11/keysym.h> +#include <X11/extensions/XKMformat.h> +#include "misc.h" +#include "inputstr.h" +#include "xkbstr.h" +#include "xkbsrv.h" +#include "xkbgeom.h" + +Atom +XkbInternAtom(char *str,Bool only_if_exists) +{ + if (str==NULL) + return None; + return MakeAtom(str,strlen(str),!only_if_exists); +} + +/***====================================================================***/ + +static void * +XkmInsureSize(void *oldPtr,int oldCount,int *newCountRtrn,int elemSize) +{ +int newCount= *newCountRtrn; + + if (oldPtr==NULL) { + if (newCount==0) + return NULL; + oldPtr= calloc(newCount,elemSize); + } + else if (oldCount<newCount) { + oldPtr= realloc(oldPtr,newCount*elemSize); + if (oldPtr!=NULL) { + char *tmp= (char *)oldPtr; + memset(&tmp[oldCount*elemSize], 0, (newCount-oldCount)*elemSize); + } + } + else if (newCount<oldCount) { + *newCountRtrn= oldCount; + } + return oldPtr; +} + +#define XkmInsureTypedSize(p,o,n,t) ((p)=((t *)XkmInsureSize((char *)(p),(o),(n),sizeof(t)))) + +static CARD8 +XkmGetCARD8(FILE *file,int *pNRead) +{ +int tmp; + tmp= getc(file); + if (pNRead&&(tmp!=EOF)) + (*pNRead)+= 1; + return tmp; +} + +static CARD16 +XkmGetCARD16(FILE *file,int *pNRead) +{ +CARD16 val; + + if ((fread(&val,2,1,file)==1)&&(pNRead)) + (*pNRead)+= 2; + return val; +} + +static CARD32 +XkmGetCARD32(FILE *file,int *pNRead) +{ +CARD32 val; + + if ((fread(&val,4,1,file)==1)&&(pNRead)) + (*pNRead)+= 4; + return val; +} + +static int +XkmSkipPadding(FILE *file,unsigned pad) +{ +register int i,nRead=0; + + for (i=0;i<pad;i++) { + if (getc(file)!=EOF) + nRead++; + } + return nRead; +} + +static int +XkmGetCountedString(FILE *file,char *str,int max_len) +{ +int count,nRead=0; + + count= XkmGetCARD16(file,&nRead); + if (count>0) { + int tmp; + if (count>max_len) { + tmp= fread(str,1,max_len,file); + while (tmp<count) { + if ((getc(file))!=EOF) + tmp++; + else break; + } + } + else { + tmp= fread(str,1,count,file); + } + nRead+= tmp; + } + if (count>=max_len) str[max_len-1]= '\0'; + else str[count]= '\0'; + count= XkbPaddedSize(nRead)-nRead; + if (count>0) + nRead+= XkmSkipPadding(file,count); + return nRead; +} + +/***====================================================================***/ + +static int +ReadXkmVirtualMods(FILE *file,XkbDescPtr xkb,XkbChangesPtr changes) +{ +register unsigned int i,bit; +unsigned int bound,named,tmp; +int nRead=0; + + if (XkbAllocServerMap(xkb,XkbVirtualModsMask,0)!=Success) { + _XkbLibError(_XkbErrBadAlloc,"ReadXkmVirtualMods",0); + return -1; + } + bound= XkmGetCARD16(file,&nRead); + named= XkmGetCARD16(file,&nRead); + for (i=tmp=0,bit=1;i<XkbNumVirtualMods;i++,bit<<=1) { + if (bound&bit) { + xkb->server->vmods[i]= XkmGetCARD8(file,&nRead); + if (changes) + changes->map.vmods|= bit; + tmp++; + } + } + if ((i= XkbPaddedSize(tmp)-tmp)>0) + nRead+= XkmSkipPadding(file,i); + if (XkbAllocNames(xkb,XkbVirtualModNamesMask,0,0)!=Success) { + _XkbLibError(_XkbErrBadAlloc,"ReadXkmVirtualMods",0); + return -1; + } + for (i=0,bit=1;i<XkbNumVirtualMods;i++,bit<<=1) { + char name[100]; + if (named&bit) { + if (nRead+=XkmGetCountedString(file,name,100)) { + xkb->names->vmods[i]= XkbInternAtom(name,FALSE); + if (changes) + changes->names.changed_vmods|= bit; + } + } + } + return nRead; +} + +/***====================================================================***/ + +static int +ReadXkmKeycodes(FILE *file,XkbDescPtr xkb,XkbChangesPtr changes) +{ +register int i; +unsigned minKC,maxKC,nAl; +int nRead=0; +char name[100]; +XkbKeyNamePtr pN; + + name[0]= '\0'; + nRead+= XkmGetCountedString(file,name,100); + minKC= XkmGetCARD8(file,&nRead); + maxKC= XkmGetCARD8(file,&nRead); + if (xkb->min_key_code==0) { + xkb->min_key_code= minKC; + xkb->max_key_code= maxKC; + } + else { + if (minKC<xkb->min_key_code) + xkb->min_key_code= minKC; + if (maxKC>xkb->max_key_code) { + _XkbLibError(_XkbErrBadValue,"ReadXkmKeycodes",maxKC); + return -1; + } + } + nAl= XkmGetCARD8(file,&nRead); + nRead+= XkmSkipPadding(file,1); + +#define WANTED (XkbKeycodesNameMask|XkbKeyNamesMask|XkbKeyAliasesMask) + if (XkbAllocNames(xkb,WANTED,0,nAl)!=Success) { + _XkbLibError(_XkbErrBadAlloc,"ReadXkmKeycodes",0); + return -1; + } + if (name[0]!='\0') { + xkb->names->keycodes= XkbInternAtom(name,FALSE); + } + + for (pN=&xkb->names->keys[minKC],i=minKC;i<=(int)maxKC;i++,pN++) { + if (fread(pN,1,XkbKeyNameLength,file)!=XkbKeyNameLength) { + _XkbLibError(_XkbErrBadLength,"ReadXkmKeycodes",0); + return -1; + } + nRead+= XkbKeyNameLength; + } + if (nAl>0) { + XkbKeyAliasPtr pAl; + for (pAl= xkb->names->key_aliases,i=0;i<nAl;i++,pAl++) { + int tmp; + tmp= fread(pAl,1,2*XkbKeyNameLength,file); + if (tmp!=2*XkbKeyNameLength) { + _XkbLibError(_XkbErrBadLength,"ReadXkmKeycodes",0); + return -1; + } + nRead+= 2*XkbKeyNameLength; + } + if (changes) + changes->names.changed|= XkbKeyAliasesMask; + } + if (changes) + changes->names.changed|= XkbKeyNamesMask; + return nRead; +} + +/***====================================================================***/ + +static int +ReadXkmKeyTypes(FILE *file,XkbDescPtr xkb,XkbChangesPtr changes) +{ +register unsigned i,n; +unsigned num_types; +int nRead=0; +int tmp; +XkbKeyTypePtr type; +xkmKeyTypeDesc wire; +XkbKTMapEntryPtr entry; +xkmKTMapEntryDesc wire_entry; +char buf[100]; + + if ((tmp= XkmGetCountedString(file,buf,100))<1) { + _XkbLibError(_XkbErrBadLength,"ReadXkmKeyTypes",0); + return -1; + } + nRead+= tmp; + if (buf[0]!='\0') { + if (XkbAllocNames(xkb,XkbTypesNameMask,0,0)!=Success) { + _XkbLibError(_XkbErrBadAlloc,"ReadXkmKeyTypes",0); + return -1; + } + xkb->names->types= XkbInternAtom(buf,FALSE); + } + num_types= XkmGetCARD16(file,&nRead); + nRead+= XkmSkipPadding(file,2); + if (num_types<1) + return nRead; + if (XkbAllocClientMap(xkb,XkbKeyTypesMask,num_types)!=Success) { + _XkbLibError(_XkbErrBadAlloc,"ReadXkmKeyTypes",0); + return nRead; + } + xkb->map->num_types= num_types; + if (num_types<XkbNumRequiredTypes) { + _XkbLibError(_XkbErrMissingReqTypes,"ReadXkmKeyTypes",0); + return -1; + } + type= xkb->map->types; + for (i=0;i<num_types;i++,type++) { + if ((int)fread(&wire,SIZEOF(xkmKeyTypeDesc),1,file)<1) { + _XkbLibError(_XkbErrBadLength,"ReadXkmKeyTypes",0); + return -1; + } + nRead+= SIZEOF(xkmKeyTypeDesc); + if (((i==XkbOneLevelIndex)&&(wire.numLevels!=1))|| + (((i==XkbTwoLevelIndex)||(i==XkbAlphabeticIndex)|| + ((i)==XkbKeypadIndex))&&(wire.numLevels!=2))) { + _XkbLibError(_XkbErrBadTypeWidth,"ReadXkmKeyTypes",i); + return -1; + } + tmp= wire.nMapEntries; + XkmInsureTypedSize(type->map,type->map_count,&tmp,XkbKTMapEntryRec); + if ((wire.nMapEntries>0)&&(type->map==NULL)) { + _XkbLibError(_XkbErrBadValue,"ReadXkmKeyTypes",wire.nMapEntries); + return -1; + } + for (n=0,entry= type->map;n<wire.nMapEntries;n++,entry++) { + if (fread(&wire_entry,SIZEOF(xkmKTMapEntryDesc),1,file)<(int)1) { + _XkbLibError(_XkbErrBadLength,"ReadXkmKeyTypes",0); + return -1; + } + nRead+= SIZEOF(xkmKTMapEntryDesc); + entry->active= (wire_entry.virtualMods==0); + entry->level= wire_entry.level; + entry->mods.mask= wire_entry.realMods; + entry->mods.real_mods= wire_entry.realMods; + entry->mods.vmods= wire_entry.virtualMods; + } + nRead+= XkmGetCountedString(file,buf,100); + if (((i==XkbOneLevelIndex)&&(strcmp(buf,"ONE_LEVEL")!=0))|| + ((i==XkbTwoLevelIndex)&&(strcmp(buf,"TWO_LEVEL")!=0))|| + ((i==XkbAlphabeticIndex)&&(strcmp(buf,"ALPHABETIC")!=0))|| + ((i==XkbKeypadIndex)&&(strcmp(buf,"KEYPAD")!=0))) { + _XkbLibError(_XkbErrBadTypeName,"ReadXkmKeyTypes",0); + return -1; + } + if (buf[0]!='\0') { + type->name= XkbInternAtom(buf,FALSE); + } + else type->name= None; + + if (wire.preserve) { + xkmModsDesc p_entry; + XkbModsPtr pre; + XkmInsureTypedSize(type->preserve,type->map_count,&tmp, + XkbModsRec); + if (type->preserve==NULL) { + _XkbLibError(_XkbErrBadMatch,"ReadXkmKeycodes",0); + return -1; + } + for (n=0,pre=type->preserve;n<wire.nMapEntries;n++,pre++) { + if (fread(&p_entry,SIZEOF(xkmModsDesc),1,file)<1) { + _XkbLibError(_XkbErrBadLength,"ReadXkmKeycodes",0); + return -1; + } + nRead+= SIZEOF(xkmModsDesc); + pre->mask= p_entry.realMods; + pre->real_mods= p_entry.realMods; + pre->vmods= p_entry.virtualMods; + } + } + if (wire.nLevelNames>0) { + int width= wire.numLevels; + if (wire.nLevelNames>(unsigned)width) { + _XkbLibError(_XkbErrBadMatch,"ReadXkmKeycodes",0); + return -1; + } + XkmInsureTypedSize(type->level_names,type->num_levels,&width,Atom); + if (type->level_names!=NULL) { + for (n=0;n<wire.nLevelNames;n++) { + if ((tmp=XkmGetCountedString(file,buf,100))<1) + return -1; + nRead+= tmp; + if (strlen(buf)==0) + type->level_names[n]= None; + else type->level_names[n]= XkbInternAtom(buf,0); + } + } + } + type->mods.mask= wire.realMods; + type->mods.real_mods= wire.realMods; + type->mods.vmods= wire.virtualMods; + type->num_levels= wire.numLevels; + type->map_count= wire.nMapEntries; + } + if (changes) { + changes->map.changed|= XkbKeyTypesMask; + changes->map.first_type= 0; + changes->map.num_types= xkb->map->num_types; + } + return nRead; +} + +/***====================================================================***/ + +static int +ReadXkmCompatMap(FILE *file,XkbDescPtr xkb,XkbChangesPtr changes) +{ +register int i; +unsigned num_si,groups; +char name[100]; +XkbSymInterpretPtr interp; +xkmSymInterpretDesc wire; +unsigned tmp; +int nRead=0; +XkbCompatMapPtr compat; +XkbAction *act; + + if ((tmp= XkmGetCountedString(file,name,100))<1) { + _XkbLibError(_XkbErrBadLength,"ReadXkmCompatMap",0); + return -1; + } + nRead+= tmp; + if (name[0]!='\0') { + if (XkbAllocNames(xkb,XkbCompatNameMask,0,0)!=Success) { + _XkbLibError(_XkbErrBadAlloc,"ReadXkmCompatMap",0); + return -1; + } + xkb->names->compat= XkbInternAtom(name,FALSE); + } + num_si= XkmGetCARD16(file,&nRead); + groups= XkmGetCARD8(file,&nRead); + nRead+= XkmSkipPadding(file,1); + if (XkbAllocCompatMap(xkb,XkbAllCompatMask,num_si)!=Success) + return -1; + compat= xkb->compat; + compat->num_si= num_si; + interp= compat->sym_interpret; + for (i=0;i<num_si;i++,interp++) { + tmp= fread(&wire,SIZEOF(xkmSymInterpretDesc),1,file); + nRead+= tmp*SIZEOF(xkmSymInterpretDesc); + interp->sym= wire.sym; + interp->mods= wire.mods; + interp->match= wire.match; + interp->virtual_mod= wire.virtualMod; + interp->flags= wire.flags; + interp->act.type= wire.actionType; + act = (XkbAction *) &interp->act; + + switch (interp->act.type) { + case XkbSA_SetMods: + case XkbSA_LatchMods: + case XkbSA_LockMods: + act->mods.flags = wire.actionData[0]; + act->mods.mask = wire.actionData[1]; + act->mods.real_mods = wire.actionData[2]; + act->mods.vmods1 = wire.actionData[3]; + act->mods.vmods2 = wire.actionData[4]; + break; + case XkbSA_SetGroup: + case XkbSA_LatchGroup: + case XkbSA_LockGroup: + act->group.flags = wire.actionData[0]; + act->group.group_XXX = wire.actionData[1]; + break; + case XkbSA_MovePtr: + act->ptr.flags = wire.actionData[0]; + act->ptr.high_XXX = wire.actionData[1]; + act->ptr.low_XXX = wire.actionData[2]; + act->ptr.high_YYY = wire.actionData[3]; + act->ptr.low_YYY = wire.actionData[4]; + break; + case XkbSA_PtrBtn: + case XkbSA_LockPtrBtn: + act->btn.flags = wire.actionData[0]; + act->btn.count = wire.actionData[1]; + act->btn.button = wire.actionData[2]; + break; + case XkbSA_DeviceBtn: + case XkbSA_LockDeviceBtn: + act->devbtn.flags = wire.actionData[0]; + act->devbtn.count = wire.actionData[1]; + act->devbtn.button = wire.actionData[2]; + act->devbtn.device = wire.actionData[3]; + break; + case XkbSA_SetPtrDflt: + act->dflt.flags = wire.actionData[0]; + act->dflt.affect = wire.actionData[1]; + act->dflt.valueXXX = wire.actionData[2]; + break; + case XkbSA_ISOLock: + act->iso.flags = wire.actionData[0]; + act->iso.mask = wire.actionData[1]; + act->iso.real_mods = wire.actionData[2]; + act->iso.group_XXX = wire.actionData[3]; + act->iso.affect = wire.actionData[4]; + act->iso.vmods1 = wire.actionData[5]; + act->iso.vmods2 = wire.actionData[6]; + break; + case XkbSA_SwitchScreen: + act->screen.flags = wire.actionData[0]; + act->screen.screenXXX = wire.actionData[1]; + break; + case XkbSA_SetControls: + case XkbSA_LockControls: + act->ctrls.flags = wire.actionData[0]; + act->ctrls.ctrls3 = wire.actionData[1]; + act->ctrls.ctrls2 = wire.actionData[2]; + act->ctrls.ctrls1 = wire.actionData[3]; + act->ctrls.ctrls0 = wire.actionData[4]; + break; + case XkbSA_RedirectKey: + act->redirect.new_key = wire.actionData[0]; + act->redirect.mods_mask = wire.actionData[1]; + act->redirect.mods = wire.actionData[2]; + act->redirect.vmods_mask0 = wire.actionData[3]; + act->redirect.vmods_mask1 = wire.actionData[4]; + act->redirect.vmods0 = wire.actionData[4]; + act->redirect.vmods1 = wire.actionData[5]; + break; + case XkbSA_DeviceValuator: + act->devval.device = wire.actionData[0]; + act->devval.v1_what = wire.actionData[1]; + act->devval.v1_ndx = wire.actionData[2]; + act->devval.v1_value = wire.actionData[3]; + act->devval.v2_what = wire.actionData[4]; + act->devval.v2_ndx = wire.actionData[5]; + act->devval.v2_what = wire.actionData[6]; + break; + + case XkbSA_XFree86Private: + /* copy the kind of action */ + memcpy(act->any.data, wire.actionData, XkbAnyActionDataSize); + break ; + + case XkbSA_Terminate: + /* no args, kinda (note: untrue for xfree86). */ + break; + case XkbSA_ActionMessage: + /* unsupported. */ + break; + } + } + if ((num_si>0)&&(changes)) { + changes->compat.first_si= 0; + changes->compat.num_si= num_si; + } + if (groups) { + register unsigned bit; + for (i=0,bit=1;i<XkbNumKbdGroups;i++,bit<<=1) { + xkmModsDesc md; + if (groups&bit) { + tmp= fread(&md,SIZEOF(xkmModsDesc),1,file); + nRead+= tmp*SIZEOF(xkmModsDesc); + xkb->compat->groups[i].real_mods= md.realMods; + xkb->compat->groups[i].vmods= md.virtualMods; + if (md.virtualMods != 0) { + unsigned mask; + if (XkbVirtualModsToReal(xkb,md.virtualMods,&mask)) + xkb->compat->groups[i].mask= md.realMods|mask; + } + else xkb->compat->groups[i].mask= md.realMods; + } + } + if (changes) + changes->compat.changed_groups|= groups; + } + return nRead; +} + +static int +ReadXkmIndicators(FILE *file,XkbDescPtr xkb,XkbChangesPtr changes) +{ +register unsigned nLEDs; +xkmIndicatorMapDesc wire; +char buf[100]; +unsigned tmp; +int nRead=0; + + if ((xkb->indicators==NULL)&&(XkbAllocIndicatorMaps(xkb)!=Success)) { + _XkbLibError(_XkbErrBadAlloc,"indicator rec",0); + return -1; + } + if (XkbAllocNames(xkb,XkbIndicatorNamesMask,0,0)!=Success) { + _XkbLibError(_XkbErrBadAlloc,"indicator names",0); + return -1; + } + nLEDs= XkmGetCARD8(file,&nRead); + nRead+= XkmSkipPadding(file,3); + xkb->indicators->phys_indicators= XkmGetCARD32(file,&nRead); + while (nLEDs-->0) { + Atom name; + XkbIndicatorMapPtr map; + + if ((tmp=XkmGetCountedString(file,buf,100))<1) { + _XkbLibError(_XkbErrBadLength,"ReadXkmIndicators",0); + return -1; + } + nRead+= tmp; + if (buf[0]!='\0') + name= XkbInternAtom(buf,FALSE); + else name= None; + if ((tmp=fread(&wire,SIZEOF(xkmIndicatorMapDesc),1,file))<1) { + _XkbLibError(_XkbErrBadLength,"ReadXkmIndicators",0); + return -1; + } + nRead+= tmp*SIZEOF(xkmIndicatorMapDesc); + if (xkb->names) { + xkb->names->indicators[wire.indicator-1]= name; + if (changes) + changes->names.changed_indicators|= (1<<(wire.indicator-1)); + } + map= &xkb->indicators->maps[wire.indicator-1]; + map->flags= wire.flags; + map->which_groups= wire.which_groups; + map->groups= wire.groups; + map->which_mods= wire.which_mods; + map->mods.mask= wire.real_mods; + map->mods.real_mods= wire.real_mods; + map->mods.vmods= wire.vmods; + map->ctrls= wire.ctrls; + } + return nRead; +} + +static XkbKeyTypePtr +FindTypeForKey(XkbDescPtr xkb,Atom name,unsigned width,KeySym *syms) +{ + if ((!xkb)||(!xkb->map)) + return NULL; + if (name!=None) { + register unsigned i; + for (i=0;i<xkb->map->num_types;i++) { + if (xkb->map->types[i].name==name) { + if (xkb->map->types[i].num_levels!=width) + DebugF("Group width mismatch between key and type\n"); + return &xkb->map->types[i]; + } + } + } + if ((width<2)||((syms!=NULL)&&(syms[1]==NoSymbol))) + return &xkb->map->types[XkbOneLevelIndex]; + if (syms!=NULL) { + if (XkbKSIsLower(syms[0])&&XkbKSIsUpper(syms[1])) + return &xkb->map->types[XkbAlphabeticIndex]; + else if (XkbKSIsKeypad(syms[0])||XkbKSIsKeypad(syms[1])) + return &xkb->map->types[XkbKeypadIndex]; + } + return &xkb->map->types[XkbTwoLevelIndex]; +} + +static int +ReadXkmSymbols(FILE *file,XkbDescPtr xkb) +{ +register int i,g,s,totalVModMaps; +xkmKeySymMapDesc wireMap; +char buf[100]; +unsigned minKC,maxKC,groupNames,tmp; +int nRead=0; + + if ((tmp=XkmGetCountedString(file,buf,100))<1) + return -1; + nRead+= tmp; + minKC= XkmGetCARD8(file,&nRead); + maxKC= XkmGetCARD8(file,&nRead); + groupNames= XkmGetCARD8(file,&nRead); + totalVModMaps= XkmGetCARD8(file,&nRead); + if (XkbAllocNames(xkb, + XkbSymbolsNameMask|XkbPhysSymbolsNameMask|XkbGroupNamesMask, + 0,0)!=Success) { + _XkbLibError(_XkbErrBadAlloc,"physical names",0); + return -1; + } + if ((buf[0]!='\0')&&(xkb->names)) { + Atom name; + name= XkbInternAtom(buf,0); + xkb->names->symbols= name; + xkb->names->phys_symbols= name; + } + for (i=0,g=1;i<XkbNumKbdGroups;i++,g<<=1) { + if (groupNames&g) { + if ((tmp=XkmGetCountedString(file,buf,100))<1) + return -1; + nRead+= tmp; + + if (!xkb->names) + continue; + + if (buf[0]!='\0') { + Atom name; + name= XkbInternAtom(buf,0); + xkb->names->groups[i]= name; + } + else xkb->names->groups[i]= None; + } + } + if (XkbAllocServerMap(xkb,XkbAllServerInfoMask,0)!=Success) { + _XkbLibError(_XkbErrBadAlloc,"server map",0); + return -1; + } + if (XkbAllocClientMap(xkb,XkbAllClientInfoMask,0)!=Success) { + _XkbLibError(_XkbErrBadAlloc,"client map",0); + return -1; + } + if (XkbAllocControls(xkb,XkbAllControlsMask)!=Success) { + _XkbLibError(_XkbErrBadAlloc,"controls",0); + return -1; + } + if ((xkb->map==NULL)||(xkb->server==NULL)) + return -1; + if (xkb->min_key_code<8) xkb->min_key_code= minKC; + if (xkb->max_key_code<8) xkb->max_key_code= maxKC; + if ((minKC>=8)&&(minKC<xkb->min_key_code)) + xkb->min_key_code= minKC; + if ((maxKC>=8)&&(maxKC>xkb->max_key_code)) { + _XkbLibError(_XkbErrBadValue,"keys in symbol map",maxKC); + return -1; + } + for (i=minKC;i<=(int)maxKC;i++) { + Atom typeName[XkbNumKbdGroups]; + XkbKeyTypePtr type[XkbNumKbdGroups]; + if ((tmp=fread(&wireMap,SIZEOF(xkmKeySymMapDesc),1,file))<1) { + _XkbLibError(_XkbErrBadLength,"ReadXkmSymbols",0); + return -1; + } + nRead+= tmp*SIZEOF(xkmKeySymMapDesc); + memset((char *)typeName, 0, XkbNumKbdGroups*sizeof(Atom)); + memset((char *)type, 0, XkbNumKbdGroups*sizeof(XkbKeyTypePtr)); + if (wireMap.flags&XkmKeyHasTypes) { + register int g; + for (g=0;g<XkbNumKbdGroups;g++) { + if ((wireMap.flags&(1<<g))&& + ((tmp=XkmGetCountedString(file,buf,100))>0)) { + typeName[g]= XkbInternAtom(buf,1); + nRead+= tmp; + } + type[g]=FindTypeForKey(xkb,typeName[g],wireMap.width,NULL); + if (type[g]==NULL) { + _XkbLibError(_XkbErrMissingTypes,"ReadXkmSymbols",0); + return -1; + } + if (typeName[g]==type[g]->name) + xkb->server->explicit[i]|= (1<<g); + } + } + if (wireMap.flags&XkmRepeatingKey) { + xkb->ctrls->per_key_repeat[i/8]|= (1<<(i%8)); + xkb->server->explicit[i]|= XkbExplicitAutoRepeatMask; + } + else if (wireMap.flags&XkmNonRepeatingKey) { + xkb->ctrls->per_key_repeat[i/8]&= ~(1<<(i%8)); + xkb->server->explicit[i]|= XkbExplicitAutoRepeatMask; + } + xkb->map->modmap[i]= wireMap.modifier_map; + if (XkbNumGroups(wireMap.num_groups)>0) { + KeySym *sym; + int nSyms; + + if (XkbNumGroups(wireMap.num_groups)>xkb->ctrls->num_groups) + xkb->ctrls->num_groups= wireMap.num_groups; + nSyms= XkbNumGroups(wireMap.num_groups)*wireMap.width; + sym= XkbResizeKeySyms(xkb,i,nSyms); + if (!sym) + return -1; + for (s=0;s<nSyms;s++) { + *sym++= XkmGetCARD32(file,&nRead); + } + if (wireMap.flags&XkmKeyHasActions) { + XkbAction * act; + act= XkbResizeKeyActions(xkb,i,nSyms); + for (s=0;s<nSyms;s++,act++) { + tmp=fread(act,SIZEOF(xkmActionDesc),1,file); + nRead+= tmp*SIZEOF(xkmActionDesc); + } + xkb->server->explicit[i]|= XkbExplicitInterpretMask; + } + } + for (g=0;g<XkbNumGroups(wireMap.num_groups);g++) { + if (((xkb->server->explicit[i]&(1<<g))==0)||(type[g]==NULL)) { + KeySym *tmpSyms; + tmpSyms= XkbKeySymsPtr(xkb,i)+(wireMap.width*g); + type[g]= FindTypeForKey(xkb,None,wireMap.width,tmpSyms); + } + xkb->map->key_sym_map[i].kt_index[g]= type[g]-(&xkb->map->types[0]); + } + xkb->map->key_sym_map[i].group_info= wireMap.num_groups; + xkb->map->key_sym_map[i].width= wireMap.width; + if (wireMap.flags&XkmKeyHasBehavior) { + xkmBehaviorDesc b; + tmp= fread(&b,SIZEOF(xkmBehaviorDesc),1,file); + nRead+= tmp*SIZEOF(xkmBehaviorDesc); + xkb->server->behaviors[i].type= b.type; + xkb->server->behaviors[i].data= b.data; + xkb->server->explicit[i]|= XkbExplicitBehaviorMask; + } + } + if (totalVModMaps>0) { + xkmVModMapDesc v; + for (i=0;i<totalVModMaps;i++) { + tmp= fread(&v,SIZEOF(xkmVModMapDesc),1,file); + nRead+= tmp*SIZEOF(xkmVModMapDesc); + if (tmp>0) + xkb->server->vmodmap[v.key]= v.vmods; + } + } + return nRead; +} + +static int +ReadXkmGeomDoodad( + FILE * file, + XkbGeometryPtr geom, + XkbSectionPtr section) +{ +XkbDoodadPtr doodad; +xkmDoodadDesc doodadWire; +char buf[100]; +unsigned tmp; +int nRead=0; + + nRead+= XkmGetCountedString(file,buf,100); + tmp= fread(&doodadWire,SIZEOF(xkmDoodadDesc),1,file); + nRead+= SIZEOF(xkmDoodadDesc)*tmp; + doodad= XkbAddGeomDoodad(geom,section,XkbInternAtom(buf,FALSE)); + if (!doodad) + return nRead; + doodad->any.type= doodadWire.any.type; + doodad->any.priority= doodadWire.any.priority; + doodad->any.top= doodadWire.any.top; + doodad->any.left= doodadWire.any.left; + switch (doodadWire.any.type) { + case XkbOutlineDoodad: + case XkbSolidDoodad: + doodad->shape.angle= doodadWire.shape.angle; + doodad->shape.color_ndx= doodadWire.shape.color_ndx; + doodad->shape.shape_ndx= doodadWire.shape.shape_ndx; + break; + case XkbTextDoodad: + doodad->text.angle= doodadWire.text.angle; + doodad->text.width= doodadWire.text.width; + doodad->text.height= doodadWire.text.height; + doodad->text.color_ndx= doodadWire.text.color_ndx; + nRead+= XkmGetCountedString(file,buf,100); + doodad->text.text= Xstrdup(buf); + nRead+= XkmGetCountedString(file,buf,100); + doodad->text.font= Xstrdup(buf); + break; + case XkbIndicatorDoodad: + doodad->indicator.shape_ndx= doodadWire.indicator.shape_ndx; + doodad->indicator.on_color_ndx= doodadWire.indicator.on_color_ndx; + doodad->indicator.off_color_ndx= doodadWire.indicator.off_color_ndx; + break; + case XkbLogoDoodad: + doodad->logo.angle= doodadWire.logo.angle; + doodad->logo.color_ndx= doodadWire.logo.color_ndx; + doodad->logo.shape_ndx= doodadWire.logo.shape_ndx; + nRead+= XkmGetCountedString(file,buf,100); + doodad->logo.logo_name= Xstrdup(buf); + break; + default: + /* report error? */ + return nRead; + } + return nRead; +} + +static int +ReadXkmGeomOverlay( FILE * file, + XkbGeometryPtr geom, + XkbSectionPtr section) +{ +char buf[100]; +unsigned tmp; +int nRead=0; +XkbOverlayPtr ol; +XkbOverlayRowPtr row; +xkmOverlayDesc olWire; +xkmOverlayRowDesc rowWire; +register int r; + + nRead+= XkmGetCountedString(file,buf,100); + tmp= fread(&olWire,SIZEOF(xkmOverlayDesc),1,file); + nRead+= tmp*SIZEOF(xkmOverlayDesc); + ol= XkbAddGeomOverlay(section,XkbInternAtom(buf,FALSE), + olWire.num_rows); + if (!ol) + return nRead; + for (r=0;r<olWire.num_rows;r++) { + int k; + xkmOverlayKeyDesc keyWire; + tmp= fread(&rowWire,SIZEOF(xkmOverlayRowDesc),1,file); + nRead+= tmp*SIZEOF(xkmOverlayRowDesc); + row= XkbAddGeomOverlayRow(ol,rowWire.row_under,rowWire.num_keys); + if (!row) { + _XkbLibError(_XkbErrBadAlloc,"ReadXkmGeomOverlay",0); + return nRead; + } + for (k=0;k<rowWire.num_keys;k++) { + tmp= fread(&keyWire,SIZEOF(xkmOverlayKeyDesc),1,file); + nRead+= tmp*SIZEOF(xkmOverlayKeyDesc); + memcpy(row->keys[k].over.name,keyWire.over,XkbKeyNameLength); + memcpy(row->keys[k].under.name,keyWire.under,XkbKeyNameLength); + } + row->num_keys= rowWire.num_keys; + } + return nRead; +} + +static int +ReadXkmGeomSection( FILE * file, + XkbGeometryPtr geom) +{ +register int i; +XkbSectionPtr section; +xkmSectionDesc sectionWire; +unsigned tmp; +int nRead= 0; +char buf[100]; +Atom nameAtom; + + nRead+= XkmGetCountedString(file,buf,100); + nameAtom= XkbInternAtom(buf,FALSE); + tmp= fread(§ionWire,SIZEOF(xkmSectionDesc),1,file); + nRead+= SIZEOF(xkmSectionDesc)*tmp; + section= XkbAddGeomSection(geom,nameAtom,sectionWire.num_rows, + sectionWire.num_doodads, + sectionWire.num_overlays); + if (!section) { + _XkbLibError(_XkbErrBadAlloc,"ReadXkmGeomSection",0); + return nRead; + } + section->top= sectionWire.top; + section->left= sectionWire.left; + section->width= sectionWire.width; + section->height= sectionWire.height; + section->angle= sectionWire.angle; + section->priority= sectionWire.priority; + if (sectionWire.num_rows>0) { + register int k; + XkbRowPtr row; + xkmRowDesc rowWire; + XkbKeyPtr key; + xkmKeyDesc keyWire; + + for (i=0;i<sectionWire.num_rows;i++) { + tmp= fread(&rowWire,SIZEOF(xkmRowDesc),1,file); + nRead+= SIZEOF(xkmRowDesc)*tmp; + row= XkbAddGeomRow(section,rowWire.num_keys); + if (!row) { + _XkbLibError(_XkbErrBadAlloc,"ReadXkmKeycodes",0); + return nRead; + } + row->top= rowWire.top; + row->left= rowWire.left; + row->vertical= rowWire.vertical; + for (k=0;k<rowWire.num_keys;k++) { + tmp= fread(&keyWire,SIZEOF(xkmKeyDesc),1,file); + nRead+= SIZEOF(xkmKeyDesc)*tmp; + key= XkbAddGeomKey(row); + if (!key) { + _XkbLibError(_XkbErrBadAlloc,"ReadXkmGeomSection",0); + return nRead; + } + memcpy(key->name.name,keyWire.name,XkbKeyNameLength); + key->gap= keyWire.gap; + key->shape_ndx= keyWire.shape_ndx; + key->color_ndx= keyWire.color_ndx; + } + } + } + if (sectionWire.num_doodads>0) { + for (i=0;i<sectionWire.num_doodads;i++) { + tmp= ReadXkmGeomDoodad(file,geom,section); + nRead+= tmp; + if (tmp<1) + return nRead; + } + } + if (sectionWire.num_overlays>0) { + for (i=0;i<sectionWire.num_overlays;i++) { + tmp= ReadXkmGeomOverlay(file,geom,section); + nRead+= tmp; + if (tmp<1) + return nRead; + } + } + return nRead; +} + +static int +ReadXkmGeometry(FILE *file,XkbDescPtr xkb) +{ +register int i; +char buf[100]; +unsigned tmp; +int nRead= 0; +xkmGeometryDesc wireGeom; +XkbGeometryPtr geom; +XkbGeometrySizesRec sizes; + + nRead+= XkmGetCountedString(file,buf,100); + tmp= fread(&wireGeom,SIZEOF(xkmGeometryDesc),1,file); + nRead+= tmp*SIZEOF(xkmGeometryDesc); + sizes.which= XkbGeomAllMask; + sizes.num_properties= wireGeom.num_properties; + sizes.num_colors= wireGeom.num_colors; + sizes.num_shapes= wireGeom.num_shapes; + sizes.num_sections= wireGeom.num_sections; + sizes.num_doodads= wireGeom.num_doodads; + sizes.num_key_aliases= wireGeom.num_key_aliases; + if (XkbAllocGeometry(xkb,&sizes)!=Success) { + _XkbLibError(_XkbErrBadAlloc,"ReadXkmGeometry",0); + return nRead; + } + geom= xkb->geom; + geom->name= XkbInternAtom(buf,FALSE); + geom->width_mm= wireGeom.width_mm; + geom->height_mm= wireGeom.height_mm; + nRead+= XkmGetCountedString(file,buf,100); + geom->label_font= Xstrdup(buf); + if (wireGeom.num_properties>0) { + char val[1024]; + for (i=0;i<wireGeom.num_properties;i++) { + nRead+= XkmGetCountedString(file,buf,100); + nRead+= XkmGetCountedString(file,val,1024); + if (XkbAddGeomProperty(geom,buf,val)==NULL) { + _XkbLibError(_XkbErrBadAlloc,"ReadXkmGeometry",0); + return nRead; + } + } + } + if (wireGeom.num_colors>0) { + for (i=0;i<wireGeom.num_colors;i++) { + nRead+= XkmGetCountedString(file,buf,100); + if (XkbAddGeomColor(geom,buf,i)==NULL) { + _XkbLibError(_XkbErrBadAlloc,"ReadXkmGeometry",0); + return nRead; + } + } + } + geom->base_color= &geom->colors[wireGeom.base_color_ndx]; + geom->label_color= &geom->colors[wireGeom.label_color_ndx]; + if (wireGeom.num_shapes>0) { + XkbShapePtr shape; + xkmShapeDesc shapeWire; + Atom nameAtom; + for (i=0;i<wireGeom.num_shapes;i++) { + register int n; + XkbOutlinePtr ol; + xkmOutlineDesc olWire; + nRead+= XkmGetCountedString(file,buf,100); + nameAtom= XkbInternAtom(buf,FALSE); + tmp= fread(&shapeWire,SIZEOF(xkmShapeDesc),1,file); + nRead+= tmp*SIZEOF(xkmShapeDesc); + shape= XkbAddGeomShape(geom,nameAtom,shapeWire.num_outlines); + if (!shape) { + _XkbLibError(_XkbErrBadAlloc,"ReadXkmGeometry",0); + return nRead; + } + for (n=0;n<shapeWire.num_outlines;n++) { + register int p; + xkmPointDesc ptWire; + tmp= fread(&olWire,SIZEOF(xkmOutlineDesc),1,file); + nRead+= tmp*SIZEOF(xkmOutlineDesc); + ol= XkbAddGeomOutline(shape,olWire.num_points); + if (!ol) { + _XkbLibError(_XkbErrBadAlloc,"ReadXkmGeometry",0); + return nRead; + } + ol->num_points= olWire.num_points; + ol->corner_radius= olWire.corner_radius; + for (p=0;p<olWire.num_points;p++) { + tmp= fread(&ptWire,SIZEOF(xkmPointDesc),1,file); + nRead+= tmp*SIZEOF(xkmPointDesc); + ol->points[p].x= ptWire.x; + ol->points[p].y= ptWire.y; + if (ptWire.x<shape->bounds.x1) shape->bounds.x1= ptWire.x; + if (ptWire.x>shape->bounds.x2) shape->bounds.x2= ptWire.x; + if (ptWire.y<shape->bounds.y1) shape->bounds.y1= ptWire.y; + if (ptWire.y>shape->bounds.y2) shape->bounds.y2= ptWire.y; + } + } + if (shapeWire.primary_ndx!=XkbNoShape) + shape->primary= &shape->outlines[shapeWire.primary_ndx]; + if (shapeWire.approx_ndx!=XkbNoShape) + shape->approx= &shape->outlines[shapeWire.approx_ndx]; + } + } + if (wireGeom.num_sections>0) { + for (i=0;i<wireGeom.num_sections;i++) { + tmp= ReadXkmGeomSection(file,geom); + nRead+= tmp; + if (tmp==0) + return nRead; + } + } + if (wireGeom.num_doodads>0) { + for (i=0;i<wireGeom.num_doodads;i++) { + tmp= ReadXkmGeomDoodad(file,geom,NULL); + nRead+= tmp; + if (tmp==0) + return nRead; + } + } + if ((wireGeom.num_key_aliases>0)&&(geom->key_aliases)) { + int sz= XkbKeyNameLength*2; + int num= wireGeom.num_key_aliases; + if (fread(geom->key_aliases,sz,num,file)!=num) { + _XkbLibError(_XkbErrBadLength,"ReadXkmGeometry",0); + return -1; + } + nRead+= (num*sz); + geom->num_key_aliases= num; + } + return nRead; +} + +Bool +XkmProbe(FILE *file) +{ +unsigned hdr,tmp; +int nRead=0; + + hdr= (('x'<<24)|('k'<<16)|('m'<<8)|XkmFileVersion); + tmp= XkmGetCARD32(file,&nRead); + if (tmp!=hdr) { + if ((tmp&(~0xff))==(hdr&(~0xff))) { + _XkbLibError(_XkbErrBadFileVersion,"XkmProbe",tmp&0xff); + } + return 0; + } + return 1; +} + +static Bool +XkmReadTOC(FILE *file,xkmFileInfo* file_info,int max_toc,xkmSectionInfo *toc) +{ +unsigned hdr,tmp; +int nRead=0; +unsigned i,size_toc; + + hdr= (('x'<<24)|('k'<<16)|('m'<<8)|XkmFileVersion); + tmp= XkmGetCARD32(file,&nRead); + if (tmp!=hdr) { + if ((tmp&(~0xff))==(hdr&(~0xff))) { + _XkbLibError(_XkbErrBadFileVersion,"XkmReadTOC",tmp&0xff); + } + else { + _XkbLibError(_XkbErrBadFileType,"XkmReadTOC",tmp); + } + return 0; + } + fread(file_info,SIZEOF(xkmFileInfo),1,file); + size_toc= file_info->num_toc; + if (size_toc>max_toc) { + DebugF("Warning! Too many TOC entries; last %d ignored\n", + size_toc-max_toc); + size_toc= max_toc; + } + for (i=0;i<size_toc;i++) { + fread(&toc[i],SIZEOF(xkmSectionInfo),1,file); + } + return 1; +} + +/***====================================================================***/ + +#define MAX_TOC 16 +unsigned +XkmReadFile(FILE *file,unsigned need,unsigned want,XkbDescPtr *xkb) +{ +register unsigned i; +xkmSectionInfo toc[MAX_TOC],tmpTOC; +xkmFileInfo fileInfo; +unsigned tmp,nRead=0; +unsigned which= need|want; + + if (!XkmReadTOC(file,&fileInfo,MAX_TOC,toc)) + return which; + if ((fileInfo.present&need)!=need) { + _XkbLibError(_XkbErrIllegalContents,"XkmReadFile", + need&(~fileInfo.present)); + return which; + } + if (*xkb==NULL) + *xkb= XkbAllocKeyboard(); + for (i=0;i<fileInfo.num_toc;i++) { + fseek(file,toc[i].offset,SEEK_SET); + tmp= fread(&tmpTOC,SIZEOF(xkmSectionInfo),1,file); + nRead= tmp*SIZEOF(xkmSectionInfo); + if ((tmpTOC.type!=toc[i].type)||(tmpTOC.format!=toc[i].format)|| + (tmpTOC.size!=toc[i].size)||(tmpTOC.offset!=toc[i].offset)) { + return which; + } + if ((which&(1<<tmpTOC.type))==0) { + continue; + } + switch (tmpTOC.type) { + case XkmVirtualModsIndex: + tmp= ReadXkmVirtualMods(file,*xkb,NULL); + break; + case XkmTypesIndex: + tmp= ReadXkmKeyTypes(file,*xkb,NULL); + break; + case XkmCompatMapIndex: + tmp= ReadXkmCompatMap(file,*xkb,NULL); + break; + case XkmKeyNamesIndex: + tmp= ReadXkmKeycodes(file,*xkb,NULL); + break; + case XkmIndicatorsIndex: + tmp= ReadXkmIndicators(file,*xkb,NULL); + break; + case XkmSymbolsIndex: + tmp= ReadXkmSymbols(file,*xkb); + break; + case XkmGeometryIndex: + tmp= ReadXkmGeometry(file,*xkb); + break; + default: + _XkbLibError(_XkbErrBadImplementation, + XkbConfigText(tmpTOC.type,XkbMessage),0); + tmp= 0; + break; + } + if (tmp>0) { + nRead+= tmp; + which&= ~(1<<toc[i].type); + (*xkb)->defined|= (1<<toc[i].type); + } + if (nRead!=tmpTOC.size) { + _XkbLibError(_XkbErrBadLength,XkbConfigText(tmpTOC.type,XkbMessage), + nRead-tmpTOC.size); + } + } + return which; +} diff --git a/xorg-server/xkeyboard-config/configure.in b/xorg-server/xkeyboard-config/configure.in index 6da549740..80af27564 100644 --- a/xorg-server/xkeyboard-config/configure.in +++ b/xorg-server/xkeyboard-config/configure.in @@ -61,7 +61,6 @@ semantics/Makefile rules/Makefile rules/bin/Makefile rules/compat/Makefile -rules/extras/Makefile symbols/Makefile symbols/digital_vndr/Makefile symbols/fujitsu_vndr/Makefile @@ -73,7 +72,6 @@ symbols/sgi_vndr/Makefile symbols/sony_vndr/Makefile symbols/sun_vndr/Makefile symbols/xfree68_vndr/Makefile -symbols/extras/Makefile types/Makefile xkeyboard-config.pc xkeyboard-config.spec diff --git a/xorg-server/xkeyboard-config/rules/Makefile.am b/xorg-server/xkeyboard-config/rules/Makefile.am index 6ca04e7fa..f2d73ce80 100644 --- a/xorg-server/xkeyboard-config/rules/Makefile.am +++ b/xorg-server/xkeyboard-config/rules/Makefile.am @@ -1,4 +1,4 @@ -SUBDIRS = bin compat extras +SUBDIRS = bin compat if CREATE_RULES_SYMLINK # extra_rules_file = $(xkb_rules_symlink) @@ -30,16 +30,16 @@ HDR base.l_k.part \ HDR base.o_k.part \ HDR base.ml_g.part \ HDR base.m_g.part \ -HDR compat/base.mlv_s.part extras/base.mlv_s.part base.mlv_s.part \ -HDR compat/base.ml_s.part extras/base.ml_s.part base.ml_s.part \ -HDR compat/base.ml1_s.part extras/base.ml1_s.part base.ml1_s.part \ -HDR compat/base.ml1v1_s.part extras/base.ml1v1_s.part \ -HDR compat/base.ml2_s.part extras/base.ml2_s.part base.ml2_s.part \ -HDR compat/base.ml3_s.part extras/base.ml3_s.part base.ml3_s.part \ -HDR compat/base.ml4_s.part extras/base.ml4_s.part base.ml4_s.part \ -HDR compat/base.ml2v2_s.part extras/base.ml2v2_s.part \ -HDR compat/base.ml3v3_s.part extras/base.ml3v3_s.part \ -HDR compat/base.ml4v4_s.part extras/base.ml4v4_s.part \ +HDR compat/base.mlv_s.part base.mlv_s.part \ +HDR compat/base.ml_s.part base.ml_s.part \ +HDR compat/base.ml1_s.part base.ml1_s.part \ +HDR compat/base.ml1v1_s.part \ +HDR compat/base.ml2_s.part base.ml2_s.part \ +HDR compat/base.ml3_s.part base.ml3_s.part \ +HDR compat/base.ml4_s.part base.ml4_s.part \ +HDR compat/base.ml2v2_s.part \ +HDR compat/base.ml3v3_s.part \ +HDR compat/base.ml4v4_s.part \ HDR base.m_s.part \ HDR compat/base.lv_c.part \ HDR compat/base.l1v1_c.part \ @@ -66,16 +66,16 @@ HDR base.l_k.part \ HDR base.o_k.part \ HDR base.ml_g.part \ HDR base.m_g.part \ -HDR compat/base.mlv_s.part extras/base.mlv_s.part base.mlv_s.part \ -HDR compat/base.ml_s.part extras/base.ml_s.part base.ml_s.part \ -HDR compat/base.ml1_s.part extras/base.ml1_s.part base.ml1_s.part \ -HDR compat/base.ml1v1_s.part extras/base.ml1v1_s.part \ -HDR compat/base.ml2_s.part extras/base.ml2_s.part base.ml2_s.part \ -HDR compat/base.ml3_s.part extras/base.ml3_s.part base.ml3_s.part \ -HDR compat/base.ml4_s.part extras/base.ml4_s.part base.ml4_s.part \ -HDR compat/base.ml2v2_s.part extras/base.ml2v2_s.part \ -HDR compat/base.ml3v3_s.part extras/base.ml3v3_s.part \ -HDR compat/base.ml4v4_s.part extras/base.ml4v4_s.part \ +HDR compat/base.mlv_s.part base.mlv_s.part \ +HDR compat/base.ml_s.part base.ml_s.part \ +HDR compat/base.ml1_s.part base.ml1_s.part \ +HDR compat/base.ml1v1_s.part \ +HDR compat/base.ml2_s.part base.ml2_s.part \ +HDR compat/base.ml3_s.part base.ml3_s.part \ +HDR compat/base.ml4_s.part base.ml4_s.part \ +HDR compat/base.ml2v2_s.part \ +HDR compat/base.ml3v3_s.part \ +HDR compat/base.ml4v4_s.part \ HDR evdev.m_s.part \ HDR compat/base.lv_c.part \ HDR compat/base.l1v1_c.part \ @@ -103,16 +103,16 @@ HDR base.l_k.part \ HDR \ HDR base.ml_g.part \ HDR base.m_g.part \ -HDR extras/base.mlv_s.part base.mlv_s.part \ -HDR extras/base.ml_s.part base.ml_s.part \ -HDR extras/base.ml1_s.part base.ml1_s.part \ -HDR extras/base.ml1v1_s.part \ -HDR extras/base.ml2_s.part base.ml2_s.part \ -HDR extras/base.ml3_s.part base.ml3_s.part \ -HDR extras/base.ml4_s.part base.ml4_s.part \ -HDR extras/base.ml2v2_s.part \ -HDR extras/base.ml3v3_s.part \ -HDR extras/base.ml4v4_s.part \ +HDR base.mlv_s.part \ +HDR base.ml_s.part \ +HDR base.ml1_s.part \ +HDR \ +HDR base.ml2_s.part \ +HDR base.ml3_s.part \ +HDR base.ml4_s.part \ +HDR \ +HDR \ +HDR \ HDR base.m_s.part \ HDR \ HDR \ @@ -138,16 +138,16 @@ HDR base.l_k.part \ HDR \ HDR base.ml_g.part \ HDR base.m_g.part \ -HDR extras/base.mlv_s.part base.mlv_s.part \ -HDR extras/base.ml_s.part base.ml_s.part \ -HDR extras/base.ml1_s.part base.ml1_s.part \ -HDR extras/base.ml1v1_s.part \ -HDR extras/base.ml2_s.part base.ml2_s.part \ -HDR extras/base.ml3_s.part base.ml3_s.part \ -HDR extras/base.ml4_s.part base.ml4_s.part \ -HDR extras/base.ml2v2_s.part \ -HDR extras/base.ml3v3_s.part \ -HDR extras/base.ml4v4_s.part \ +HDR base.mlv_s.part \ +HDR base.ml_s.part \ +HDR base.ml1_s.part \ +HDR \ +HDR base.ml2_s.part \ +HDR base.ml3_s.part \ +HDR base.ml4_s.part \ +HDR \ +HDR \ +HDR \ HDR evdev.m_s.part \ HDR \ HDR \ diff --git a/xorg-server/xkeyboard-config/rules/base.extras.xml.in b/xorg-server/xkeyboard-config/rules/base.extras.xml.in index 7089d049e..b068589fd 100644 --- a/xorg-server/xkeyboard-config/rules/base.extras.xml.in +++ b/xorg-server/xkeyboard-config/rules/base.extras.xml.in @@ -67,6 +67,22 @@ </layout> <layout> <configItem> + <name>ro</name> + <_shortDescription>Rou</_shortDescription> + <_description>Romania</_description> + <languageList><iso639Id>rum</iso639Id></languageList> + </configItem> + <variantList> + <variant> + <configItem> + <name>ergonomic</name> + <_description>Ergonomic Touchtype</_description> + </configItem> + </variant> + </variantList> + </layout> + <layout> + <configItem> <name>rs</name> <_shortDescription>SRB</_shortDescription> <_description>Serbia</_description> diff --git a/xorg-server/xkeyboard-config/rules/extras/Makefile.am b/xorg-server/xkeyboard-config/rules/extras/Makefile.am deleted file mode 100644 index fafed6033..000000000 --- a/xorg-server/xkeyboard-config/rules/extras/Makefile.am +++ /dev/null @@ -1,51 +0,0 @@ -transform_files=layoutsMapping.lst variantsMapping.lst - -scripts_dir=$(srcdir)/../bin - -scripts= \ -base.ml2_s.part \ -base.ml3_s.part \ -base.ml4_s.part \ -base.ml2v2_s.part \ -base.ml3v3_s.part \ -base.ml4v4_s.part \ -base.ml_s.part \ -base.ml1_s.part \ -base.mlv_s.part \ -base.ml1v1_s.part - -noinst_SCRIPTS=$(scripts) - -base.ml2_s.part: $(scripts_dir)/mln_s.sh $(transform_files) - sh $< 2 $(srcdir) - -base.ml3_s.part: $(scripts_dir)/mln_s.sh $(transform_files) - sh $< 3 $(srcdir) - -base.ml4_s.part: $(scripts_dir)/mln_s.sh $(transform_files) - sh $< 4 $(srcdir) - -base.ml2v2_s.part: $(scripts_dir)/mlnvn_s.sh $(transform_files) - sh $< 2 $(srcdir) - -base.ml3v3_s.part: $(scripts_dir)/mlnvn_s.sh $(transform_files) - sh $< 3 $(srcdir) - -base.ml4v4_s.part: $(scripts_dir)/mlnvn_s.sh $(transform_files) - sh $< 4 $(srcdir) - -base.ml_s.part: $(scripts_dir)/ml_s.sh $(transform_files) - sh $< $(srcdir) - -base.ml1_s.part: $(scripts_dir)/ml1_s.sh $(transform_files) - sh $< $(srcdir) - -base.mlv_s.part: $(scripts_dir)/mlv_s.sh $(transform_files) - sh $< $(srcdir) - -base.ml1v1_s.part: $(scripts_dir)/ml1v1_s.sh $(transform_files) - sh $< $(srcdir) - -EXTRA_DIST=$(transform_files) - -CLEANFILES=$(scripts) diff --git a/xorg-server/xkeyboard-config/rules/extras/layoutsMapping.lst b/xorg-server/xkeyboard-config/rules/extras/layoutsMapping.lst deleted file mode 100644 index d75b4f44d..000000000 --- a/xorg-server/xkeyboard-config/rules/extras/layoutsMapping.lst +++ /dev/null @@ -1 +0,0 @@ -apl extras/apl diff --git a/xorg-server/xkeyboard-config/rules/extras/variantsMapping.lst b/xorg-server/xkeyboard-config/rules/extras/variantsMapping.lst deleted file mode 100644 index fd0add719..000000000 --- a/xorg-server/xkeyboard-config/rules/extras/variantsMapping.lst +++ /dev/null @@ -1,6 +0,0 @@ -rs combiningkeys extras/rs combiningkeys
-ru chu extras/ru chu
-ir ave extras/ir ave
-us alt-intl-unicode extras/us alt-intl-unicode
-us crd extras/us crd
-us intl-unicode extras/us intl-unicode
diff --git a/xorg-server/xkeyboard-config/symbols/Makefile.am b/xorg-server/xkeyboard-config/symbols/Makefile.am index 79e9ad162..270b7a4d6 100644 --- a/xorg-server/xkeyboard-config/symbols/Makefile.am +++ b/xorg-server/xkeyboard-config/symbols/Makefile.am @@ -1,40 +1,41 @@ -SUBDIRS = digital_vndr fujitsu_vndr hp_vndr macintosh_vndr nec_vndr nokia_vndr sgi_vndr sony_vndr sun_vndr xfree68_vndr extras
-
-symbolsdir = $(xkb_base)/symbols
-dist_symbols_DATA = \
-ad af al \
-am ara at az \
-ba bd be \
-bg br brai \
-bt bw by \
-ca cd \
-ch cn cz \
-de dk \
-ee es et epo \
-fi fo fr \
-gb ge gh gn \
-gr hr hu \
-ie il in iq \
-ir is it jp \
-ke kg kh \
-kr kz \
-la latam latin \
-lk lt lv \
-ma mao me \
-mk ml mm \
-mn mt mv \
-ng nl no np \
-pc ph pk pl pt \
-ro rs ru \
-se si sk sn \
-sy th \
-terminate \
-tj tm tr tz \
-ua us uz vn \
-za \
-altwin capslock compose ctrl empty eurosign rupeesign group inet \
-keypad kpdl level3 level5 nbsp olpc shift srvr_ctrl typo
-
-dir_data = $(dist_symbols_DATA)
-
-include $(top_srcdir)/xkbrules.am
+SUBDIRS = digital_vndr fujitsu_vndr hp_vndr macintosh_vndr nec_vndr nokia_vndr sgi_vndr sony_vndr sun_vndr xfree68_vndr + +symbolsdir = $(xkb_base)/symbols +dist_symbols_DATA = \ +ad af al \ +am apl ara \ +at az \ +ba bd be \ +bg br brai \ +bt bw by \ +ca cd \ +ch cn cz \ +de dk \ +ee es et epo \ +fi fo fr \ +gb ge gh gn \ +gr hr hu \ +ie il in iq \ +ir is it jp \ +ke kg kh \ +kr kz \ +la latam latin \ +lk lt lv \ +ma mao me \ +mk ml mm \ +mn mt mv \ +ng nl no np \ +pc ph pk pl pt \ +ro rs ru \ +se si sk sn \ +sy th \ +terminate \ +tj tm tr tz \ +ua us uz vn \ +za \ +altwin capslock compose ctrl empty eurosign rupeesign group inet \ +keypad kpdl level3 level5 nbsp olpc shift srvr_ctrl typo + +dir_data = $(dist_symbols_DATA) + +include $(top_srcdir)/xkbrules.am diff --git a/xorg-server/xkeyboard-config/symbols/extras/apl b/xorg-server/xkeyboard-config/symbols/apl index 57cdb0824..4421cc398 100644 --- a/xorg-server/xkeyboard-config/symbols/extras/apl +++ b/xorg-server/xkeyboard-config/symbols/apl @@ -1,294 +1,296 @@ -// APL Keyboard Layouts
-
-// This file supports:
-// - The Sharp APL for Unix (SAX) layout
-// - The IBM APL2 layout
-// - The Manugistics APL*PLUS II (Version 5.1, 1993) keyboard layout
-
-// Unicode APL table: http://aplwiki.com/UnicodeAplTable
-// ...and another: http://publibfp.boulder.ibm.com/epubs/pdf/h2110611.pdf (appendix A)
-// Generic Unicode stuff: http://www.fileformat.info/info/unicode/category/index.htm
-
-// Tim Nelson (this file's creator) says:
-
-// This file doesn't deal with all the combining stuff -- I'm not an APL programmer,
-// and am not quite sure what's needed here. However, it may be possible to get this
-// working with dead keys and the like. Patches gratefully accepted.
-
-// Some of the shift-key assignments may differ from the APL tradition. If
-// that's not considered acceptable, it should be possible to remap the
-// shift keys. I have striven, however, to ensure that the use of shift keys
-// in these maps is at least self-consistent.
-
-// I'm assuming that this will be used with another keyboard layout (ie. for
-// your language), with a special shift key to use these maps.
-
-partial alphanumeric_keys modifier_keys
-xkb_symbols "common" {
- name[Group1]= "APL";
-
- key <AE01> { [ diaeresis ] };
- key <AE02> { [ U00AF ] }; // ¯ -- Macron
- key <AE03> { [ less ] };
- key <AE04> { [ U2264 ] }; // ≤ -- Less-than Or Equal To
- key <AE05> { [ equal ] };
- key <AE06> { [ U2265 ] }; // ≥ -- Greater-than Or Equal To
- key <AE07> { [ greater ] };
- key <AE08> { [ U2260 ] }; // ≠ -- Not Equal To
- key <AE09> { [ U2228 ] }; // ∨ -- Logical Or
- key <AE10> { [ U2227 ] }; // ∧ -- Logical And
-
- // Q
- key <AD01> { [ question ] };
- // W
- key <AD02> { [ U2375 ] }; // ⍵ -- APL Functional Symbol Omega
- // E
- key <AD03> { [ U220A ] }; // ∊ -- Small Element Of
- // R
- key <AD04> { [ U2374 ] }; // ⍴ -- APL Functional Symbol Rho
- // T
- key <AD05> { [ asciitilde ] };
- // Y
- key <AD06> { [ U2191 ] }; // ↑ -- Upwards Arrow
- // U
- key <AD07> { [ U2193 ] }; // ↓ -- Downwards Arrow
- // I
- key <AD08> { [ U2373 ] }; // ⍳ -- APL Functional Symbol Iota
- // O
- key <AD09> { [ U25CB ] }; // ○ -- White Circle
- // P
- key <AD10> { [ U22C6 ] }; // ⋆ -- Should this be a plain asterisk, or the star operator???
- // [
- key <AD11> { [ U2190 ] }; // ← -- Leftwards Arrow
-
- // A
- key <AC01> { [ U237A ] }; // ⍺ -- APL Functional Symbol Alpha
- // S
- key <AC02> { [ U2308 ] }; // ⌈ -- Left Ceiling
- // D
- key <AC03> { [ U230A ] }; // ⌊ -- Left Floor
- // F
- key <AC04> { [ underscore ] };
- // G
- key <AC05> { [ U2207 ] }; // ∇ -- Nabla
- // H
- key <AC06> { [ U2206 ] }; // ∆ -- Increment
- // J
- key <AC07> { [ U2218 ] }; // ∘ -- Ring Operator
- // K
- key <AC08> { [ apostrophe ] };
- // L
- key <AC09> { [ U2395 ] }; // ⎕ -- APL Functional Symbol Quad
-
- // Z
- key <AB01> { [ U2282 ] }; // ⊂ -- Subset Of
- // X
- key <AB02> { [ U2283 ] }; // ⊃ -- Superset Of
- // C
- key <AB03> { [ U2229 ] }; // ∩ -- Intersection
- // V
- key <AB04> { [ U222A ] }; // ∪ -- Union
- // B
- key <AB05> { [ U22A5 ] }; // ⊥ -- Up Tack
- // N
- key <AB06> { [ U22A4 ] }; // ⊤ -- Down Tack
- // M
- key <AB07> { [ U007C ] }; // | -- Vertical Line
-};
-
-// Keys common to a number of keyboards that allow normal language usage alongside APL
-partial alphanumeric_keys modifier_keys
-xkb_symbols "unified" {
- name[Group1]= "APL Keyboard Symbols: Unified Layout";
-
- include "apl(common)"
-
- // `
- key <TLDE> { [ U22C4 ] }; // ⋄ -- Diamond Operator
- key <AE09> { [ NoSymbol, U2371 ] }; // ⍱ -- APL Functional Symbol Down Caret Tilde
- key <AE10> { [ NoSymbol, U2372 ] }; // ⍲ -- APL Functional Symbol Up Caret Tilde
- // -
- key <AE11> { [ U00D7 ] }; // × -- Multiplication Sign
- // =
- key <AE12> { [ U00F7, U2339 ] }; // ÷ ⌹ -- Division Sign / APL Functional Symbol Quad Divide
-
- // ]
- key <AD12> { [ U2192 ] }; // → -- Rightwards Arrow
-};
-
-// Layout: http://www.wickensonline.co.uk/apl-unicomp.html
-default
-partial alphanumeric_keys modifier_keys
-xkb_symbols "sax" {
- name[Group1]= "APL Keyboard Symbols: Sharp APL for Unix";
-
- include "apl(unified)"
-
- key <AE01> { [ NoSymbol, U00A1 ] }; // ¡ -- Inverted Exclamation Mark
- key <AE04> { [ NoSymbol, cent ] };
- key <AE08> { [ NoSymbol, U2342 ] }; // ⍂ -- APL Functional Symbol Quad Backslash
- // -
- key <AE11> { [ NoSymbol, U2261 ] }; // ≡ -- Identical To
-
- // Q
- key <AD01> { [ NoSymbol, U00BF ] }; // ¿ -- Inverted Question Mark
- // W
- key <AD02> { [ NoSymbol, U233D ] }; // ⌽ -- APL Functional Symbol Circle Stile
- // E
- key <AD03> { [ NoSymbol, U2377 ] }; // ⍷ -- APL Functional Symbol Epsilon Underbar
- // T
- key <AD05> { [ NoSymbol, U2349 ] }; // ⍉ -- APL Functional Symbol Circle Backslash
- // I
- key <AD08> { [ NoSymbol, U2378 ] }; // ⍸ -- APL Functional Symbol Iota Underbar
- // O
- key <AD09> { [ NoSymbol, U2365 ] }; // ⍥ -- APL Functional Symbol Circle Diaeresis
- // P
- key <AD10> { [ NoSymbol, U235F ] }; // ⍟ -- APL Functional Symbol Circle Star
-
- // A
- key <AC01> { [ NoSymbol, U2296 ] }; // ⊖ -- Circled Minus
- // F
- key <AC04> { [ NoSymbol, U236B ] }; // ⍫ -- APL Functional Symbol Del Tilde
- // G
- key <AC05> { [ NoSymbol, U2352 ] }; // ∇ ⍒ -- APL Functional Symbol Del Stile
- // H
- key <AC06> { [ NoSymbol, U234B ] }; // ∆ ⍋ -- APL Functional Symbol Delta Stile
- // J
- key <AC07> { [ NoSymbol, U2364 ] }; // ⍤ -- APL Functional Symbol Jot Diaeresis
- // K
- key <AC08> { [ NoSymbol, U233B ] }; // ⌻
- // L
- key <AC09> { [ NoSymbol, U235E ] }; // ⍞ -- APL Functional Symbol Quote Quad
- // ;
- key <AC10> { [ U22A2 ] }; // ⊢ -- Right Tack
- // '
- key <AC11> { [ U22A3 ] }; // ⊣ -- Left Tack
-
- // C
- key <AB03> { [ NoSymbol, U235D ] }; // ⍝ -- APL Functional Symbol Up Shoe Jot
- // B
- key <AB05> { [ NoSymbol, U234E ] }; // ⍎ -- APL Functional Symbol Down Tack Jot (Unicode got the name wrong; it should have been "Up Tack")
- // N
- key <AB06> { [ NoSymbol, U2355 ] }; // ⍕ -- APL Functional Symbol Up Tack Jot (Unicode got the name wrong; it should have been "Down Tack")
- // M
- key <AB07> { [ NoSymbol, U2336 ] }; // ⌶ -- APL Functional Symbol I-Beam
- // ,
- key <AB08> { [ U235E, U236A ] }; // ⍞ ⍪ -- APL Functional Symbol Quote Quad / APL Functional Symbol Comma Bar
- // .
- key <AB09> { [ U234E, U2359 ] }; // ⍎ ⍙ -- [See B key] / APL Functional Symbol Delta Underbar
- // /
- key <AB10> { [ U2355, U233F ] }; // ⍕ ⌿ -- [See N key] / APL Functional Symbol Slash Bar
-
- key <BKSL> { [ U235D, U2340 ] }; // ⍝ ⍀ -- APL Functional Symbol Up Shoe Jot / APL Functional Symbol Backslash Bar
-};
-
-// Layout: http://www.wickensonline.co.uk/apl-unicomp.html
-partial alphanumeric_keys modifier_keys
-xkb_symbols "apl2" {
- name[Group1]= "APL Keyboard Symbols: IBM APL2";
-
- include "apl(common)"
-
- // The first column is NoSymbol because it inherits. The second is NoSymbol because those keys don't do anything
-
- // `
- key <TLDE> { [ NoSymbol, U233B, U2342 ] }; // ⌻ ⍂ --
- key <AE01> { [ NoSymbol, NoSymbol, U2336 ] }; // ⌶ -- APL Functional Symbol I-Beam
- key <AE02> { [ NoSymbol, NoSymbol, U236B ] }; // ⍫ -- APL Functional Symbol Del Tilde
- key <AE03> { [ NoSymbol, NoSymbol, U2353 ] }; // ⍒ -- APL Functional Symbol Del Stile
- key <AE04> { [ NoSymbol, NoSymbol, U234B ] }; // ⍋ -- APL Functional Symbol Delta Stile
- key <AE05> { [ NoSymbol, NoSymbol, U233D ] }; // ⌽ -- APL Functional Symbol Circle Stile
- key <AE06> { [ NoSymbol, NoSymbol, U2349 ] }; // ⍉ -- APL Functional Symbol Circle Backslash
- key <AE07> { [ NoSymbol, NoSymbol, U2296 ] }; // ⊖ -- Circled Minus
- key <AE08> { [ NoSymbol, NoSymbol, U235F ] }; // ⍟ -- APL Functional Symbol Circle Star
- key <AE09> { [ NoSymbol, NoSymbol, U2371 ] }; // ⍱ -- APL Functional Symbol Down Caret Tilde
- key <AE10> { [ NoSymbol, NoSymbol, U2372 ] }; // ⍲ -- APL Functional Symbol Up Caret Tilde
- // -
- key <AE11> { [ plus, minus, exclam ] };
- // =
- key <AE12> { [ U00D7, U00F7, U2339 ] }; // × ÷ ⌹ -- Multiplication Sign / Division Sign / APL Functional Symbol Quad Divide
-
- // [
- key <AD11> { [ NoSymbol, U2192, U235E ] }; // (←) → ⍞ -- Rightwards Arrow / APL Functional Symbol Quote Quad
- // ]
- key <AD12> { [ U2337, U2378, U2359 ] }; // ⌷ ⍸ ⍙ -- APL Functional Symbol Squish Quad / APL Functional Symbol Iota Underbar / APL Functional Symbol Delta Underbar
-
- // ;
- key <AC10> { [ bracketleft, parenleft, U234E ] }; // ⍎ -- [See B key in SAX layout]
- // '
- key <AC11> { [ bracketright, parenright, U2355 ] }; // ⍕ -- [See N key in SAX layout]
-
- // ,
- key <AB08> { [ comma, semicolon, U235D ] }; // ⍝ -- APL Functional Symbol Up Shoe Jot
- // .
- key <AB09> { [ period, colon, U2340 ] }; // ⍀ -- APL Functional Symbol Backslash Bar
- // /
- key <AB10> { [ slash, backslash, U233F ] }; // ⌿ -- APL Functional Symbol Slash Bar
-
- key <BKSL> { [ U2261, U2377, U2364 ] }; // ≡ ⍷ ⍤ -- Identical To / APL Functional Symbol Epsilon Underbar / APL Functional Symbol Jot Diaeresis
-};
-
-partial alphanumeric_keys modifier_keys
-xkb_symbols "aplplusII" {
- name[Group1]= "APL Keyboard Symbols: Manugistics APL*PLUS II";
-
- include "apl(apl2)"
-
- // `
- key <TLDE> { [ dollar, U22C4, U236A ] }; // ⋄ ⍪ -- Diamond Operator / APL Functional Symbol Comma Bar
- key <AE01> { [ NoSymbol, NoSymbol, U2261 ] }; // ≡ -- Identical To
-
- // [
- key <AD11> { [ U2190, NoSymbol, U235E ] }; // ← ⍞ -- Leftwards Arrow / APL Functional Symbol Quote Quad
- // ]
- key <AD12> { [ U2192, NoSymbol, U236C ] }; // → ⍬ -- Rightwards Arrow / APL Functional Symbol Zilde
-
- // ;
- key <AC10> { [ bracketleft, parenleft, U234E ] }; // ⍎ -- [See B key in SAX layout]
- // '
- key <AC11> { [ bracketright, parenright, U2355 ] }; // ⍕ -- [See N key in SAX layout]
-
- key <BKSL> { [ U22A3, U22A2, U2359 ] }; // ⊣ ⊢ ⍙ -- Left Tack / Right Tack / APL Functional Symbol Delta Underbar
-};
-
-
-// MicroAPL layout: http://aplwiki.com/APLXKeyboardLayouts
-// I didn't do the old-style MicroAPL layout; patches gratefully accepted
-partial alphanumeric_keys modifier_keys
-xkb_symbols "aplx" {
- name[Group1]= "APL Keyboard Symbols: APLX Unified APL Layout";
-
- include "apl(unified)"
-
- // `
- key <TLDE> { [ NoSymbol, U235E ] }; // ⍞ -- APL Functional Symbol Quote Quad
- key <AE01> { [ NoSymbol, U2336 ] }; // ⌶ -- APL Functional Symbol I-Beam
- key <AE02> { [ NoSymbol, U236B ] }; // ⍫ -- APL Functional Symbol Del Tilde
- key <AE03> { [ NoSymbol, U2353 ] }; // ⍒ -- APL Functional Symbol Del Stile
- key <AE04> { [ NoSymbol, U234B ] }; // ⍋ -- APL Functional Symbol Delta Stile
- key <AE05> { [ NoSymbol, U233D ] }; // ⌽ -- APL Functional Symbol Circle Stile
- key <AE06> { [ NoSymbol, U2349 ] }; // ⍉ -- APL Functional Symbol Circle Backslash
- key <AE07> { [ NoSymbol, U2296 ] }; // ⊖ -- Circled Minus
- key <AE08> { [ NoSymbol, U235F ] }; // ⍟ -- APL Functional Symbol Circle Star
- // -
- key <AE11> { [ NoSymbol, exclam ] };
-
- // [
- key <AD11> { [ NoSymbol, U2347 ] }; // ⍇ -- Box With Left Arrow
- // ]
- key <AD12> { [ NoSymbol, U2348 ] }; // ⍈ -- Box With Right Arrow
-
- // ;
- key <AC10> { [ U234E, U2261 ] }; // ⍎ ≡ -- [See B key in SAX layout] / Identical To
- // '
- key <AC11> { [ U2355, U2262 ] }; // ⍕ ≢ -- [See N key in SAX layout] / Not Identical To
-
- // ,
- key <AB08> { [ U235D, U236A ] }; // ⍝ ⍪ -- APL Functional Symbol Up Shoe Jot / APL Functional Symbol Comma Bar
- // .
- key <AB09> { [ U2340, U2364 ] }; // ⍀ ⍤ -- APL Functional Symbol Backslash Bar / APL Functional Symbol Jot Diaeresis
- // /
- key <AB10> { [ U233F ] }; // ⌿ -- APL Functional Symbol Slash Bar
-
- key <BKSL> { [ U22A3, U22A3 ] }; // ⊣ ⊢ -- Left Tack / Right Tack
-};
+// EXTRAS: +// +// APL Keyboard Layouts + +// This file supports: +// - The Sharp APL for Unix (SAX) layout +// - The IBM APL2 layout +// - The Manugistics APL*PLUS II (Version 5.1, 1993) keyboard layout + +// Unicode APL table: http://aplwiki.com/UnicodeAplTable +// ...and another: http://publibfp.boulder.ibm.com/epubs/pdf/h2110611.pdf (appendix A) +// Generic Unicode stuff: http://www.fileformat.info/info/unicode/category/index.htm + +// Tim Nelson (this file's creator) says: + +// This file doesn't deal with all the combining stuff -- I'm not an APL programmer, +// and am not quite sure what's needed here. However, it may be possible to get this +// working with dead keys and the like. Patches gratefully accepted. + +// Some of the shift-key assignments may differ from the APL tradition. If +// that's not considered acceptable, it should be possible to remap the +// shift keys. I have striven, however, to ensure that the use of shift keys +// in these maps is at least self-consistent. + +// I'm assuming that this will be used with another keyboard layout (ie. for +// your language), with a special shift key to use these maps. + +partial alphanumeric_keys modifier_keys +xkb_symbols "common" { + name[Group1]= "APL"; + + key <AE01> { [ diaeresis ] }; + key <AE02> { [ U00AF ] }; // ¯ -- Macron + key <AE03> { [ less ] }; + key <AE04> { [ U2264 ] }; // ≤ -- Less-than Or Equal To + key <AE05> { [ equal ] }; + key <AE06> { [ U2265 ] }; // ≥ -- Greater-than Or Equal To + key <AE07> { [ greater ] }; + key <AE08> { [ U2260 ] }; // ≠ -- Not Equal To + key <AE09> { [ U2228 ] }; // ∨ -- Logical Or + key <AE10> { [ U2227 ] }; // ∧ -- Logical And + + // Q + key <AD01> { [ question ] }; + // W + key <AD02> { [ U2375 ] }; // ⍵ -- APL Functional Symbol Omega + // E + key <AD03> { [ U220A ] }; // ∊ -- Small Element Of + // R + key <AD04> { [ U2374 ] }; // ⍴ -- APL Functional Symbol Rho + // T + key <AD05> { [ asciitilde ] }; + // Y + key <AD06> { [ U2191 ] }; // ↑ -- Upwards Arrow + // U + key <AD07> { [ U2193 ] }; // ↓ -- Downwards Arrow + // I + key <AD08> { [ U2373 ] }; // ⍳ -- APL Functional Symbol Iota + // O + key <AD09> { [ U25CB ] }; // ○ -- White Circle + // P + key <AD10> { [ U22C6 ] }; // ⋆ -- Should this be a plain asterisk, or the star operator??? + // [ + key <AD11> { [ U2190 ] }; // ← -- Leftwards Arrow + + // A + key <AC01> { [ U237A ] }; // ⍺ -- APL Functional Symbol Alpha + // S + key <AC02> { [ U2308 ] }; // ⌈ -- Left Ceiling + // D + key <AC03> { [ U230A ] }; // ⌊ -- Left Floor + // F + key <AC04> { [ underscore ] }; + // G + key <AC05> { [ U2207 ] }; // ∇ -- Nabla + // H + key <AC06> { [ U2206 ] }; // ∆ -- Increment + // J + key <AC07> { [ U2218 ] }; // ∘ -- Ring Operator + // K + key <AC08> { [ apostrophe ] }; + // L + key <AC09> { [ U2395 ] }; // ⎕ -- APL Functional Symbol Quad + + // Z + key <AB01> { [ U2282 ] }; // ⊂ -- Subset Of + // X + key <AB02> { [ U2283 ] }; // ⊃ -- Superset Of + // C + key <AB03> { [ U2229 ] }; // ∩ -- Intersection + // V + key <AB04> { [ U222A ] }; // ∪ -- Union + // B + key <AB05> { [ U22A5 ] }; // ⊥ -- Up Tack + // N + key <AB06> { [ U22A4 ] }; // ⊤ -- Down Tack + // M + key <AB07> { [ U007C ] }; // | -- Vertical Line +}; + +// Keys common to a number of keyboards that allow normal language usage alongside APL +partial alphanumeric_keys modifier_keys +xkb_symbols "unified" { + name[Group1]= "APL Keyboard Symbols: Unified Layout"; + + include "apl(common)" + + // ` + key <TLDE> { [ U22C4 ] }; // ⋄ -- Diamond Operator + key <AE09> { [ NoSymbol, U2371 ] }; // ⍱ -- APL Functional Symbol Down Caret Tilde + key <AE10> { [ NoSymbol, U2372 ] }; // ⍲ -- APL Functional Symbol Up Caret Tilde + // - + key <AE11> { [ U00D7 ] }; // × -- Multiplication Sign + // = + key <AE12> { [ U00F7, U2339 ] }; // ÷ ⌹ -- Division Sign / APL Functional Symbol Quad Divide + + // ] + key <AD12> { [ U2192 ] }; // → -- Rightwards Arrow +}; + +// Layout: http://www.wickensonline.co.uk/apl-unicomp.html +default +partial alphanumeric_keys modifier_keys +xkb_symbols "sax" { + name[Group1]= "APL Keyboard Symbols: Sharp APL for Unix"; + + include "apl(unified)" + + key <AE01> { [ NoSymbol, U00A1 ] }; // ¡ -- Inverted Exclamation Mark + key <AE04> { [ NoSymbol, cent ] }; + key <AE08> { [ NoSymbol, U2342 ] }; // ⍂ -- APL Functional Symbol Quad Backslash + // - + key <AE11> { [ NoSymbol, U2261 ] }; // ≡ -- Identical To + + // Q + key <AD01> { [ NoSymbol, U00BF ] }; // ¿ -- Inverted Question Mark + // W + key <AD02> { [ NoSymbol, U233D ] }; // ⌽ -- APL Functional Symbol Circle Stile + // E + key <AD03> { [ NoSymbol, U2377 ] }; // ⍷ -- APL Functional Symbol Epsilon Underbar + // T + key <AD05> { [ NoSymbol, U2349 ] }; // ⍉ -- APL Functional Symbol Circle Backslash + // I + key <AD08> { [ NoSymbol, U2378 ] }; // ⍸ -- APL Functional Symbol Iota Underbar + // O + key <AD09> { [ NoSymbol, U2365 ] }; // ⍥ -- APL Functional Symbol Circle Diaeresis + // P + key <AD10> { [ NoSymbol, U235F ] }; // ⍟ -- APL Functional Symbol Circle Star + + // A + key <AC01> { [ NoSymbol, U2296 ] }; // ⊖ -- Circled Minus + // F + key <AC04> { [ NoSymbol, U236B ] }; // ⍫ -- APL Functional Symbol Del Tilde + // G + key <AC05> { [ NoSymbol, U2352 ] }; // ∇ ⍒ -- APL Functional Symbol Del Stile + // H + key <AC06> { [ NoSymbol, U234B ] }; // ∆ ⍋ -- APL Functional Symbol Delta Stile + // J + key <AC07> { [ NoSymbol, U2364 ] }; // ⍤ -- APL Functional Symbol Jot Diaeresis + // K + key <AC08> { [ NoSymbol, U233B ] }; // ⌻ + // L + key <AC09> { [ NoSymbol, U235E ] }; // ⍞ -- APL Functional Symbol Quote Quad + // ; + key <AC10> { [ U22A2 ] }; // ⊢ -- Right Tack + // ' + key <AC11> { [ U22A3 ] }; // ⊣ -- Left Tack + + // C + key <AB03> { [ NoSymbol, U235D ] }; // ⍝ -- APL Functional Symbol Up Shoe Jot + // B + key <AB05> { [ NoSymbol, U234E ] }; // ⍎ -- APL Functional Symbol Down Tack Jot (Unicode got the name wrong; it should have been "Up Tack") + // N + key <AB06> { [ NoSymbol, U2355 ] }; // ⍕ -- APL Functional Symbol Up Tack Jot (Unicode got the name wrong; it should have been "Down Tack") + // M + key <AB07> { [ NoSymbol, U2336 ] }; // ⌶ -- APL Functional Symbol I-Beam + // , + key <AB08> { [ U235E, U236A ] }; // ⍞ ⍪ -- APL Functional Symbol Quote Quad / APL Functional Symbol Comma Bar + // . + key <AB09> { [ U234E, U2359 ] }; // ⍎ ⍙ -- [See B key] / APL Functional Symbol Delta Underbar + // / + key <AB10> { [ U2355, U233F ] }; // ⍕ ⌿ -- [See N key] / APL Functional Symbol Slash Bar + + key <BKSL> { [ U235D, U2340 ] }; // ⍝ ⍀ -- APL Functional Symbol Up Shoe Jot / APL Functional Symbol Backslash Bar +}; + +// Layout: http://www.wickensonline.co.uk/apl-unicomp.html +partial alphanumeric_keys modifier_keys +xkb_symbols "apl2" { + name[Group1]= "APL Keyboard Symbols: IBM APL2"; + + include "apl(common)" + + // The first column is NoSymbol because it inherits. The second is NoSymbol because those keys don't do anything + + // ` + key <TLDE> { [ NoSymbol, U233B, U2342 ] }; // ⌻ ⍂ -- + key <AE01> { [ NoSymbol, NoSymbol, U2336 ] }; // ⌶ -- APL Functional Symbol I-Beam + key <AE02> { [ NoSymbol, NoSymbol, U236B ] }; // ⍫ -- APL Functional Symbol Del Tilde + key <AE03> { [ NoSymbol, NoSymbol, U2353 ] }; // ⍒ -- APL Functional Symbol Del Stile + key <AE04> { [ NoSymbol, NoSymbol, U234B ] }; // ⍋ -- APL Functional Symbol Delta Stile + key <AE05> { [ NoSymbol, NoSymbol, U233D ] }; // ⌽ -- APL Functional Symbol Circle Stile + key <AE06> { [ NoSymbol, NoSymbol, U2349 ] }; // ⍉ -- APL Functional Symbol Circle Backslash + key <AE07> { [ NoSymbol, NoSymbol, U2296 ] }; // ⊖ -- Circled Minus + key <AE08> { [ NoSymbol, NoSymbol, U235F ] }; // ⍟ -- APL Functional Symbol Circle Star + key <AE09> { [ NoSymbol, NoSymbol, U2371 ] }; // ⍱ -- APL Functional Symbol Down Caret Tilde + key <AE10> { [ NoSymbol, NoSymbol, U2372 ] }; // ⍲ -- APL Functional Symbol Up Caret Tilde + // - + key <AE11> { [ plus, minus, exclam ] }; + // = + key <AE12> { [ U00D7, U00F7, U2339 ] }; // × ÷ ⌹ -- Multiplication Sign / Division Sign / APL Functional Symbol Quad Divide + + // [ + key <AD11> { [ NoSymbol, U2192, U235E ] }; // (←) → ⍞ -- Rightwards Arrow / APL Functional Symbol Quote Quad + // ] + key <AD12> { [ U2337, U2378, U2359 ] }; // ⌷ ⍸ ⍙ -- APL Functional Symbol Squish Quad / APL Functional Symbol Iota Underbar / APL Functional Symbol Delta Underbar + + // ; + key <AC10> { [ bracketleft, parenleft, U234E ] }; // ⍎ -- [See B key in SAX layout] + // ' + key <AC11> { [ bracketright, parenright, U2355 ] }; // ⍕ -- [See N key in SAX layout] + + // , + key <AB08> { [ comma, semicolon, U235D ] }; // ⍝ -- APL Functional Symbol Up Shoe Jot + // . + key <AB09> { [ period, colon, U2340 ] }; // ⍀ -- APL Functional Symbol Backslash Bar + // / + key <AB10> { [ slash, backslash, U233F ] }; // ⌿ -- APL Functional Symbol Slash Bar + + key <BKSL> { [ U2261, U2377, U2364 ] }; // ≡ ⍷ ⍤ -- Identical To / APL Functional Symbol Epsilon Underbar / APL Functional Symbol Jot Diaeresis +}; + +partial alphanumeric_keys modifier_keys +xkb_symbols "aplplusII" { + name[Group1]= "APL Keyboard Symbols: Manugistics APL*PLUS II"; + + include "apl(apl2)" + + // ` + key <TLDE> { [ dollar, U22C4, U236A ] }; // ⋄ ⍪ -- Diamond Operator / APL Functional Symbol Comma Bar + key <AE01> { [ NoSymbol, NoSymbol, U2261 ] }; // ≡ -- Identical To + + // [ + key <AD11> { [ U2190, NoSymbol, U235E ] }; // ← ⍞ -- Leftwards Arrow / APL Functional Symbol Quote Quad + // ] + key <AD12> { [ U2192, NoSymbol, U236C ] }; // → ⍬ -- Rightwards Arrow / APL Functional Symbol Zilde + + // ; + key <AC10> { [ bracketleft, parenleft, U234E ] }; // ⍎ -- [See B key in SAX layout] + // ' + key <AC11> { [ bracketright, parenright, U2355 ] }; // ⍕ -- [See N key in SAX layout] + + key <BKSL> { [ U22A3, U22A2, U2359 ] }; // ⊣ ⊢ ⍙ -- Left Tack / Right Tack / APL Functional Symbol Delta Underbar +}; + + +// MicroAPL layout: http://aplwiki.com/APLXKeyboardLayouts +// I didn't do the old-style MicroAPL layout; patches gratefully accepted +partial alphanumeric_keys modifier_keys +xkb_symbols "aplx" { + name[Group1]= "APL Keyboard Symbols: APLX Unified APL Layout"; + + include "apl(unified)" + + // ` + key <TLDE> { [ NoSymbol, U235E ] }; // ⍞ -- APL Functional Symbol Quote Quad + key <AE01> { [ NoSymbol, U2336 ] }; // ⌶ -- APL Functional Symbol I-Beam + key <AE02> { [ NoSymbol, U236B ] }; // ⍫ -- APL Functional Symbol Del Tilde + key <AE03> { [ NoSymbol, U2353 ] }; // ⍒ -- APL Functional Symbol Del Stile + key <AE04> { [ NoSymbol, U234B ] }; // ⍋ -- APL Functional Symbol Delta Stile + key <AE05> { [ NoSymbol, U233D ] }; // ⌽ -- APL Functional Symbol Circle Stile + key <AE06> { [ NoSymbol, U2349 ] }; // ⍉ -- APL Functional Symbol Circle Backslash + key <AE07> { [ NoSymbol, U2296 ] }; // ⊖ -- Circled Minus + key <AE08> { [ NoSymbol, U235F ] }; // ⍟ -- APL Functional Symbol Circle Star + // - + key <AE11> { [ NoSymbol, exclam ] }; + + // [ + key <AD11> { [ NoSymbol, U2347 ] }; // ⍇ -- Box With Left Arrow + // ] + key <AD12> { [ NoSymbol, U2348 ] }; // ⍈ -- Box With Right Arrow + + // ; + key <AC10> { [ U234E, U2261 ] }; // ⍎ ≡ -- [See B key in SAX layout] / Identical To + // ' + key <AC11> { [ U2355, U2262 ] }; // ⍕ ≢ -- [See N key in SAX layout] / Not Identical To + + // , + key <AB08> { [ U235D, U236A ] }; // ⍝ ⍪ -- APL Functional Symbol Up Shoe Jot / APL Functional Symbol Comma Bar + // . + key <AB09> { [ U2340, U2364 ] }; // ⍀ ⍤ -- APL Functional Symbol Backslash Bar / APL Functional Symbol Jot Diaeresis + // / + key <AB10> { [ U233F ] }; // ⌿ -- APL Functional Symbol Slash Bar + + key <BKSL> { [ U22A3, U22A3 ] }; // ⊣ ⊢ -- Left Tack / Right Tack +}; diff --git a/xorg-server/xkeyboard-config/symbols/es b/xorg-server/xkeyboard-config/symbols/es index 048a9f03a..88b390d97 100644 --- a/xorg-server/xkeyboard-config/symbols/es +++ b/xorg-server/xkeyboard-config/symbols/es @@ -1,202 +1,217 @@ -// based on a keyboard
-// Modified for a real Spanish Keyboard by Jon Tombs
-//
-
-partial default alphanumeric_keys
-xkb_symbols "basic" {
-
- include "latin(type4)"
-
- name[Group1]="Spain";
-
- key <AE01> { [ 1, exclam, bar, exclamdown ] };
- key <AE03> { [ 3, periodcentered, numbersign, sterling ] };
- key <AE04> { [ 4, dollar, asciitilde, dollar ] };
- key <AE06> { [ 6, ampersand, notsign, fiveeighths ] };
- key <AE11> { [apostrophe, question, backslash, questiondown ] };
- key <AE12> { [exclamdown, questiondown, dead_tilde, asciitilde ] };
-
- key <AD11> { [dead_grave, dead_circumflex, bracketleft, dead_abovering ] };
- key <AD12> { [ plus, asterisk, bracketright, dead_macron ] };
-
- key <AC10> { [ ntilde, Ntilde, asciitilde, dead_doubleacute ] };
- key <AC11> { [dead_acute, dead_diaeresis, braceleft, braceleft ] };
- key <TLDE> { [ masculine, ordfeminine, backslash, backslash ] };
-
- key <BKSL> { [ ccedilla, Ccedilla, braceright, dead_breve ] };
-
- include "level3(ralt_switch)"
-};
-
-partial alphanumeric_keys
-xkb_symbols "Sundeadkeys" {
-
- include "es(basic)"
-
- key <AC11> { [dead_acute, dead_diaeresis, braceleft, braceleft ] };
- key <AD11> { [dead_grave, dead_circumflex, bracketleft, dead_abovering ] };
-};
-
-partial alphanumeric_keys
-xkb_symbols "sundeadkeys" {
-
- include "es(Sundeadkeys)"
-
- name[Group1]="Spain - Sun dead keys";
-};
-
-partial alphanumeric_keys
-xkb_symbols "nodeadkeys" {
-
- include "es(basic)"
-
- name[Group1]="Spain - Eliminate dead keys";
-
- key <AD11> { [ grave, asciicircum, bracketleft, degree ] };
- key <AD12> { [ plus, asterisk, bracketright, macron ] };
- key <AC10> { [ ntilde, Ntilde, asciitilde, doubleacute ] };
- key <AC11> { [ acute, diaeresis, braceleft, braceleft ] };
- key <BKSL> { [ ccedilla, Ccedilla, braceright, breve ] };
- key <AB10> { [ minus, underscore, dead_belowdot, abovedot ] };
-};
-
-// Spanish mapping (note R-H exchange)
-partial alphanumeric_keys
-xkb_symbols "dvorak" {
-
- name[Group1]="Spain - Dvorak";
-
- // Alphanumeric section
- key <TLDE> {[ masculine, ordfeminine, backslash, degree ]};
- key <AE01> {[ 1, exclam, bar, onesuperior ]};
- key <AE02> {[ 2, quotedbl, at, twosuperior ]};
- key <AE03> {[ 3, periodcentered, numbersign, threesuperior ]};
- key <AE04> {[ 4, dollar, asciitilde, onequarter ]};
- key <AE05> {[ 5, percent, brokenbar, fiveeighths ]};
- key <AE06> {[ 6, ampersand, notsign, threequarters ]};
- key <AE07> {[ 7, slash, onehalf, seveneighths ]};
- key <AE08> {[ 8, parenleft, oneeighth, threeeighths ]};
- key <AE09> {[ 9, parenright, asciicircum ]};
- key <AE10> {[ 0, equal, grave, dead_doubleacute ]};
- key <AE11> {[ apostrophe, question, dead_macron, dead_ogonek ]};
- key <AE12> {[ exclamdown, questiondown, dead_breve, dead_abovedot ]};
-
- key <AD01> {[ period, colon ]};
- key <AD02> {[ comma, semicolon ]};
- key <AD03> {[ ntilde, Ntilde, lstroke, Lstroke ]};
- key <AD04> {[ p, P, paragraph ]};
- key <AD05> {[ y, Y, yen ]};
- key <AD06> {[ f, F, tslash, Tslash ]};
- key <AD07> {[ g, G, dstroke, Dstroke ]};
- key <AD08> {[ c, C, cent, copyright ]};
- key <AD09> {[ h, H, hstroke, Hstroke ]};
- key <AD10> {[ l, L, sterling ]};
- key <AD11> {[ dead_grave, dead_circumflex, bracketleft, dead_caron ]};
- key <AD12> {[ plus, asterisk, bracketright, plusminus ]};
-
- key <AC01> {[ a, A, ae, AE ]};
- key <AC02> {[ o, O, oslash, Oslash ]};
- key <AC03> {[ e, E, EuroSign ]};
- key <AC04> {[ u, U, aring, Aring ]};
- key <AC05> {[ i, I, oe, OE ]};
- key <AC06> {[ d, D, eth, ETH ]};
- key <AC07> {[ r, R, registered, trademark ]};
- key <AC08> {[ t, T, thorn, THORN ]};
- key <AC09> {[ n, N, eng, ENG ]};
- key <AC10> {[ s, S, ssharp, section ]};
- key <AC11> {[ dead_acute, dead_diaeresis, braceleft, dead_tilde ]};
- key <BKSL> {[ ccedilla, Ccedilla, braceright, dead_cedilla ]};
-
- key <LSGT> {[ less, greater, guillemotleft, guillemotright ]};
- key <AB01> {[ minus, underscore, hyphen, macron ]};
- key <AB02> {[ q, Q, currency ]};
- key <AB03> {[ j, J ]};
- key <AB04> {[ k, K, kra ]};
- key <AB05> {[ x, X, multiply, division ]};
- key <AB06> {[ b, B ]};
- key <AB07> {[ m, M, mu ]};
- key <AB08> {[ w, W ]};
- key <AB09> {[ v, V ]};
- key <AB10> {[ z, Z ]};
-
- include "level3(ralt_switch)"
-};
-
-partial alphanumeric_keys
-xkb_symbols "cat" {
-
- include "es(basic)"
-
- name[Group1]="Spain - Catalan variant with middle-dot L";
-
- key <AC09> { [ l, L, 0x1000140, 0x100013F ] };
-};
-
-partial alphanumeric_keys
-xkb_symbols "ast" {
-
- include "es(basic)"
-
- name[Group1]="Spain - Asturian variant with bottom-dot H and bottom-dot L";
-
- key <AC06> { [ h, H, 0x1001E25, 0x1001E24 ] };
- key <AC09> { [ l, L, 0x1001E37, 0x1001E36 ] };
-};
-
-// Copied from macintosh_vndr/es
-partial alphanumeric_keys
-xkb_symbols "mac" {
-
- // Describes the differences between a very simple mac_US
- // keyboard and a very simple Spanish keybaord
-
- include "es"
- name[Group1]= "Spain - Macintosh";
-
-};
-
-partial alphanumeric_keys
-xkb_symbols "olpc" {
-
- include "us(basic)"
- name[Group1]="Spain";
-
- key <TLDE> { [ masculine, ordfeminine ] };
- key <AE01> { [ 1, exclam, bar ] };
- key <AE02> { [ 2, quotedbl, at ] };
- key <AE03> { [ 3, dead_grave, numbersign, grave ] };
- key <AE05> { [ 5, percent, asciicircum, dead_circumflex ] };
- key <AE06> { [ 6, ampersand, notsign ] };
- key <AE07> { [ 7, slash, backslash ] };
- key <AE08> { [ 8, parenleft ] };
- key <AE09> { [ 9, parenright ] };
- key <AE10> { [ 0, equal ] };
- key <AE11> { [ apostrophe, question ] };
- key <AE12> { [ exclamdown, questiondown ] };
-
- key <AD03> { [ e, E, EuroSign ] };
- key <AD11> { [ dead_acute, dead_diaeresis, acute, dead_abovering ] };
- key <AD12> { [ bracketleft, braceleft ] };
-
- key <AC10> { [ ntilde, Ntilde ] };
- key <AC11> { [ plus, asterisk, dead_tilde ] };
- key <BKSL> { [ bracketright, braceright ] };
-
- key <AB08> { [ comma, semicolon ] };
- key <AB09> { [ period, colon ] };
- key <AB10> { [ minus, underscore ] };
-
- key <I219> { [ less, greater, ISO_Next_Group ] };
-
- include "level3(ralt_switch)"
-};
-
-partial alphanumeric_keys
-xkb_symbols "deadtilde" {
-
- include "es(basic)"
-
- name[Group1]="Spain - Include dead tilde";
-
- key <AE04> { [ 4, dollar, dead_tilde, dollar ] };
-};
+// based on a keyboard +// Modified for a real Spanish Keyboard by Jon Tombs +// + +partial default alphanumeric_keys +xkb_symbols "basic" { + + include "latin(type4)" + + name[Group1]="Spain"; + + key <AE01> { [ 1, exclam, bar, exclamdown ] }; + key <AE03> { [ 3, periodcentered, numbersign, sterling ] }; + key <AE04> { [ 4, dollar, asciitilde, dollar ] }; + key <AE06> { [ 6, ampersand, notsign, fiveeighths ] }; + key <AE11> { [apostrophe, question, backslash, questiondown ] }; + key <AE12> { [exclamdown, questiondown, dead_tilde, asciitilde ] }; + + key <AD11> { [dead_grave, dead_circumflex, bracketleft, dead_abovering ] }; + key <AD12> { [ plus, asterisk, bracketright, dead_macron ] }; + + key <AC10> { [ ntilde, Ntilde, asciitilde, dead_doubleacute ] }; + key <AC11> { [dead_acute, dead_diaeresis, braceleft, braceleft ] }; + key <TLDE> { [ masculine, ordfeminine, backslash, backslash ] }; + + key <BKSL> { [ ccedilla, Ccedilla, braceright, dead_breve ] }; + + include "level3(ralt_switch)" +}; + +partial alphanumeric_keys +xkb_symbols "Sundeadkeys" { + + include "es(basic)" + + key <AC11> { [dead_acute, dead_diaeresis, braceleft, braceleft ] }; + key <AD11> { [dead_grave, dead_circumflex, bracketleft, dead_abovering ] }; +}; + +partial alphanumeric_keys +xkb_symbols "sundeadkeys" { + + include "es(Sundeadkeys)" + + name[Group1]="Spain - Sun dead keys"; +}; + +partial alphanumeric_keys +xkb_symbols "nodeadkeys" { + + include "es(basic)" + + name[Group1]="Spain - Eliminate dead keys"; + + key <AD11> { [ grave, asciicircum, bracketleft, degree ] }; + key <AD12> { [ plus, asterisk, bracketright, macron ] }; + key <AC10> { [ ntilde, Ntilde, asciitilde, doubleacute ] }; + key <AC11> { [ acute, diaeresis, braceleft, braceleft ] }; + key <BKSL> { [ ccedilla, Ccedilla, braceright, breve ] }; + key <AB10> { [ minus, underscore, dead_belowdot, abovedot ] }; +}; + +// Spanish mapping (note R-H exchange) +partial alphanumeric_keys +xkb_symbols "dvorak" { + + name[Group1]="Spain - Dvorak"; + + // Alphanumeric section + key <TLDE> {[ masculine, ordfeminine, backslash, degree ]}; + key <AE01> {[ 1, exclam, bar, onesuperior ]}; + key <AE02> {[ 2, quotedbl, at, twosuperior ]}; + key <AE03> {[ 3, periodcentered, numbersign, threesuperior ]}; + key <AE04> {[ 4, dollar, asciitilde, onequarter ]}; + key <AE05> {[ 5, percent, brokenbar, fiveeighths ]}; + key <AE06> {[ 6, ampersand, notsign, threequarters ]}; + key <AE07> {[ 7, slash, onehalf, seveneighths ]}; + key <AE08> {[ 8, parenleft, oneeighth, threeeighths ]}; + key <AE09> {[ 9, parenright, asciicircum ]}; + key <AE10> {[ 0, equal, grave, dead_doubleacute ]}; + key <AE11> {[ apostrophe, question, dead_macron, dead_ogonek ]}; + key <AE12> {[ exclamdown, questiondown, dead_breve, dead_abovedot ]}; + + key <AD01> {[ period, colon ]}; + key <AD02> {[ comma, semicolon ]}; + key <AD03> {[ ntilde, Ntilde, lstroke, Lstroke ]}; + key <AD04> {[ p, P, paragraph ]}; + key <AD05> {[ y, Y, yen ]}; + key <AD06> {[ f, F, tslash, Tslash ]}; + key <AD07> {[ g, G, dstroke, Dstroke ]}; + key <AD08> {[ c, C, cent, copyright ]}; + key <AD09> {[ h, H, hstroke, Hstroke ]}; + key <AD10> {[ l, L, sterling ]}; + key <AD11> {[ dead_grave, dead_circumflex, bracketleft, dead_caron ]}; + key <AD12> {[ plus, asterisk, bracketright, plusminus ]}; + + key <AC01> {[ a, A, ae, AE ]}; + key <AC02> {[ o, O, oslash, Oslash ]}; + key <AC03> {[ e, E, EuroSign ]}; + key <AC04> {[ u, U, aring, Aring ]}; + key <AC05> {[ i, I, oe, OE ]}; + key <AC06> {[ d, D, eth, ETH ]}; + key <AC07> {[ r, R, registered, trademark ]}; + key <AC08> {[ t, T, thorn, THORN ]}; + key <AC09> {[ n, N, eng, ENG ]}; + key <AC10> {[ s, S, ssharp, section ]}; + key <AC11> {[ dead_acute, dead_diaeresis, braceleft, dead_tilde ]}; + key <BKSL> {[ ccedilla, Ccedilla, braceright, dead_cedilla ]}; + + key <LSGT> {[ less, greater, guillemotleft, guillemotright ]}; + key <AB01> {[ minus, underscore, hyphen, macron ]}; + key <AB02> {[ q, Q, currency ]}; + key <AB03> {[ j, J ]}; + key <AB04> {[ k, K, kra ]}; + key <AB05> {[ x, X, multiply, division ]}; + key <AB06> {[ b, B ]}; + key <AB07> {[ m, M, mu ]}; + key <AB08> {[ w, W ]}; + key <AB09> {[ v, V ]}; + key <AB10> {[ z, Z ]}; + + include "level3(ralt_switch)" +}; + +partial alphanumeric_keys +xkb_symbols "cat" { + + include "es(basic)" + + name[Group1]="Spain - Catalan variant with middle-dot L"; + + key <AC09> { [ l, L, 0x1000140, 0x100013F ] }; +}; + +partial alphanumeric_keys +xkb_symbols "ast" { + + include "es(basic)" + + name[Group1]="Spain - Asturian variant with bottom-dot H and bottom-dot L"; + + key <AC06> { [ h, H, 0x1001E25, 0x1001E24 ] }; + key <AC09> { [ l, L, 0x1001E37, 0x1001E36 ] }; +}; + +// Copied from macintosh_vndr/es +partial alphanumeric_keys +xkb_symbols "mac" { + + // Describes the differences between a very simple mac_US + // keyboard and a very simple Spanish keybaord + + include "es" + name[Group1]= "Spain - Macintosh"; + +}; + +partial alphanumeric_keys +xkb_symbols "olpc" { + + include "us(basic)" + name[Group1]="Spain"; + + key <TLDE> { [ masculine, ordfeminine ] }; + key <AE01> { [ 1, exclam, bar ] }; + key <AE02> { [ 2, quotedbl, at ] }; + key <AE03> { [ 3, dead_grave, numbersign, grave ] }; + key <AE05> { [ 5, percent, asciicircum, dead_circumflex ] }; + key <AE06> { [ 6, ampersand, notsign ] }; + key <AE07> { [ 7, slash, backslash ] }; + key <AE08> { [ 8, parenleft ] }; + key <AE09> { [ 9, parenright ] }; + key <AE10> { [ 0, equal ] }; + key <AE11> { [ apostrophe, question ] }; + key <AE12> { [ exclamdown, questiondown ] }; + + key <AD03> { [ e, E, EuroSign ] }; + key <AD11> { [ dead_acute, dead_diaeresis, acute, dead_abovering ] }; + key <AD12> { [ bracketleft, braceleft ] }; + + key <AC10> { [ ntilde, Ntilde ] }; + key <AC11> { [ plus, asterisk, dead_tilde ] }; + key <BKSL> { [ bracketright, braceright, section ] }; + + key <AB08> { [ comma, semicolon ] }; + key <AB09> { [ period, colon ] }; + key <AB10> { [ minus, underscore ] }; + + key <I219> { [ less, greater, ISO_Next_Group ] }; + + include "level3(ralt_switch)" +}; + +partial alphanumeric_keys +xkb_symbols "deadtilde" { + + include "es(basic)" + + name[Group1]="Spain - Include dead tilde"; + + key <AE04> { [ 4, dollar, dead_tilde, dollar ] }; +}; + +partial alphanumeric_keys +xkb_symbols "olpc2" { + + // Modified variant of US International layout, specifically for Peru + // Contact: Sayamindu Dasgupta <sayamindu@laptop.org> + + include "us(olpc)" + name[Group1]="Spain - OLPC2"; + + key <AE03> { [ 3, numbersign, dead_grave, dead_grave] }; // combining grave + key <I236> { [ XF86Start ] }; + + include "level3(ralt_switch)" +}; diff --git a/xorg-server/xkeyboard-config/symbols/extras/Makefile.am b/xorg-server/xkeyboard-config/symbols/extras/Makefile.am deleted file mode 100644 index 948060441..000000000 --- a/xorg-server/xkeyboard-config/symbols/extras/Makefile.am +++ /dev/null @@ -1,5 +0,0 @@ -symbolsdir = $(xkb_base)/symbols/extras
-dist_symbols_DATA = apl \
- ir \
- rs ru \
- us
diff --git a/xorg-server/xkeyboard-config/symbols/extras/ir b/xorg-server/xkeyboard-config/symbols/extras/ir deleted file mode 100644 index 52502bf75..000000000 --- a/xorg-server/xkeyboard-config/symbols/extras/ir +++ /dev/null @@ -1,63 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////
-//
-// Generated keyboard layout file with the Keyboard Layout Editor.
-// For more about the software, see http://code.google.com/p/keyboardlayouteditor
-//
-// Version 0.2, fixed AD09.
-//
-// Layout by Ernst Tremel, http://ubuntuforums.org/showpost.php?p=9365469&postcount=32
-// Creation of this file by Simos Xenitellis.
-
-partial default alphanumeric_keys
-xkb_symbols "ave"
-{
- name[Group1] = "Iran - Avestan";
-
- key <AB01> { [ U10B30, U10B32 ] }; // 𐬰 𐬲
- key <AB02> { [ U10B11, U10B12 ] }; // 𐬑 𐬒
- key <AB03> { [ U10B17, UE102 ] }; // 𐬗
- key <AB04> { [ U10B2C, U10B13 ] }; // 𐬬 𐬓
- key <AB05> { [ U10B20, U10B21 ] }; // 𐬠 𐬡
- key <AB06> { [ U10B25, U10B27 ] }; // 𐬥 𐬧
- key <AB07> { [ U10B28, U10B29 ] }; // 𐬨 𐬩
- key <AB08> { [ U10B3C, U10B39 ] }; // 𐬼 𐬹
- key <AB09> { [ U10B3E, U10B3D ] }; // 𐬾 𐬽
- key <AB10> { [ U10B3F, periodcentered ] }; // 𐬿 ·
-
- key <AC01> { [ U10B00, U10B01 ] }; // 𐬀 𐬁
- key <AC02> { [ U10B2F, U10B31 ] }; // 𐬯 𐬱
- key <AC03> { [ U10B1B, U10B1C ] }; // 𐬛 𐬜
- key <AC04> { [ U10B1F, U10B16 ] }; // 𐬟 𐬖
- key <AC05> { [ U10B14, U10B15 ] }; // 𐬔 𐬕
- key <AC06> { [ U10B35, UE100 ] }; // 𐬵
- key <AC07> { [ U10B18, U10B24 ] }; // 𐬘 𐬤
- key <AC08> { [ U10B10, UE101 ] }; // 𐬐
- key <AC09> { [ U10B2E, UE103 ] }; // 𐬮
- key <AC10> { [ U10B3B, U10B3A ] }; // 𐬻 𐬺
- key <AC11> { [ U10B1D ] }; // 𐬝
-
- key <AD01> { [ U10B22, U10B23 ] }; // 𐬢 𐬣
- key <AD02> { [ U10B33, U10B34 ] }; // 𐬳 𐬴
- key <AD03> { [ U10B08, U10B09 ] }; // 𐬈 𐬉
- key <AD04> { [ U10B2D, U10B26 ] }; // 𐬭 𐬦
- key <AD05> { [ U10B19, U10B1A ] }; // 𐬙 𐬚
- key <AD06> { [ U10B2B, U10B2A ] }; // 𐬫 𐬪
- key <AD07> { [ U10B0E, U10B0F ] }; // 𐬎 𐬏
- key <AD08> { [ U10B0C, U10B0D ] }; // 𐬌 𐬍
- key <AD09> { [ U10B0A, U10B0B ] }; // 𐬊 𐬋
- key <AD10> { [ U10B1E ] }; // 𐬞
- key <AD11> { [ U10B06, U10B07 ] }; // 𐬆 𐬇
- key <AD12> { [ U10B02, U10B03 ] }; // 𐬂 𐬃
-
- key <AE01> { [ U10B78 ] }; // 𐭸
- key <AE02> { [ U10B79 ] }; // 𐭹
- key <AE03> { [ U10B7A ] }; // 𐭺
- key <AE04> { [ U10B7B ] }; // 𐭻
- key <AE05> { [ U10B7C ] }; // 𐭼
- key <AE06> { [ U10B7D ] }; // 𐭽
- key <AE07> { [ U10B7E ] }; // 𐭾
- key <AE08> { [ U10B7F ] }; // 𐭿
-
- key <BKSL> { [ U10B04, U10B05 ] }; // 𐬄 𐬅
- key <LSGT> { [ U10B04, U10B05 ] }; // 𐬄 𐬅
-};
diff --git a/xorg-server/xkeyboard-config/symbols/extras/rs b/xorg-server/xkeyboard-config/symbols/extras/rs deleted file mode 100644 index cc6b5fb44..000000000 --- a/xorg-server/xkeyboard-config/symbols/extras/rs +++ /dev/null @@ -1,15 +0,0 @@ -xkb_symbols "combiningkeys" { - // Raw combining characters instead of dead keys, - // especially good for post-accenting texts. - - name[Group1]= "Serbia - Combining accents instead of dead keys"; - - include "rs(basic)" - - key <AE03> { [ any,any, U0302, dead_circumflex ] }; // 3, U0302 = COMBINING CIRCUMFLEX ACCENT - key <AE07> { [ any,any, U0300, NoSymbol ] }; // 7, U0300 = COMBINING GRAVE ACCENT - key <AE08> { [ any,any, U030F, NoSymbol ] }; // 8, U030F = COMBINING DOUBLE GRAVE ACCENT - key <AE09> { [ any,any, U0301, NoSymbol ] }; // 9, U0301 = COMBINING ACUTE ACCENT - key <AE10> { [ any,any, U0311, NoSymbol ] }; // 0, U0311 = COMBINING INVERTED BREVE - key <AE11> { [ any,any, U0304, NoSymbol ] }; // -, U0304 = COMBINING MACRON -}; diff --git a/xorg-server/xkeyboard-config/symbols/extras/ru b/xorg-server/xkeyboard-config/symbols/extras/ru deleted file mode 100644 index b872be3d8..000000000 --- a/xorg-server/xkeyboard-config/symbols/extras/ru +++ /dev/null @@ -1,58 +0,0 @@ -// Church Slavonic language layout
-// based on
-// russian standard keyboard
-// Aleksandr Andreev and Yuri Shardt
-// Last Changes 2010/08/01. Contact <aleksandr.andreev@gmail.com>
-
-partial alphanumeric_keys
-xkb_symbols "chu"
-{
- name[Group1]= "Russia - Church Slavonic";
- key <TLDE> { [ U0457, U0407, U0482, U20DD ] }; // ї Ї ҂ e.g: а⃝ where the last is a combining ten thousands sign
- key <AE01> { [ U0461, U0460, U047D, U047C] }; // ѡ Ѡ ѽ Ѽ
- key <AE02> { [ U0454, U0404, U0465, U0464] }; // є Є ѥ Ѥ
- key <AE03> { [ U046F, U046E, U0469, U0468] }; // ѯ Ѯ ѩ Ѩ
- key <AE04> { [ U0471, U0470, U046D, U046C] }; // ѱ Ѱ ѭ Ѭ
- key <AE05> { [ U0473, U0472, UA657, UA656] }; // ѳ Ѳ iotified A
- key <AE06> { [ U0475, U0474, U0477, U0476] }; // ѵ Ѵ ѷ Ѷ
- key <AE07> { [ U047B, U047A, UA64D, UA64C] }; // ѻ Ѻ ꙍ Ꙍ
- key <AE08> { [ U047F, U047E, U046B, U046A] }; // ѿ Ѿ ѫ Ѫ
- key <AE09> { [ U0455, U0405, parenleft, U002A ] }; // ѕ Ѕ ( *
- key <AE10> { [ Cyrillic_u, Cyrillic_U, parenright, U0488 ] }; // у У ) NB: for diagraph Ouk, use Cyrillic_o + Cyrillic_u
- key <AE11> { [ U0483, U0486, U0487, U005F] }; // а҃ а҆ а҇, _ (titlo, psili, pokrytie, underscore)
- key <AE12> { [ U0301, U0300, U0484, UA67E] }; // а̀ а́ а҄ ꙾ (oxia, varia, kamora, kavyka)
- key <AD01> { [ Cyrillic_shorti, Cyrillic_SHORTI, U0456 ] };
- key <AD02> { [ Cyrillic_tse, Cyrillic_TSE, U2DF0 ] };
- key <AD03> { [ UA64B, UA64A, U2DF9 ] }; // Cyrillic monograph Uk (not U)!
- key <AD04> { [ Cyrillic_ka, Cyrillic_KA, U2DE6 ] };
- key <AD05> { [ Cyrillic_ie, Cyrillic_IE, U2DF7 ] };
- key <AD06> { [ Cyrillic_en, Cyrillic_EN, U2DE9 ] };
- key <AD07> { [ Cyrillic_ghe, Cyrillic_GHE, U2DE2 ] };
- key <AD08> { [ Cyrillic_sha, Cyrillic_SHA, U2DF2 ] };
- key <AD09> { [ Cyrillic_shcha, Cyrillic_SHCHA, U2DF3 ] };
- key <AD10> { [ Cyrillic_ze, Cyrillic_ZE, U2DE5 ] };
- key <AD11> { [ Cyrillic_ha, Cyrillic_HA, U2DEF ] };
- key <AD12> { [Cyrillic_hardsign,Cyrillic_HARDSIGN, UA67D ] }; // Payerok
- key <BKSL> { [backslash, slash, colon, question] }; // \ / : ? (note, for Slavonic question use semicolon
- key <AC01> { [ Cyrillic_ef, Cyrillic_EF ] };
- key <AC02> { [ Cyrillic_yeru, Cyrillic_YERU ] };
- key <AC03> { [ Cyrillic_ve, Cyrillic_VE, U2DE1 ] };
- key <AC04> { [ Cyrillic_a, Cyrillic_A, U2DF6 ] };
- key <AC05> { [ Cyrillic_pe, Cyrillic_PE, U2DEB ] };
- key <AC06> { [ Cyrillic_er, Cyrillic_ER, U2DEC ] };
- key <AC07> { [ Cyrillic_o, Cyrillic_O, U2DEA ] };
- key <AC08> { [ Cyrillic_el, Cyrillic_EL, U2DE7 ] };
- key <AC09> { [ Cyrillic_de, Cyrillic_DE, U2DE3 ] };
- key <AC10> { [ Cyrillic_zhe, Cyrillic_ZHE, U2DE4 ] };
- key <AC11> { [ U0463, U0462, U2DFA ] }; // Yat
- key <AB01> { [ U0467, U0466, U2DFD ] }; // Small Yus
- key <AB02> { [ Cyrillic_che, Cyrillic_CHE, U2DF1 ] };
- key <AB03> { [ Cyrillic_es, Cyrillic_ES, U2DED ] };
- key <AB04> { [ Cyrillic_em, Cyrillic_EM, U2DE8 ] };
- key <AB05> { [ Cyrillic_i, Cyrillic_I ] };
- key <AB06> { [ Cyrillic_te, Cyrillic_TE, U2DEE ] };
- key <AB07> { [Cyrillic_softsign,Cyrillic_SOFTSIGN ] };
- key <AB08> { [ Cyrillic_be, Cyrillic_BE, U2DE0 ] };
- key <AB09> { [ Cyrillic_yu, Cyrillic_YU, U2DFB ] };
- key <AB10> { [ period, comma, semicolon, exclam ] };
-};
diff --git a/xorg-server/xkeyboard-config/symbols/extras/us b/xorg-server/xkeyboard-config/symbols/extras/us deleted file mode 100644 index 45d9954cf..000000000 --- a/xorg-server/xkeyboard-config/symbols/extras/us +++ /dev/null @@ -1,146 +0,0 @@ -// XCompose is out! Unicode combining is in! For those of us who live
-// on the edge: A keymap using Unicode combining characters instead of
-// deadkeys. This variation does not deviate from the lame MS-style
-// US-intl layout; but it uses AltGr for combining, like altgr-intl.
-//
-// This might break your font layout layout systems (because they
-// suck), caveat emptor. Also, most of today's software will count
-// individual combining marks for selection, deletion, character
-// counting &c., and won't be smart enough to do canonical equivalence
-// when searching, &c.
-//
-// With Unicode combining you use "handwriting order", not
-// "typewriting order" as with deadkeys. That is, you first type the
-// base character, then the diacritics/accents/modifiers. This has
-// the advantage of avoiding hidden states --- each keypress changes
-// something on screen.
-//
-// TODO: as of now, this duplicates all us(intl) functionality with
-// combining. With care, perhaps we could add more combining marks
-// not present in intl, and support all major languages.
-partial alphanumeric_keys
-xkb_symbols "intl-unicode" {
-
- name[Group1]= "USA - International (AltGr Unicode combining)";
-
- include "us(intl)"
- include "level3(ralt_switch)"
-
- // grave, tilde
- key <TLDE> { [grave, asciitilde, U0300, U0303 ] };
- // double acute
- key <AE02> { [ 2, at, twosuperior, U030B ] };
- // macron
- key <AE03> { [ 3, numbersign, threesuperior, U0304 ] };
- // circumflex
- key <AE06> { [ 6, asciicircum, onequarter, U0302 ] };
- // horn
- key <AE07> { [ 7, ampersand, onehalf, U031B ] };
- // ogonek
- key <AE08> { [ 8, asterisk, threequarters, U0328 ] };
- // breve
- key <AE09> { [ 9, parenleft, leftsinglequotemark, U0306 ] };
- // abovering
- key <AE10> { [ 0, parenright, rightsinglequotemark, U030A ] };
-
- // belowdot
- key <AE11> { [ minus, underscore, yen, U0323 ] };
- // acute, diaeresis
- key <AC11> { [apostrophe, quotedbl, U0301, U0308 ] };
- // abovedot, caron
- key <AB09> { [ period, greater, U0307, U030C ] };
- // hook
- key <AB10> { [ slash, question, questiondown, 0309 ] };
-
- // alt-intl compatibility
- // cedilla, caron
- key <AB08> { [ comma, less, U0327, U030C ] };
- // ogonek, diaeresis
- key <AC10> { [ semicolon, colon, U0328, U0308 ] };
- // doubleacute, horn
- key <AE12> { [ equal, plus, U030B, U031B ] };
-
- // we don't do combining latin letters and combining enclosures
- // because support for those is very rare.
-};
-
-// XCompose is out! Unicode combining is in! For those of us who live
-// on the edge: A keymap using Unicode combining characters instead of
-// deadkeys. This variation does break compatibility with us-intl,
-// whenever I thought it would be more mnemonic or Unicodeish.
-partial alphanumeric_keys
-xkb_symbols "alt-intl-unicode" {
-
- name[Group1]= "USA - International (AltGr Unicode combining, alternative)";
-
- include "extras/us(intl-unicode)"
- include "level3(ralt_switch)"
-
- // easier macron; em-dash.
- // em-dash is available via compose, but I added here since it's such
- // an important typographic character.
- key <AE11> { [ minus, underscore, U0304, U2014 ] };
-
- // belowdot, abovedot (caron at coma/less key, per above)
- key <AB09> { [ period, greater, U0323, U0307 ] };
-
-};
-
-partial alphanumeric_keys
-xkb_symbols "ats" {
-
- include "us"
-
- name[Group1]= "USA - Atsina";
-
- //Using Dead key to get COMBINING COMMA ABOVE for ejectives on
- //q, l, t, s, m, g, k, p, w, y, r
- //XCompose key is used for the other accute and grave.
-
- key <AD03> { [ e, E, eacute, Eacute ] };
- key <AD07> { [ u, U, uacute, Uacute ] };
- key <AD08> { [ i, I, iacute, Iacute ] };
- key <AD09> { [ o, O, oacute, Oacute ] };
- key <AD11> { [ bracketleft, braceleft, U03B8 ] };
- key <AD12> { [ bracketright, braceright, U010D, U010C ] };
- //U+010C (uppercase Č) and U+010D (lowercase č).
-
- key <AC01> { [ a, A, aacute, Aacute ] };
-
-
- //Small letter Open use compose to key get acute accent
- key <AB03> { [ c, C, U0254, U0186 ] };
- key <AB08> { [ comma, less, U0313 ] };
- key <AB10> { [ slash, question, U0294 ] };
-
- include "level3(ralt_switch)"
- include "compose(rctrl)"
-};
-
-partial alphanumeric_keys
-xkb_symbols "crd" {
-
- include "us"
-
- name[Group1]= "USA - Couer D'alene Salish";
-
- // Alphanumeric section
- key <AD02> { [ w, W, U02B7, U02B7 ] };
- key <AE07> { [ 7, ampersand, U0294 ] };
- key <AD01> { [ q, Q, U221A ] };
- key <AB04> { [ v, V, U0259 ] };
- key <BKSL> { [ backslash, bar, U026B ] };
- key <AD03> { [ e, E, U025B ] };
- key <AD08> { [ i, I, U026A ] };
- key <AC07> { [ j, J, U01F0 ] };
- key <AE06> { [ 6, asciicircum, U0295 ] };
- key <AC02> { [ s, S, U0161 ] };
- key <AB03> { [ c, C, U010D ] };
- key <AD09> { [ o, O, U0254 ] };
- key <AB09> { [ period, greater, U0323 ] };
-
- include "level3(ralt_switch)"
- include "compose(rctrl)"
-
- // End alphanumeric section
-};
diff --git a/xorg-server/xkeyboard-config/symbols/ir b/xorg-server/xkeyboard-config/symbols/ir index 6f4618df7..1832e819b 100644 --- a/xorg-server/xkeyboard-config/symbols/ir +++ b/xorg-server/xkeyboard-config/symbols/ir @@ -1,240 +1,306 @@ -// Iranian keyboard layout
-
-////////////////////////////////////////
-// Persian layout,
-// based on
-// Information Technology – Layout of Persian Letters and Symbols on Computer Keyboards
-// ISIRI 9147 – 1st Edition
-// Institute of Standards and Industrial Research of Iran
-// http://www.isiri.org/UserStd/DownloadStd.aspx?id=9147
-// http://behnam.esfahbod.info/standards/isiri-keyboard-9147.pdf
-//
-// Author: Behnam Esfahbod <behnam@esfahbod.info>
-//
-
-partial default alphanumeric_keys
-xkb_symbols "pes" {
- name[Group1]= "Iran";
-
- include "ir(pes_part_basic)"
- include "ir(pes_part_ext)"
-
- include "nbsp(zwnj2nb3nnb4)"
- include "level3(ralt_switch)"
-};
-
-
-partial alphanumeric_keys
-xkb_symbols "pes_keypad" {
- name[Group1]= "Iran - Persian, with Persian Keypad";
-
- include "ir(pes_part_basic)"
- include "ir(pes_part_keypad)"
-
- include "nbsp(zwnj2nb3nnb4)"
- include "level3(ralt_switch)"
-};
-
-partial hidden alphanumeric_keys
-xkb_symbols "pes_part_basic" {
-
- // Persian digits
- key <AE01> { [ Farsi_1, exclam, quoteleft ] };
- key <AE02> { [ Farsi_2, 0x100066c, at ] };
- key <AE03> { [ Farsi_3, 0x100066b, numbersign ] };
- key <AE04> { [ Farsi_4, 0x100fdfc, dollar ] };
- key <AE05> { [ Farsi_5, 0x100066a, percent ] };
- key <AE06> { [ Farsi_6, multiply, asciicircum ] };
- key <AE07> { [ Farsi_7, Arabic_comma, ampersand ] };
- key <AE08> { [ Farsi_8, asterisk, enfilledcircbullet ] };
- key <AE09> { [ Farsi_9, parenright, 0x100200e ] };
- key <AE10> { [ Farsi_0, parenleft, 0x100200f ] };
-
- // Persian letters and symbols
- key <AD01> { [ Arabic_dad, Arabic_sukun, degree ] };
- key <AD02> { [ Arabic_sad, Arabic_dammatan, VoidSymbol ] };
- key <AD03> { [ Arabic_theh, Arabic_kasratan, 0x13a4 ] };
- key <AD04> { [ Arabic_qaf, Arabic_fathatan, VoidSymbol ] };
- key <AD05> { [ Arabic_feh, Arabic_damma, VoidSymbol ] };
- key <AD06> { [ Arabic_ghain, Arabic_kasra, VoidSymbol ] };
- key <AD07> { [ Arabic_ain, Arabic_fatha, VoidSymbol ] };
- key <AD08> { [ Arabic_heh, Arabic_shadda, 0x100202d ] };
- key <AD09> { [ Arabic_khah, bracketright, 0x100202e ] };
- key <AD10> { [ Arabic_hah, bracketleft, 0x100202c ] };
- key <AD11> { [ Arabic_jeem, braceright, 0x100202a ] };
- key <AD12> { [ Arabic_tcheh, braceleft, 0x100202b ] };
-
- key <AC01> { [ Arabic_sheen, Arabic_hamzaonwaw, VoidSymbol ] };
- key <AC02> { [ Arabic_seen, Arabic_hamzaonyeh, VoidSymbol ] };
- key <AC03> { [ Farsi_yeh, Arabic_yeh, Arabic_alefmaksura ] };
- key <AC04> { [ Arabic_beh, Arabic_hamzaunderalef, VoidSymbol ] };
- key <AC05> { [ Arabic_lam, Arabic_hamzaonalef, VoidSymbol ] };
- key <AC06> { [ Arabic_alef, Arabic_maddaonalef, 0x1000671 ] };
- key <AC07> { [ Arabic_teh, Arabic_tehmarbuta, VoidSymbol ] };
- key <AC08> { [ Arabic_noon, guillemotright, 0x100fd3e ] };
- key <AC09> { [ Arabic_meem, guillemotleft, 0x100fd3f ] };
- key <AC10> { [ Arabic_keheh, colon, semicolon ] };
- key <AC11> { [ Arabic_gaf, Arabic_semicolon, quotedbl ] };
-
- key <AB01> { [ Arabic_zah, Arabic_kaf, VoidSymbol ] };
- key <AB02> { [ Arabic_tah, 0x1000653, VoidSymbol ] };
- key <AB03> { [ Arabic_zain, Arabic_jeh, VoidSymbol ] };
- key <AB04> { [ Arabic_ra, Arabic_superscript_alef
-, 0x1000656 ] };
- key <AB05> { [ Arabic_thal, 0x100200c, 0x100200d ] };
- key <AB06> { [ Arabic_dal, Arabic_hamza_above
-, Arabic_hamza_below ] };
- key <AB07> { [ Arabic_peh, Arabic_hamza, ellipsis ] };
- key <AB08> { [ Arabic_waw, greater, comma ] };
- key <AB09> { [ period, less, apostrophe ] };
- key <AB10> { [ slash, Arabic_question_mark, question ] };
-
- key <TLDE> { [ 0x100200d, division, asciitilde ] };
- key <AE11> { [ minus, Arabic_tatweel, underscore ] };
- key <AE12> { [ equal, plus, 0x1002212 ] };
- key <BKSL> { [ backslash, bar, 0x1002010 ] };
-};
-
-partial hidden alphanumeric_keys
-xkb_symbols "pes_part_ext" {
-
- // Persian and ASCII digits
- key <AE01> { [ 0x10006f1, exclam, quoteleft, 1 ] };
- key <AE02> { [ 0x10006f2, 0x100066c, at, 2 ] };
- key <AE03> { [ 0x10006f3, 0x100066b, numbersign, 3 ] };
- key <AE04> { [ 0x10006f4, 0x100fdfc, dollar, 4 ] };
- key <AE05> { [ 0x10006f5, 0x100066a, percent, 5 ] };
- key <AE06> { [ 0x10006f6, multiply, asciicircum, 6 ] };
- key <AE07> { [ 0x10006f7, Arabic_comma, ampersand, 7 ] };
- key <AE08> { [ 0x10006f8, asterisk, enfilledcircbullet, 8 ] };
- key <AE09> { [ 0x10006f9, parenright, 0x100200e, 9 ] };
- key <AE10> { [ 0x10006f0, parenleft, 0x100200f, 0 ] };
-};
-
-partial hidden alphanumeric_keys
-xkb_symbols "pes_part_keypad" {
-
- // Persian digits and Mathematical operators
- key <KPDV> { [ division, XF86_Ungrab ] };
- key <KPMU> { [ multiply, XF86_ClearGrab ] };
- key <KPSU> { [ 0x1002212, XF86_Prev_VMode ] };
- key <KPAD> { [ plus, XF86_Next_VMode ] };
-
- key <KPEN> { [ KP_Enter ] };
- key <KPEQ> { [ equal ] };
-
- key <KP7> { [ KP_Home, 0x10006f7 ] };
- key <KP8> { [ KP_Up, 0x10006f8 ] };
- key <KP9> { [ KP_Prior, 0x10006f9 ] };
-
- key <KP4> { [ KP_Left, 0x10006f4 ] };
- key <KP5> { [ KP_Begin, 0x10006f5 ] };
- key <KP6> { [ KP_Right, 0x10006f6 ] };
-
- key <KP1> { [ KP_End, 0x10006f1 ] };
- key <KP2> { [ KP_Down, 0x10006f2 ] };
- key <KP3> { [ KP_Next, 0x10006f3 ] };
-
- key <KP0> { [ KP_Insert, 0x10006f0 ] };
- key <KPDL> { [ KP_Delete, 0x100066b ] };
-};
-
-
-////////////////////////////////////////
-// Kurdish Layout
-
-partial alphanumeric_keys
-xkb_symbols "ku" {
- include "tr(ku)"
- name[Group1]= "Iran - Kurdish, Latin Q";
-};
-
-partial alphanumeric_keys
-xkb_symbols "ku_f" {
- include "tr(ku_f)"
- name[Group1]= "Iran - Kurdish, (F)";
-};
-
-partial alphanumeric_keys
-xkb_symbols "ku_alt" {
- include "tr(ku_alt)"
- name[Group1]= "Iran - Kurdish, Latin Alt-Q";
-};
-
-////////////////////////////////////////
-// Kurdish Soranî Bahdînî (Arabic) keyboard layout,
-// based on the Kurdî Soranî Bahdînî keyboard from KurdITGroup
-// which is based on National Iranian Keyboard Standard (ISIRI 2901:1994),
-// with additions.
-//
-// Copyright (C) 2006 Erdal Ronahî, published under the GPL v2
-//
-// Special copyright note: author explicitly permitted to license this
-// layout under MIT/X11 license, for details see
-// https://bugs.freedesktop.org/show_bug.cgi?id=9541
-//
-// Author: Erdal Ronahî <erdal.ronahi@gmail.com>
-//
-// Kurdish Arabic-Latin Layout for Soranî
-
-partial alphanumeric_keys
-xkb_symbols "ku_ara" {
- name[Group1]= "Iran - Kurdish, Arabic-Latin";
-
- // Other 3-Level symbols
- key <TLDE> { [ 0x100200d, division, asciitilde ] };
- key <BKSL> { [ backslash, bar, ccedilla, Ccedilla ] };
-
- // Digits
- key <AE01> { [ 1, exclam, 0x10006f1, quoteleft ] };
- key <AE02> { [ 2, at, 0x10006f2, at ] };
- key <AE03> { [ 3, numbersign, 0x10006f3, 0x100066b ] };
- key <AE04> { [ 4, dollar, 0x10006f4, 0x100fdfc ] };
- key <AE05> { [ 5, percent, 0x10006f5, 0x100066a ] };
- key <AE06> { [ 6, asciicircum, 0x10006f6, multiply ] };
- key <AE07> { [ 7, ampersand, 0x10006f7, Arabic_comma ] };
- key <AE08> { [ 8, asterisk, 0x10006f8, enfilledcircbullet ] };
- key <AE09> { [ 9, parenright, 0x10006f9, 0x100200e ] };
- key <AE10> { [ 0, parenleft, 0x10006f0, 0x100200f ] };
- key <AE11> { [ minus, Arabic_tatweel, underscore ] };
- key <AE12> { [ equal, plus, 0x1002212 ] };
-
- key <AD01> { [ Arabic_qaf, X, q, Q ] };
- key <AD02> { [ Arabic_waw, X, w, W ] };
- key <AD03> { [ 0x10006d5, Arabic_heh, e, E ] };
- key <AD04> { [ Arabic_ra , 0x1000695, r, R ] };
- key <AD05> { [ Arabic_teh, Arabic_tah, t, T ] };
- key <AD06> { [ 0x10006cc, 0x10006ce, y, Y ] };
- key <AD07> { [ Arabic_hamzaonyeh, Arabic_hamza, u, U ] };
- key <AD08> { [ Arabic_hah, Arabic_ain, i, I ] };
- key <AD09> { [ 0x10006c6, Arabic_hamzaonwaw, o, O ] };
- key <AD10> { [ 0x100067e, Arabic_theh, p, P ] };
- key <AD11> { [ bracketright, braceright, ucircumflex, Ucircumflex ] };
- key <AD12> { [ bracketleft, braceleft, scedilla, Scedilla ] };
-
- key <AC01> { [ Arabic_alef, Arabic_maddaonalef, a, A ] };
- key <AC02> { [ Arabic_seen, Arabic_sheen, s, S ] };
- key <AC03> { [ Arabic_dal, Arabic_thal, d, D ] };
- key <AC04> { [ Arabic_feh, Arabic_hamzaunderalef, f, F ] };
- key <AC05> { [ 0x10006af, Arabic_ghain, g, G ] };
- key <AC06> { [ Arabic_heh, 0x100200c, h, H ] };
- key <AC07> { [ 0x1000698, Arabic_hamzaonalef, j, J ] };
- key <AC08> { [ 0x10006a9, Arabic_kaf, k, K ] };
- key <AC09> { [ Arabic_lam, 0x10006b5, l, L ] };
- key <AC10> { [ Arabic_semicolon, colon, ecircumflex, Ecircumflex ] };
- key <AC11> { [ apostrophe, quotedbl, icircumflex, Icircumflex ] };
-
- key <AB01> { [ Arabic_zain, Arabic_dad, z, Z ] };
- key <AB02> { [ Arabic_khah, Arabic_sad, x, X ] };
- key <AB03> { [ Arabic_jeem, 0x1000686, c, C ] };
- key <AB04> { [ 0x10006a4, Arabic_zah, v, V ] };
- key <AB05> { [ Arabic_beh, 0x1000649, b, B ] };
- key <AB06> { [ Arabic_noon, Arabic_tehmarbuta, n, N ] };
- key <AB07> { [ Arabic_meem, Arabic_tatweel, m, M ] };
- key <AB08> { [ Arabic_comma, greater, comma ] };
- key <AB09> { [ period, less, apostrophe ] };
- key <AB10> { [ slash, Arabic_question_mark, question ] };
-
- include "nbsp(zwnj2nb3)"
- include "level3(ralt_switch)"
-};
+// Iranian keyboard layout + +//////////////////////////////////////// +// Persian layout, +// based on +// Information Technology – Layout of Persian Letters and Symbols on Computer Keyboards +// ISIRI 9147 – 1st Edition +// Institute of Standards and Industrial Research of Iran +// http://www.isiri.org/UserStd/DownloadStd.aspx?id=9147 +// http://behnam.esfahbod.info/standards/isiri-keyboard-9147.pdf +// +// Author: Behnam Esfahbod <behnam@esfahbod.info> +// + +partial default alphanumeric_keys +xkb_symbols "pes" { + name[Group1]= "Iran"; + + include "ir(pes_part_basic)" + include "ir(pes_part_ext)" + + include "nbsp(zwnj2nb3nnb4)" + include "level3(ralt_switch)" +}; + + +partial alphanumeric_keys +xkb_symbols "pes_keypad" { + name[Group1]= "Iran - Persian, with Persian Keypad"; + + include "ir(pes_part_basic)" + include "ir(pes_part_keypad)" + + include "nbsp(zwnj2nb3nnb4)" + include "level3(ralt_switch)" +}; + +partial hidden alphanumeric_keys +xkb_symbols "pes_part_basic" { + + // Persian digits + key <AE01> { [ Farsi_1, exclam, quoteleft ] }; + key <AE02> { [ Farsi_2, 0x100066c, at ] }; + key <AE03> { [ Farsi_3, 0x100066b, numbersign ] }; + key <AE04> { [ Farsi_4, 0x100fdfc, dollar ] }; + key <AE05> { [ Farsi_5, 0x100066a, percent ] }; + key <AE06> { [ Farsi_6, multiply, asciicircum ] }; + key <AE07> { [ Farsi_7, Arabic_comma, ampersand ] }; + key <AE08> { [ Farsi_8, asterisk, enfilledcircbullet ] }; + key <AE09> { [ Farsi_9, parenright, 0x100200e ] }; + key <AE10> { [ Farsi_0, parenleft, 0x100200f ] }; + + // Persian letters and symbols + key <AD01> { [ Arabic_dad, Arabic_sukun, degree ] }; + key <AD02> { [ Arabic_sad, Arabic_dammatan, VoidSymbol ] }; + key <AD03> { [ Arabic_theh, Arabic_kasratan, 0x13a4 ] }; + key <AD04> { [ Arabic_qaf, Arabic_fathatan, VoidSymbol ] }; + key <AD05> { [ Arabic_feh, Arabic_damma, VoidSymbol ] }; + key <AD06> { [ Arabic_ghain, Arabic_kasra, VoidSymbol ] }; + key <AD07> { [ Arabic_ain, Arabic_fatha, VoidSymbol ] }; + key <AD08> { [ Arabic_heh, Arabic_shadda, 0x100202d ] }; + key <AD09> { [ Arabic_khah, bracketright, 0x100202e ] }; + key <AD10> { [ Arabic_hah, bracketleft, 0x100202c ] }; + key <AD11> { [ Arabic_jeem, braceright, 0x100202a ] }; + key <AD12> { [ Arabic_tcheh, braceleft, 0x100202b ] }; + + key <AC01> { [ Arabic_sheen, Arabic_hamzaonwaw, VoidSymbol ] }; + key <AC02> { [ Arabic_seen, Arabic_hamzaonyeh, VoidSymbol ] }; + key <AC03> { [ Farsi_yeh, Arabic_yeh, Arabic_alefmaksura ] }; + key <AC04> { [ Arabic_beh, Arabic_hamzaunderalef, VoidSymbol ] }; + key <AC05> { [ Arabic_lam, Arabic_hamzaonalef, VoidSymbol ] }; + key <AC06> { [ Arabic_alef, Arabic_maddaonalef, 0x1000671 ] }; + key <AC07> { [ Arabic_teh, Arabic_tehmarbuta, VoidSymbol ] }; + key <AC08> { [ Arabic_noon, guillemotright, 0x100fd3e ] }; + key <AC09> { [ Arabic_meem, guillemotleft, 0x100fd3f ] }; + key <AC10> { [ Arabic_keheh, colon, semicolon ] }; + key <AC11> { [ Arabic_gaf, Arabic_semicolon, quotedbl ] }; + + key <AB01> { [ Arabic_zah, Arabic_kaf, VoidSymbol ] }; + key <AB02> { [ Arabic_tah, 0x1000653, VoidSymbol ] }; + key <AB03> { [ Arabic_zain, Arabic_jeh, VoidSymbol ] }; + key <AB04> { [ Arabic_ra, Arabic_superscript_alef +, 0x1000656 ] }; + key <AB05> { [ Arabic_thal, 0x100200c, 0x100200d ] }; + key <AB06> { [ Arabic_dal, Arabic_hamza_above +, Arabic_hamza_below ] }; + key <AB07> { [ Arabic_peh, Arabic_hamza, ellipsis ] }; + key <AB08> { [ Arabic_waw, greater, comma ] }; + key <AB09> { [ period, less, apostrophe ] }; + key <AB10> { [ slash, Arabic_question_mark, question ] }; + + key <TLDE> { [ 0x100200d, division, asciitilde ] }; + key <AE11> { [ minus, Arabic_tatweel, underscore ] }; + key <AE12> { [ equal, plus, 0x1002212 ] }; + key <BKSL> { [ backslash, bar, 0x1002010 ] }; +}; + +partial hidden alphanumeric_keys +xkb_symbols "pes_part_ext" { + + // Persian and ASCII digits + key <AE01> { [ 0x10006f1, exclam, quoteleft, 1 ] }; + key <AE02> { [ 0x10006f2, 0x100066c, at, 2 ] }; + key <AE03> { [ 0x10006f3, 0x100066b, numbersign, 3 ] }; + key <AE04> { [ 0x10006f4, 0x100fdfc, dollar, 4 ] }; + key <AE05> { [ 0x10006f5, 0x100066a, percent, 5 ] }; + key <AE06> { [ 0x10006f6, multiply, asciicircum, 6 ] }; + key <AE07> { [ 0x10006f7, Arabic_comma, ampersand, 7 ] }; + key <AE08> { [ 0x10006f8, asterisk, enfilledcircbullet, 8 ] }; + key <AE09> { [ 0x10006f9, parenright, 0x100200e, 9 ] }; + key <AE10> { [ 0x10006f0, parenleft, 0x100200f, 0 ] }; +}; + +partial hidden alphanumeric_keys +xkb_symbols "pes_part_keypad" { + + // Persian digits and Mathematical operators + key <KPDV> { [ division, XF86_Ungrab ] }; + key <KPMU> { [ multiply, XF86_ClearGrab ] }; + key <KPSU> { [ 0x1002212, XF86_Prev_VMode ] }; + key <KPAD> { [ plus, XF86_Next_VMode ] }; + + key <KPEN> { [ KP_Enter ] }; + key <KPEQ> { [ equal ] }; + + key <KP7> { [ KP_Home, 0x10006f7 ] }; + key <KP8> { [ KP_Up, 0x10006f8 ] }; + key <KP9> { [ KP_Prior, 0x10006f9 ] }; + + key <KP4> { [ KP_Left, 0x10006f4 ] }; + key <KP5> { [ KP_Begin, 0x10006f5 ] }; + key <KP6> { [ KP_Right, 0x10006f6 ] }; + + key <KP1> { [ KP_End, 0x10006f1 ] }; + key <KP2> { [ KP_Down, 0x10006f2 ] }; + key <KP3> { [ KP_Next, 0x10006f3 ] }; + + key <KP0> { [ KP_Insert, 0x10006f0 ] }; + key <KPDL> { [ KP_Delete, 0x100066b ] }; +}; + + +//////////////////////////////////////// +// Kurdish Layout + +partial alphanumeric_keys +xkb_symbols "ku" { + include "tr(ku)" + name[Group1]= "Iran - Kurdish, Latin Q"; +}; + +partial alphanumeric_keys +xkb_symbols "ku_f" { + include "tr(ku_f)" + name[Group1]= "Iran - Kurdish, (F)"; +}; + +partial alphanumeric_keys +xkb_symbols "ku_alt" { + include "tr(ku_alt)" + name[Group1]= "Iran - Kurdish, Latin Alt-Q"; +}; + +//////////////////////////////////////// +// Kurdish Soranî Bahdînî (Arabic) keyboard layout, +// based on the Kurdî Soranî Bahdînî keyboard from KurdITGroup +// which is based on National Iranian Keyboard Standard (ISIRI 2901:1994), +// with additions. +// +// Copyright (C) 2006 Erdal Ronahî, published under the GPL v2 +// +// Special copyright note: author explicitly permitted to license this +// layout under MIT/X11 license, for details see +// https://bugs.freedesktop.org/show_bug.cgi?id=9541 +// +// Author: Erdal Ronahî <erdal.ronahi@gmail.com> +// +// Kurdish Arabic-Latin Layout for Soranî + +partial alphanumeric_keys +xkb_symbols "ku_ara" { + name[Group1]= "Iran - Kurdish, Arabic-Latin"; + + // Other 3-Level symbols + key <TLDE> { [ 0x100200d, division, asciitilde ] }; + key <BKSL> { [ backslash, bar, ccedilla, Ccedilla ] }; + + // Digits + key <AE01> { [ 1, exclam, 0x10006f1, quoteleft ] }; + key <AE02> { [ 2, at, 0x10006f2, at ] }; + key <AE03> { [ 3, numbersign, 0x10006f3, 0x100066b ] }; + key <AE04> { [ 4, dollar, 0x10006f4, 0x100fdfc ] }; + key <AE05> { [ 5, percent, 0x10006f5, 0x100066a ] }; + key <AE06> { [ 6, asciicircum, 0x10006f6, multiply ] }; + key <AE07> { [ 7, ampersand, 0x10006f7, Arabic_comma ] }; + key <AE08> { [ 8, asterisk, 0x10006f8, enfilledcircbullet ] }; + key <AE09> { [ 9, parenright, 0x10006f9, 0x100200e ] }; + key <AE10> { [ 0, parenleft, 0x10006f0, 0x100200f ] }; + key <AE11> { [ minus, Arabic_tatweel, underscore ] }; + key <AE12> { [ equal, plus, 0x1002212 ] }; + + key <AD01> { [ Arabic_qaf, X, q, Q ] }; + key <AD02> { [ Arabic_waw, X, w, W ] }; + key <AD03> { [ 0x10006d5, Arabic_heh, e, E ] }; + key <AD04> { [ Arabic_ra , 0x1000695, r, R ] }; + key <AD05> { [ Arabic_teh, Arabic_tah, t, T ] }; + key <AD06> { [ 0x10006cc, 0x10006ce, y, Y ] }; + key <AD07> { [ Arabic_hamzaonyeh, Arabic_hamza, u, U ] }; + key <AD08> { [ Arabic_hah, Arabic_ain, i, I ] }; + key <AD09> { [ 0x10006c6, Arabic_hamzaonwaw, o, O ] }; + key <AD10> { [ 0x100067e, Arabic_theh, p, P ] }; + key <AD11> { [ bracketright, braceright, ucircumflex, Ucircumflex ] }; + key <AD12> { [ bracketleft, braceleft, scedilla, Scedilla ] }; + + key <AC01> { [ Arabic_alef, Arabic_maddaonalef, a, A ] }; + key <AC02> { [ Arabic_seen, Arabic_sheen, s, S ] }; + key <AC03> { [ Arabic_dal, Arabic_thal, d, D ] }; + key <AC04> { [ Arabic_feh, Arabic_hamzaunderalef, f, F ] }; + key <AC05> { [ 0x10006af, Arabic_ghain, g, G ] }; + key <AC06> { [ Arabic_heh, 0x100200c, h, H ] }; + key <AC07> { [ 0x1000698, Arabic_hamzaonalef, j, J ] }; + key <AC08> { [ 0x10006a9, Arabic_kaf, k, K ] }; + key <AC09> { [ Arabic_lam, 0x10006b5, l, L ] }; + key <AC10> { [ Arabic_semicolon, colon, ecircumflex, Ecircumflex ] }; + key <AC11> { [ apostrophe, quotedbl, icircumflex, Icircumflex ] }; + + key <AB01> { [ Arabic_zain, Arabic_dad, z, Z ] }; + key <AB02> { [ Arabic_khah, Arabic_sad, x, X ] }; + key <AB03> { [ Arabic_jeem, 0x1000686, c, C ] }; + key <AB04> { [ 0x10006a4, Arabic_zah, v, V ] }; + key <AB05> { [ Arabic_beh, 0x1000649, b, B ] }; + key <AB06> { [ Arabic_noon, Arabic_tehmarbuta, n, N ] }; + key <AB07> { [ Arabic_meem, Arabic_tatweel, m, M ] }; + key <AB08> { [ Arabic_comma, greater, comma ] }; + key <AB09> { [ period, less, apostrophe ] }; + key <AB10> { [ slash, Arabic_question_mark, question ] }; + + include "nbsp(zwnj2nb3)" + include "level3(ralt_switch)" +}; + +// EXTRAS: + +///////////////////////////////////////////////////////////////////////////////// +// +// Generated keyboard layout file with the Keyboard Layout Editor. +// For more about the software, see http://code.google.com/p/keyboardlayouteditor +// +// Version 0.2, fixed AD09. +// +// Layout by Ernst Tremel, http://ubuntuforums.org/showpost.php?p=9365469&postcount=32 +// Creation of this file by Simos Xenitellis. + +partial default alphanumeric_keys +xkb_symbols "ave" +{ + name[Group1] = "Iran - Avestan"; + + key <AB01> { [ U10B30, U10B32 ] }; // 𐬰 𐬲 + key <AB02> { [ U10B11, U10B12 ] }; // 𐬑 𐬒 + key <AB03> { [ U10B17, UE102 ] }; // 𐬗 + key <AB04> { [ U10B2C, U10B13 ] }; // 𐬬 𐬓 + key <AB05> { [ U10B20, U10B21 ] }; // 𐬠 𐬡 + key <AB06> { [ U10B25, U10B27 ] }; // 𐬥 𐬧 + key <AB07> { [ U10B28, U10B29 ] }; // 𐬨 𐬩 + key <AB08> { [ U10B3C, U10B39 ] }; // 𐬼 𐬹 + key <AB09> { [ U10B3E, U10B3D ] }; // 𐬾 𐬽 + key <AB10> { [ U10B3F, periodcentered ] }; // 𐬿 · + + key <AC01> { [ U10B00, U10B01 ] }; // 𐬀 𐬁 + key <AC02> { [ U10B2F, U10B31 ] }; // 𐬯 𐬱 + key <AC03> { [ U10B1B, U10B1C ] }; // 𐬛 𐬜 + key <AC04> { [ U10B1F, U10B16 ] }; // 𐬟 𐬖 + key <AC05> { [ U10B14, U10B15 ] }; // 𐬔 𐬕 + key <AC06> { [ U10B35, UE100 ] }; // 𐬵 + key <AC07> { [ U10B18, U10B24 ] }; // 𐬘 𐬤 + key <AC08> { [ U10B10, UE101 ] }; // 𐬐 + key <AC09> { [ U10B2E, UE103 ] }; // 𐬮 + key <AC10> { [ U10B3B, U10B3A ] }; // 𐬻 𐬺 + key <AC11> { [ U10B1D ] }; // 𐬝 + + key <AD01> { [ U10B22, U10B23 ] }; // 𐬢 𐬣 + key <AD02> { [ U10B33, U10B34 ] }; // 𐬳 𐬴 + key <AD03> { [ U10B08, U10B09 ] }; // 𐬈 𐬉 + key <AD04> { [ U10B2D, U10B26 ] }; // 𐬭 𐬦 + key <AD05> { [ U10B19, U10B1A ] }; // 𐬙 𐬚 + key <AD06> { [ U10B2B, U10B2A ] }; // 𐬫 𐬪 + key <AD07> { [ U10B0E, U10B0F ] }; // 𐬎 𐬏 + key <AD08> { [ U10B0C, U10B0D ] }; // 𐬌 𐬍 + key <AD09> { [ U10B0A, U10B0B ] }; // 𐬊 𐬋 + key <AD10> { [ U10B1E ] }; // 𐬞 + key <AD11> { [ U10B06, U10B07 ] }; // 𐬆 𐬇 + key <AD12> { [ U10B02, U10B03 ] }; // 𐬂 𐬃 + + key <AE01> { [ U10B78 ] }; // 𐭸 + key <AE02> { [ U10B79 ] }; // 𐭹 + key <AE03> { [ U10B7A ] }; // 𐭺 + key <AE04> { [ U10B7B ] }; // 𐭻 + key <AE05> { [ U10B7C ] }; // 𐭼 + key <AE06> { [ U10B7D ] }; // 𐭽 + key <AE07> { [ U10B7E ] }; // 𐭾 + key <AE08> { [ U10B7F ] }; // 𐭿 + + key <BKSL> { [ U10B04, U10B05 ] }; // 𐬄 𐬅 + key <LSGT> { [ U10B04, U10B05 ] }; // 𐬄 𐬅 +}; diff --git a/xorg-server/xkeyboard-config/symbols/ro b/xorg-server/xkeyboard-config/symbols/ro index 9e9663cce..f37a60dac 100644 --- a/xorg-server/xkeyboard-config/symbols/ro +++ b/xorg-server/xkeyboard-config/symbols/ro @@ -1,233 +1,255 @@ -//
-// Complete set of Romanian keyboards as described in the new Romanian standard
-// SR 13392:2004 adopted in December 2004 by ASRO, "Asociatia de Standardizare
-// din Romania".
-//
-// The default mapping is the RO_US/Programmers layout because of the lack of
-// Romanian hardware keyboards. The primary standard layout is implemented as
-// the "std" variant. If you're determined to get cedillas as in ISO-8859-2
-// (and not commabelow accents as in ISO-8859-16) use the defined variants
-// "cedilla" for the default layout or "std_cedilla" for the standard one.
-// Pre-Vista MS compatible layout included (use the "winkeys" variant).
-//
-// Created by Cristian Gafton, <gafton@redhat.com> (C) 2000
-// Modified by Marius Andreiana, <mandreiana@yahoo.com> (C) 2001
-// Completed by Misu Moldovan, <dumol@gnome.ro> (C) 2001, 2004-2008.
-// v 1.4
-
-
-partial default alphanumeric_keys
-xkb_symbols "basic" {
-// This RO_US/Programmers layout, although the secondary layout in the
-// Romanian standard, has always been the "de facto" standard in the
-// Linux/Unix world. It is implemented here as the default layout and it's
-// fully compatible with an US keyboard (Euro on AltGr+5 doesn't count).
-
- include "us"
-
- name[Group1]="Romania";
-
- key <AE01> { [ 1, exclam, dead_tilde ] };
- key <AE02> { [ 2, at, dead_caron ] };
- key <AE03> { [ 3, numbersign, dead_circumflex ] };
- key <AE04> { [ 4, dollar, dead_breve ] };
- key <AE05> { [ 5, percent, dead_abovering ] };
- key <AE06> { [ 6, asciicircum, dead_ogonek ] };
- key <AE07> { [ 7, ampersand, dead_grave ] };
- key <AE08> { [ 8, asterisk, dead_abovedot ] };
- key <AE09> { [ 9, parenleft, dead_acute ] };
- key <AE10> { [ 0, parenright, dead_doubleacute ] };
- key <AE11> { [ minus, underscore, dead_diaeresis, endash ] };
- key <AE12> { [ equal, plus, dead_cedilla, plusminus ] };
- key <AD01> { [ q, Q, acircumflex, Acircumflex ] };
- key <AD02> { [ w, W, ssharp ] };
- key <AD03> { [ e, E, EuroSign ] };
- key <AD05> { [ t, T, 0x100021b, 0x100021a ] };
- key <AD08> { [ i, I, icircumflex, Icircumflex ] };
- key <AD10> { [ p, P, section ] };
- key <AD11> { [ bracketleft, braceleft, doublelowquotemark ] };
- key <AD12> { [ bracketright, braceright, rightdoublequotemark ] };
- key <AC01> { [ a, A, abreve, Abreve ] };
- key <AC02> { [ s, S, 0x1000219, 0x1000218 ] };
- key <AC03> { [ d, D, dstroke, Dstroke ] };
- key <AC09> { [ l, L, lstroke, Lstroke ] };
- key <LSGT> { [ backslash, bar ] };
- key <AB03> { [ c, C, copyright ] };
- key <AB08> { [ comma, less, guillemotleft ] };
- key <AB09> { [ period, greater, guillemotright ] };
-
- include "level3(ralt_switch)"
-};
-
-partial alphanumeric_keys
-xkb_symbols "cedilla" {
- // Variant of the basic layout with cedillas.
- // Implements S and T with cedilllas as in ISO-8859-2.
- // Included for compatibility reasons (this used to be the def variant).
-
- include "ro(basic)"
-
- name[Group1]="Romania - Cedilla";
-
- key <AD05> { [ t, T, tcedilla, Tcedilla ] };
- key <AC02> { [ s, S, scedilla, Scedilla ] };
-};
-
-partial alphanumeric_keys
-xkb_symbols "std" {
- // Primary layout in the new Romanian standard.
- // Implemented here as a variant because of the lack of hardware
- // Romanian keyboards and because of the predilection of Romanian
- // X users towards the secondary layout from the new standard.
-
- include "us"
-
- name[Group1]="Romania - Standard";
-
- key <TLDE> { [ doublelowquotemark, rightdoublequotemark, grave, asciitilde ] };
- key <AE01> { [ 1, exclam, dead_tilde ] };
- key <AE02> { [ 2, at, dead_caron ] };
- key <AE03> { [ 3, numbersign, dead_circumflex ] };
- key <AE04> { [ 4, dollar, dead_breve ] };
- key <AE05> { [ 5, percent, dead_abovering ] };
- key <AE06> { [ 6, asciicircum, dead_ogonek ] };
- key <AE07> { [ 7, ampersand, dead_grave ] };
- key <AE08> { [ 8, asterisk, dead_abovedot ] };
- key <AE09> { [ 9, parenleft, dead_acute ] };
- key <AE10> { [ 0, parenright, dead_doubleacute ] };
- key <AE11> { [ minus, underscore, dead_diaeresis, endash ] };
- key <AE12> { [ equal, plus, dead_cedilla, plusminus ] };
- key <AD03> { [ e, E, EuroSign ] };
- key <AD10> { [ p, P, section ] };
- key <AD11> { [ abreve, Abreve, bracketleft, braceleft ] };
- key <AD12> { [ icircumflex, Icircumflex, bracketright, braceright ] };
- key <BKSL> { [ acircumflex, Acircumflex, backslash, bar ] };
- key <AC02> { [ s, S, ssharp ] };
- key <AC03> { [ d, D, dstroke, Dstroke ] };
- key <AC09> { [ l, L, lstroke, Lstroke ] };
- key <AC10> { [ 0x1000219, 0x1000218, semicolon, colon ] };
- key <AC11> { [ 0x100021b, 0x100021a, apostrophe, quotedbl ] };
- key <LSGT> { [ backslash, bar ] };
- key <AB03> { [ c, C, copyright ] };
- key <AB08> { [ comma, semicolon, less, guillemotleft ] };
- key <AB09> { [ period, colon, greater, guillemotright ] };
-
- key <KPDL> { [ KP_Delete, KP_Separator ] };
-
- include "level3(ralt_switch)"
-};
-
-
-partial alphanumeric_keys
-xkb_symbols "std_cedilla" {
- // Variant of the "std" layout with cedillas.
- // Implements S and T with cedillas as in ISO-8859-2.
- // Included for compatibility reasons.
-
- include "ro(std)"
-
- name[Group1]="Romania - Standard (Cedilla)";
-
- key <AC10> { [ scedilla, Scedilla ] };
- key <AC11> { [ tcedilla, Tcedilla ] };
-};
-
-
-partial alphanumeric_keys
-xkb_symbols "winkeys" {
- // Describes the differences between a very simple US/ASCII
- // keyboard and a very simple Romanian keybaord
- // Created by Manfred Pohler, <Manfred.Pohler@t-online.de> (C) 2003
-
- include "latin"
-
- name[Group1]="Romania - Winkeys";
-
- // Alphanumeric section
- key <TLDE> { [ bracketright, bracketleft ] };
-
- key <AE01> { [ 1, exclam, asciitilde, asciitilde ] };
- key <AE02> { [ 2, quotedbl, at, at ] };
- key <AE03> { [ 3, numbersign, asciicircum,asciicircum ] };
- key <AE04> { [ 4, currency ] };
- key <AE05> { [ 5, percent, degree, degree ] };
- key <AE06> { [ 6, ampersand ] };
- key <AE07> { [ 7, slash, grave, grave ] };
- key <AE08> { [ 8, parenleft ] };
- key <AE09> { [ 9, parenright ] };
- key <AE10> { [ 0, equal ] };
- key <AE11> { [ plus, question ] };
- key <AE12> { [ apostrophe, asterisk ] };
-
- key <AD01> { [ q, Q, backslash, backslash ] };
- key <AD02> { [ w, W, bar, bar ] };
- key <AD03> { [ e, E, EuroSign, EuroSign ] };
- key <AD05> { [ t, T ] };
- key <AD06> { [ z, Z ] };
- key <AD07> { [ u, U ] };
- key <AD08> { [ i, I ] };
- key <AD11> { [ abreve, Abreve, division, division ] };
- key <AD12> { [ icircumflex, Icircumflex, multiply, multiply ] };
-
- key <AC04> { [ f, F ] };
- key <AC05> { [ g, G ] };
- key <AC10> { [ scedilla, Scedilla, dollar, dollar ] };
- key <AC11> { [ tcedilla, Tcedilla, ssharp, ssharp ] };
-
- key <AB01> { [ y, Y ] };
- key <AB05> { [ b, B, braceleft, braceleft ] };
- key <AB06> { [ n, N, braceright, braceright ] };
- key <AB07> { [ m, M, section, section ] };
- key <AB08> { [ comma, semicolon, less, less ] };
- key <AB09> { [ period, colon, greater, greater ] };
- key <AB10> { [ minus, underscore ] };
-
- key <BKSL> { [ acircumflex, Acircumflex ] };
-
- // End alphanumeric section, begin "Keypad"
- include "kpdl(comma)"
- // End "Keypad" section
-
- include "level3(ralt_switch)"
-
-};
-
-// Crimean Tatar (Crimean Turkish) layouts.
-partial
-xkb_symbols "crh_f" {
- include "tr(crh_f)"
-
- name[Group1]="Romania - Crimean Tatar (Turkish F)";
-};
-
-partial
-xkb_symbols "crh_alt" {
- include "tr(crh_alt)"
-
- name[Group1]="Romania - Crimean Tatar (Turkish Alt-Q)";
-};
-
-partial
-xkb_symbols "crh_dobruca1" {
- include "tr(crh)"
-
- name[Group1]="Romania - Crimean Tatar (Dobruca-1 Q)";
-
- key <AD05> { [ t, T, tcedilla, Tcedilla ] };
- key <AD10> { [ p, P, abreve, Abreve ] };
-
- key <AC04> { [ f, F, ibreve, Ibreve ] };
- key <AC07> { [ iacute, Iacute, j, J ] };
-
- key <AB07> { [ m, M, trademark, masculine ] };
-};
-
-partial
-xkb_symbols "crh_dobruca2" {
- include "ro(crh_dobruca1)"
-
- name[Group1]="Romania - Crimean Tatar (Dobruca-2 Q)";
-
- key <AC04> { [ f, F, iacute, Iacute ] };
- key <AC07> { [ ibreve, Ibreve, j, J ] };
-};
+// +// Complete set of Romanian keyboards as described in the new Romanian standard +// SR 13392:2004 adopted in December 2004 by ASRO, "Asociatia de Standardizare +// din Romania". +// +// The default mapping is the RO_US/Programmers layout because of the lack of +// Romanian hardware keyboards. The primary standard layout is implemented as +// the "std" variant. If you're determined to get cedillas as in ISO-8859-2 +// (and not commabelow accents as in ISO-8859-16) use the defined variants +// "cedilla" for the default layout or "std_cedilla" for the standard one. +// Pre-Vista MS compatible layout included (use the "winkeys" variant). +// +// Created by Cristian Gafton, <gafton@redhat.com> (C) 2000 +// Modified by Marius Andreiana, <mandreiana@yahoo.com> (C) 2001 +// Completed by Misu Moldovan, <dumol@gnome.ro> (C) 2001, 2004-2008. +// v 1.4 + + +partial default alphanumeric_keys +xkb_symbols "basic" { +// This RO_US/Programmers layout, although the secondary layout in the +// Romanian standard, has always been the "de facto" standard in the +// Linux/Unix world. It is implemented here as the default layout and it's +// fully compatible with an US keyboard (Euro on AltGr+5 doesn't count). + + include "us" + + name[Group1]="Romania"; + + key <AE01> { [ 1, exclam, dead_tilde ] }; + key <AE02> { [ 2, at, dead_caron ] }; + key <AE03> { [ 3, numbersign, dead_circumflex ] }; + key <AE04> { [ 4, dollar, dead_breve ] }; + key <AE05> { [ 5, percent, dead_abovering ] }; + key <AE06> { [ 6, asciicircum, dead_ogonek ] }; + key <AE07> { [ 7, ampersand, dead_grave ] }; + key <AE08> { [ 8, asterisk, dead_abovedot ] }; + key <AE09> { [ 9, parenleft, dead_acute ] }; + key <AE10> { [ 0, parenright, dead_doubleacute ] }; + key <AE11> { [ minus, underscore, dead_diaeresis, endash ] }; + key <AE12> { [ equal, plus, dead_cedilla, plusminus ] }; + key <AD01> { [ q, Q, acircumflex, Acircumflex ] }; + key <AD02> { [ w, W, ssharp ] }; + key <AD03> { [ e, E, EuroSign ] }; + key <AD05> { [ t, T, 0x100021b, 0x100021a ] }; + key <AD08> { [ i, I, icircumflex, Icircumflex ] }; + key <AD10> { [ p, P, section ] }; + key <AD11> { [ bracketleft, braceleft, doublelowquotemark ] }; + key <AD12> { [ bracketright, braceright, rightdoublequotemark ] }; + key <AC01> { [ a, A, abreve, Abreve ] }; + key <AC02> { [ s, S, 0x1000219, 0x1000218 ] }; + key <AC03> { [ d, D, dstroke, Dstroke ] }; + key <AC09> { [ l, L, lstroke, Lstroke ] }; + key <LSGT> { [ backslash, bar ] }; + key <AB03> { [ c, C, copyright ] }; + key <AB08> { [ comma, less, guillemotleft ] }; + key <AB09> { [ period, greater, guillemotright ] }; + + include "level3(ralt_switch)" +}; + +partial alphanumeric_keys +xkb_symbols "cedilla" { + // Variant of the basic layout with cedillas. + // Implements S and T with cedilllas as in ISO-8859-2. + // Included for compatibility reasons (this used to be the def variant). + + include "ro(basic)" + + name[Group1]="Romania - Cedilla"; + + key <AD05> { [ t, T, tcedilla, Tcedilla ] }; + key <AC02> { [ s, S, scedilla, Scedilla ] }; +}; + +partial alphanumeric_keys +xkb_symbols "std" { + // Primary layout in the new Romanian standard. + // Implemented here as a variant because of the lack of hardware + // Romanian keyboards and because of the predilection of Romanian + // X users towards the secondary layout from the new standard. + + include "us" + + name[Group1]="Romania - Standard"; + + key <TLDE> { [ doublelowquotemark, rightdoublequotemark, grave, asciitilde ] }; + key <AE01> { [ 1, exclam, dead_tilde ] }; + key <AE02> { [ 2, at, dead_caron ] }; + key <AE03> { [ 3, numbersign, dead_circumflex ] }; + key <AE04> { [ 4, dollar, dead_breve ] }; + key <AE05> { [ 5, percent, dead_abovering ] }; + key <AE06> { [ 6, asciicircum, dead_ogonek ] }; + key <AE07> { [ 7, ampersand, dead_grave ] }; + key <AE08> { [ 8, asterisk, dead_abovedot ] }; + key <AE09> { [ 9, parenleft, dead_acute ] }; + key <AE10> { [ 0, parenright, dead_doubleacute ] }; + key <AE11> { [ minus, underscore, dead_diaeresis, endash ] }; + key <AE12> { [ equal, plus, dead_cedilla, plusminus ] }; + key <AD03> { [ e, E, EuroSign ] }; + key <AD10> { [ p, P, section ] }; + key <AD11> { [ abreve, Abreve, bracketleft, braceleft ] }; + key <AD12> { [ icircumflex, Icircumflex, bracketright, braceright ] }; + key <BKSL> { [ acircumflex, Acircumflex, backslash, bar ] }; + key <AC02> { [ s, S, ssharp ] }; + key <AC03> { [ d, D, dstroke, Dstroke ] }; + key <AC09> { [ l, L, lstroke, Lstroke ] }; + key <AC10> { [ 0x1000219, 0x1000218, semicolon, colon ] }; + key <AC11> { [ 0x100021b, 0x100021a, apostrophe, quotedbl ] }; + key <LSGT> { [ backslash, bar ] }; + key <AB03> { [ c, C, copyright ] }; + key <AB08> { [ comma, semicolon, less, guillemotleft ] }; + key <AB09> { [ period, colon, greater, guillemotright ] }; + + key <KPDL> { [ KP_Delete, KP_Separator ] }; + + include "level3(ralt_switch)" +}; + + +partial alphanumeric_keys +xkb_symbols "std_cedilla" { + // Variant of the "std" layout with cedillas. + // Implements S and T with cedillas as in ISO-8859-2. + // Included for compatibility reasons. + + include "ro(std)" + + name[Group1]="Romania - Standard (Cedilla)"; + + key <AC10> { [ scedilla, Scedilla ] }; + key <AC11> { [ tcedilla, Tcedilla ] }; +}; + + +partial alphanumeric_keys +xkb_symbols "winkeys" { + // Describes the differences between a very simple US/ASCII + // keyboard and a very simple Romanian keybaord + // Created by Manfred Pohler, <Manfred.Pohler@t-online.de> (C) 2003 + + include "latin" + + name[Group1]="Romania - Winkeys"; + + // Alphanumeric section + key <TLDE> { [ bracketright, bracketleft ] }; + + key <AE01> { [ 1, exclam, asciitilde, asciitilde ] }; + key <AE02> { [ 2, quotedbl, at, at ] }; + key <AE03> { [ 3, numbersign, asciicircum,asciicircum ] }; + key <AE04> { [ 4, currency ] }; + key <AE05> { [ 5, percent, degree, degree ] }; + key <AE06> { [ 6, ampersand ] }; + key <AE07> { [ 7, slash, grave, grave ] }; + key <AE08> { [ 8, parenleft ] }; + key <AE09> { [ 9, parenright ] }; + key <AE10> { [ 0, equal ] }; + key <AE11> { [ plus, question ] }; + key <AE12> { [ apostrophe, asterisk ] }; + + key <AD01> { [ q, Q, backslash, backslash ] }; + key <AD02> { [ w, W, bar, bar ] }; + key <AD03> { [ e, E, EuroSign, EuroSign ] }; + key <AD05> { [ t, T ] }; + key <AD06> { [ z, Z ] }; + key <AD07> { [ u, U ] }; + key <AD08> { [ i, I ] }; + key <AD11> { [ abreve, Abreve, division, division ] }; + key <AD12> { [ icircumflex, Icircumflex, multiply, multiply ] }; + + key <AC04> { [ f, F ] }; + key <AC05> { [ g, G ] }; + key <AC10> { [ scedilla, Scedilla, dollar, dollar ] }; + key <AC11> { [ tcedilla, Tcedilla, ssharp, ssharp ] }; + + key <AB01> { [ y, Y ] }; + key <AB05> { [ b, B, braceleft, braceleft ] }; + key <AB06> { [ n, N, braceright, braceright ] }; + key <AB07> { [ m, M, section, section ] }; + key <AB08> { [ comma, semicolon, less, less ] }; + key <AB09> { [ period, colon, greater, greater ] }; + key <AB10> { [ minus, underscore ] }; + + key <BKSL> { [ acircumflex, Acircumflex ] }; + + // End alphanumeric section, begin "Keypad" + include "kpdl(comma)" + // End "Keypad" section + + include "level3(ralt_switch)" + +}; + +// Crimean Tatar (Crimean Turkish) layouts. +partial +xkb_symbols "crh_f" { + include "tr(crh_f)" + + name[Group1]="Romania - Crimean Tatar (Turkish F)"; +}; + +partial +xkb_symbols "crh_alt" { + include "tr(crh_alt)" + + name[Group1]="Romania - Crimean Tatar (Turkish Alt-Q)"; +}; + +partial +xkb_symbols "crh_dobruca1" { + include "tr(crh)" + + name[Group1]="Romania - Crimean Tatar (Dobruca-1 Q)"; + + key <AD05> { [ t, T, tcedilla, Tcedilla ] }; + key <AD10> { [ p, P, abreve, Abreve ] }; + + key <AC04> { [ f, F, ibreve, Ibreve ] }; + key <AC07> { [ iacute, Iacute, j, J ] }; + + key <AB07> { [ m, M, trademark, masculine ] }; +}; + +partial +xkb_symbols "crh_dobruca2" { + include "ro(crh_dobruca1)" + + name[Group1]="Romania - Crimean Tatar (Dobruca-2 Q)"; + + key <AC04> { [ f, F, iacute, Iacute ] }; + key <AC07> { [ ibreve, Ibreve, j, J ] }; +}; + +// EXTRAS: + +partial alphanumeric_keys +xkb_symbols "ergonomic" { + // This layout is optimized for fast touch-typing in Romanian on a + // US keyboard, and works by swapping out symbols infrequently used + // in written Romanian (q,w,y,k) in favor of native ones, thus reducing + // the need to use modifier keys. + // Created by Gabriel Somlo, <somlo@cmu.edu> (C) 2011 + + include "ro(basic)" + + name[Group1]="Romania - Ergonomic Touchtype"; + + key <AD01> { [ abreve, Abreve, q, Q ] }; + key <AD02> { [ 0x1000219, 0x1000218, w, W ] }; + key <AD06> { [ 0x100021b, 0x100021a, y, Y ] }; + key <AC01> { [ a, A, acircumflex, Acircumflex ] }; + key <AC08> { [ icircumflex, Icircumflex, k, K ] }; +}; + diff --git a/xorg-server/xkeyboard-config/symbols/rs b/xorg-server/xkeyboard-config/symbols/rs index 3929ff4ec..d4628852f 100644 --- a/xorg-server/xkeyboard-config/symbols/rs +++ b/xorg-server/xkeyboard-config/symbols/rs @@ -1,327 +1,345 @@ -// Bosnian, Croatian, Serbian and Slovenian XKB keyboard mapping
-// (derived from "Danube" D.2)
-//
-// Danube D.2 from 2003-05-12 is available at http://srpski.org/dunav/
-//
-// Original authors:
-// Danilo Segan (Данило Шеган) <danilo@kvota.net>
-// Chusslove Illich (Часлав Илић) <chaslav@sezampro.yu>
-//
-// Danilo Segan <danilo@kvota.net>:
-// - Modified for inclusion in XFree86
-// - Further modifications on 2005-08-18 to support Bosnian, Croatian
-// and Slovenian in xkeyboard-config
-//
-
-default partial alphanumeric_keys
-xkb_symbols "basic" {
-
- name[Group1]= "Serbia";
-
- include "rs(cyrlevel3)"
- include "rs(common)"
- include "rs(cyralpha)"
- include "level3(ralt_switch)"
-};
-
-
-partial alphanumeric_keys
-xkb_symbols "latin" {
-
- name[Group1]= "Serbia - Latin";
-
- include "latin(type3)"
- include "rs(latalpha)"
- include "rs(latlevel3)"
- include "rs(common)"
- include "level3(ralt_switch)"
-};
-
-
-partial alphanumeric_keys
-xkb_symbols "yz" {
- // Cyrillic_zhe and Cyrillic_ze swapped.
-
- name[Group1]= "Serbia - Z and ZHE swapped";
-
- include "rs(basic)"
-
- key <AD06> { [ Cyrillic_zhe, Cyrillic_ZHE, any,any ] }; // y
- key <AB01> { [ Cyrillic_ze, Cyrillic_ZE, any,any ] }; // z
-};
-
-partial hidden alphanumeric_keys
-xkb_symbols "common" {
- // "Common" keys: keys which are same for both latin and cyrillic keyboards
-
- key.type[Group1] = "FOUR_LEVEL";
-
- key <TLDE> { [ quoteleft, asciitilde, any,any ] }; //
- key <AE01> { [ 1, exclam, any,any ] }; //
- key <AE02> { [ 2, quotedbl, any,any ] }; //
- key <AE03> { [ 3, numbersign, any,any ] }; //
- key <AE04> { [ 4, dollar, any,any ] }; //
- key <AE05> { [ 5, percent, any,any ] }; //
- key <AE06> { [ 6, ampersand, any,any ] }; //
- key <AE07> { [ 7, slash, any,any ] }; //
- key <AE08> { [ 8, parenleft, any,any ] }; //
- key <AE09> { [ 9, parenright, any,any ] }; //
- key <AE10> { [ 0, equal, any,any ] }; //
- key <AE11> { [ apostrophe, question, any,any ] }; //
- key <AE12> { [ plus, asterisk, any,any ] }; //
-
- key <AB08> { [ comma, semicolon, any,any ] }; //
- key <AB09> { [ period, colon, any,any ] }; //
- key <AB10> { [ minus, underscore, any,any ] }; //
-
- include "kpdl(comma)"
-};
-
-partial hidden alphanumeric_keys
-xkb_symbols "cyralpha" {
-
- key.type[Group1] = "FOUR_LEVEL_ALPHABETIC";
-
- key <AD01> { [ Cyrillic_lje, Cyrillic_LJE, any,any ] }; // q
- key <AD02> { [ Cyrillic_nje, Cyrillic_NJE, any,any ] }; // w
- key <AD03> { [ Cyrillic_ie, Cyrillic_IE, any,any ] }; // e
- key <AD04> { [ Cyrillic_er, Cyrillic_ER, any,any ] }; // r
- key <AD05> { [ Cyrillic_te, Cyrillic_TE, any,any ] }; // t
- key <AD06> { [ Cyrillic_ze, Cyrillic_ZE, any,any ] }; // y
- key <AD07> { [ Cyrillic_u, Cyrillic_U, any,any ] }; // u
- key <AD08> { [ Cyrillic_i, Cyrillic_I, any,any ] }; // i
- key <AD09> { [ Cyrillic_o, Cyrillic_O, any,any ] }; // o
- key <AD10> { [ Cyrillic_pe, Cyrillic_PE, any,any ] }; // p
- key <AD11> { [ Cyrillic_sha, Cyrillic_SHA, any,any ] }; // [ {
- key <AD12> { [ Serbian_dje, Serbian_DJE, any,any ] }; // ] }
-
- key <AC01> { [ Cyrillic_a, Cyrillic_A, any,any ] }; // a
- key <AC02> { [ Cyrillic_es, Cyrillic_ES, any,any ] }; // s
- key <AC03> { [ Cyrillic_de, Cyrillic_DE, any,any ] }; // d
- key <AC04> { [ Cyrillic_ef, Cyrillic_EF, any,any ] }; // f
- key <AC05> { [ Cyrillic_ghe, Cyrillic_GHE, any,any ] }; // g
- key <AC06> { [ Cyrillic_ha, Cyrillic_HA, any,any ] }; // h
- key <AC07> { [ Cyrillic_je, Cyrillic_JE, any,any ] }; // j
- key <AC08> { [ Cyrillic_ka, Cyrillic_KA, any,any ] }; // k
- key <AC09> { [ Cyrillic_el, Cyrillic_EL, any,any ] }; // l
- key <AC10> { [ Cyrillic_che, Cyrillic_CHE, any,any ] }; // ; :
- key <AC11> { [ Serbian_tshe, Serbian_TSHE, any,any ] }; // ' "
- key <BKSL> { [ Cyrillic_zhe, Cyrillic_ZHE, any,any ] }; // \ |
-
- key <AB01> { [ Cyrillic_zhe, Cyrillic_ZHE, any,any ] }; // z
- key <AB02> { [ Cyrillic_dzhe, Cyrillic_DZHE, any,any ] }; // x
- key <AB03> { [ Cyrillic_tse, Cyrillic_TSE, any,any ] }; // c
- key <AB04> { [ Cyrillic_ve, Cyrillic_VE, any,any ] }; // v
- key <AB05> { [ Cyrillic_be, Cyrillic_BE, any,any ] }; // b
- key <AB06> { [ Cyrillic_en, Cyrillic_EN, any,any ] }; // n
- key <AB07> { [ Cyrillic_em, Cyrillic_EM, any,any ] }; // m
-};
-
-
-partial hidden alphanumeric_keys
-xkb_symbols "latalpha" {
-
- key.type[Group1] = "FOUR_LEVEL_ALPHABETIC";
-
- key <AD11> { [ scaron, Scaron, any,any ] }; //
- key <AD12> { [ dstroke, Dstroke, any,any ] }; //
-
- key <AC10> { [ ccaron, Ccaron, any,any ] }; //
- key <AC11> { [ cacute, Cacute, any,any ] }; //
- key <BKSL> { [ zcaron, Zcaron, any,any ] }; //
-
-};
-
-partial hidden alphanumeric_keys
-xkb_symbols "twoletter" {
- // These are letters which are written in latin transcription with two-characters.
-
- key <AD01> { type[Group1] = "SEPARATE_CAPS_AND_SHIFT_ALPHABETIC",
- [ U1C9, U1C8, any, U1C7 ] }; // q
- key <AD02> { type[Group1] = "SEPARATE_CAPS_AND_SHIFT_ALPHABETIC",
- [ U1CC, U1CB, any, U1CA ] }; // w
- key <AB02> { type[Group1] = "SEPARATE_CAPS_AND_SHIFT_ALPHABETIC",
- [ U1C6, U1C5, any, U1C4 ] }; // x
-
- // Also replace letter Y with Zcaron, since Y is of no use any longer
- key <AB01> { [ zcaron, Zcaron, any,any ] }; //
-};
-
-partial hidden alphanumeric_keys
-xkb_symbols "latlevel3" {
- key <TLDE> { [ any,any, notsign, notsign ] }; // ` ~
- key <AE01> { [ any,any, dead_tilde, asciitilde ] }; // 1 !
- key <AE02> { [ any,any, dead_caron, caron ] }; // 2 @
- key <AE03> { [ any,any, dead_circumflex, asciicircum ] }; // 3 #
- key <AE04> { [ any,any, dead_breve, breve ] }; // 4 $
- key <AE05> { [ any,any, dead_abovering, degree ] }; // 5 %
- key <AE06> { [ any,any, dead_ogonek, ogonek ] }; // 6 ^
- key <AE07> { [ any,any, dead_grave, grave ] }; // 7 &
- key <AE08> { [ any,any, dead_abovedot, abovedot ] }; // 8 *
- key <AE09> { [ any,any, dead_acute, apostrophe ] }; // 9 (
- key <AE10> { [ any,any, dead_doubleacute, doubleacute ] }; // 0 )
- key <AE11> { [ any,any, dead_diaeresis, diaeresis ] }; // - _
- key <AE12> { [ any,any, dead_cedilla, cedilla ] }; // = +
-
- key <AD01> { [ any,any, backslash, Greek_OMEGA ] }; // q
- key <AD02> { [ any,any, bar, Lstroke ] }; // w
- key <AD03> { [ any,any, EuroSign, EuroSign ] }; // e
- key <AD04> { [ any,any, paragraph, registered ] }; // r
- key <AD05> { [ any,any, tslash, Tslash ] }; // t // ALPHABETIC
- key <AD06> { [ any,any, leftarrow, yen ] }; // y
- key <AD07> { [ any,any, downarrow, uparrow ] }; // u
- key <AD08> { [ any,any, rightarrow, idotless ] }; // i
- key <AD09> { [ any,any, oslash, Ooblique ] }; // o // ALPHABETIC
- key <AD10> { [ any,any, thorn, THORN ] }; // p // ALPHABETIC
- key <AD11> { [ any,any, division, dead_abovering ] }; // [
- key <AD12> { [ any,any, multiply, dead_macron ] }; // ]
-
- key <AC01> { [ any,any, ae, AE ] }; // a // ALPHABETIC
- key <AC02> { [ any,any, doublelowquotemark, guillemotright ] }; // s
- key <AC03> { [ any,any, leftdoublequotemark, guillemotleft ] }; // d
- key <AC04> { [ any,any, bracketleft, ordfeminine ] }; // f
- key <AC05> { [ any,any, bracketright, ENG ] }; // g
- key <AC06> { [ any,any, hstroke, Hstroke ] }; // h // ALPHABETIC
- key <AC07> { [ any,any, NoSymbol, NoSymbol ] }; // j
- key <AC08> { [ any,any, lstroke, ampersand ] }; // k
- key <AC09> { [ any,any, lstroke, Lstroke ] }; // l
- key <AC10> { [ any,any, dead_acute, dead_doubleacute ] }; // ;
- key <AC11> { [ any,any, ssharp, dead_caron ] }; // '
- key <BKSL> { [ any,any, currency, dead_breve ] }; // \
-
- key <AB01> { [ any,any, leftsinglequotemark, guillemotright ] }; // z
- key <AB02> { [ any,any, rightsinglequotemark,guillemotleft ] }; // x
- key <AB03> { [ any,any, cent, copyright ] }; // c
- key <AB04> { [ any,any, at, grave ] }; // v
- key <AB05> { [ any,any, braceleft, apostrophe ] }; // b
- key <AB06> { [ any,any, braceright, braceright ] }; // n
- key <AB07> { [ any,any, asciicircum, masculine ] }; // m
- key <AB08> { [ any,any, less, multiply ] }; // , <
- key <AB09> { [ any,any, greater, division ] }; // . >
- key <AB10> { [ any,any, emdash, endash ] }; // / ?
-
-};
-
-partial hidden alphanumeric_keys
-xkb_symbols "cyrlevel3" {
- key <TLDE> { [ any,any, degree, notsign ] }; // ` ~
- key <AE03> { [ any,any, dead_circumflex, NoSymbol ] }; // 3 #
- key <AE07> { [ any,any, dead_grave, NoSymbol ] }; // 7 &
- key <AE08> { [ any,any, dead_doublegrave, NoSymbol ] }; // 8 *
- key <AE09> { [ any,any, dead_acute, NoSymbol ] }; // 9 (
- key <AE10> { [ any,any, dead_invertedbreve, NoSymbol ] }; // 0 )
- key <AE11> { [ any,any, dead_macron, NoSymbol ] }; // - _
-
- key <AD01> { [ any,any, backslash, NoSymbol ] }; // q
- key <AD02> { [ any,any, bar, NoSymbol ] }; // w
- key <AD03> { [ any,any, EuroSign, sterling ] }; // e
- key <AD04> { [ any,any, paragraph, registered ] }; // r
- key <AD05> { [ any,any, ellipsis, NoSymbol ] }; // t // ALPHABETIC
- key <AD06> { [ any,any, leftarrow, yen ] }; // y
- key <AD07> { [ any,any, downarrow, uparrow ] }; // u
- key <AD08> { [ any,any, rightarrow, NoSymbol ] }; // i
- key <AD09> { [ any,any, section, NoSymbol ] }; // o // ALPHABETIC
- key <AD11> { [ any,any, division, NoSymbol ] }; // [
- key <AD12> { [ any,any, multiply, NoSymbol ] }; // ]
-
- key <AC02> { [ any,any, doublelowquotemark, guillemotright ] }; // s
- key <AC03> { [ any,any, leftdoublequotemark, guillemotleft ] }; // d
- key <AC04> { [ any,any, bracketleft, NoSymbol ] }; // f
- key <AC05> { [ any,any, bracketright, NoSymbol ] }; // g
- key <BKSL> { [ any,any, currency, NoSymbol ] }; // \
-
- key <AB01> { [ any,any, leftsinglequotemark, NoSymbol ] }; // z
- key <AB02> { [ any,any, rightsinglequotemark,NoSymbol ] }; // x
- key <AB03> { [ any,any, cent, copyright ] }; // c
- key <AB04> { [ any,any, at, NoSymbol ] }; // v
- key <AB05> { [ any,any, braceleft, NoSymbol ] }; // b
- key <AB06> { [ any,any, braceright, NoSymbol ] }; // n
- key <AB07> { [ any,any, asciicircum, NoSymbol ] }; // m
- key <AB08> { [ any,any, less, NoSymbol ] }; // , <
- key <AB09> { [ any,any, greater, NoSymbol ] }; // . >
- key <AB10> { [ any,any, emdash, endash ] }; // / ?
-};
-
-partial alphanumeric_keys
-xkb_symbols "latinunicode" {
- // This mapping supports the Unicode characters 0x1c4-0x1cc (dz, lj, and nj
- // as single character). You get the title form with AltGr+Shift.
-
- name[Group1]= "Serbia - Latin Unicode";
-
- include "rs(latin)"
- include "rs(twoletter)"
-};
-
-partial alphanumeric_keys
-xkb_symbols "latinyz" {
- // For those who insist on using "english-position" Z and Y.
-
- name[Group1]= "Serbia - Latin qwerty";
-
- include "rs(latin)"
-
- key <AD06> { [ y, Y, any,any ] }; // y
- key <AB01> { [ z, Z, any,any ] }; // z
-};
-
-partial alphanumeric_keys
-xkb_symbols "latinunicodeyz" {
- // Unicode, ZHE and Z swapped.
-
- name[Group1]= "Serbia - Latin Unicode qwerty";
-
- include "rs(latinunicode)"
-
- key <AD06> { [ zcaron, Zcaron, any,any ] }; // y
- key <AB01> { [ z, Z, any,any ] }; // z
-};
-
-xkb_symbols "alternatequotes" {
- // Another acceptable »pair of quotes« for Serbian
-
- name[Group1]= "Serbia - With guillemets";
-
- include "rs(basic)"
-
- key <AC02> { [ any,any, guillemotright, NoSymbol ] }; // s
- key <AC03> { [ any,any, guillemotleft, NoSymbol ] }; // d
-};
-
-xkb_symbols "latinalternatequotes" {
- // Another acceptable »pair of quotes« for Serbian
-
- name[Group1]= "Serbia - Latin with guillemets";
-
- include "rs(latin)"
-
- key <AC02> { [ any,any, guillemotright, NoSymbol ] }; // s
- key <AC03> { [ any,any, guillemotleft, NoSymbol ] }; // d
-};
-
-xkb_symbols "rue" {
- // Homophonic layout for Pannonian Rusyn (spoken mainly in Serbia and
- // Croatia by the Rusyn people), based on Ukrainian homophonic.
- // Author: Ljubomir J. Papuga (Любомир Я. Папуґа) <papuga.rs@gmail.com>
-
- name[Group1]= "Serbia - Pannonian Rusyn Homophonic";
-
- include "ua(homophonic)"
-
- key <TLDE> { [ grave, asciitilde ] };
- key <AE03> { [ 3, doublelowquotemark ] };
- key <AE04> { [ 4, rightdoublequotemark ] };
- key <AE07> { [ 7, EuroSign ] };
- key <AE11> { [ 0x002D, emdash ] };
- key <AE12> { [ equal, plus ] };
-
- key <AD02> { [ Ukrainian_ie, Ukrainian_IE ] };
- key <AD06> { [ Cyrillic_yu, Cyrillic_YU ] };
- key <AD08> { [ Cyrillic_i, Cyrillic_I ] };
- key <AD11> { [ Cyrillic_sha, Cyrillic_SHA ] };
- key <AD12> { [ Cyrillic_shcha, Cyrillic_SHCHA ] };
-
- key <LSGT> { [ Ukrainian_yi, Ukrainian_YI ] };
- key <AB08> { [ comma, semicolon ] };
- key <AB09> { [ period, colon ] };
-};
+// Bosnian, Croatian, Serbian and Slovenian XKB keyboard mapping +// (derived from "Danube" D.2) +// +// Danube D.2 from 2003-05-12 is available at http://srpski.org/dunav/ +// +// Original authors: +// Danilo Segan (Данило Шеган) <danilo@kvota.net> +// Chusslove Illich (Часлав Илић) <chaslav@sezampro.yu> +// +// Danilo Segan <danilo@kvota.net>: +// - Modified for inclusion in XFree86 +// - Further modifications on 2005-08-18 to support Bosnian, Croatian +// and Slovenian in xkeyboard-config +// + +default partial alphanumeric_keys +xkb_symbols "basic" { + + name[Group1]= "Serbia"; + + include "rs(cyrlevel3)" + include "rs(common)" + include "rs(cyralpha)" + include "level3(ralt_switch)" +}; + + +partial alphanumeric_keys +xkb_symbols "latin" { + + name[Group1]= "Serbia - Latin"; + + include "latin(type3)" + include "rs(latalpha)" + include "rs(latlevel3)" + include "rs(common)" + include "level3(ralt_switch)" +}; + + +partial alphanumeric_keys +xkb_symbols "yz" { + // Cyrillic_zhe and Cyrillic_ze swapped. + + name[Group1]= "Serbia - Z and ZHE swapped"; + + include "rs(basic)" + + key <AD06> { [ Cyrillic_zhe, Cyrillic_ZHE, any,any ] }; // y + key <AB01> { [ Cyrillic_ze, Cyrillic_ZE, any,any ] }; // z +}; + +partial hidden alphanumeric_keys +xkb_symbols "common" { + // "Common" keys: keys which are same for both latin and cyrillic keyboards + + key.type[Group1] = "FOUR_LEVEL"; + + key <TLDE> { [ quoteleft, asciitilde, any,any ] }; // + key <AE01> { [ 1, exclam, any,any ] }; // + key <AE02> { [ 2, quotedbl, any,any ] }; // + key <AE03> { [ 3, numbersign, any,any ] }; // + key <AE04> { [ 4, dollar, any,any ] }; // + key <AE05> { [ 5, percent, any,any ] }; // + key <AE06> { [ 6, ampersand, any,any ] }; // + key <AE07> { [ 7, slash, any,any ] }; // + key <AE08> { [ 8, parenleft, any,any ] }; // + key <AE09> { [ 9, parenright, any,any ] }; // + key <AE10> { [ 0, equal, any,any ] }; // + key <AE11> { [ apostrophe, question, any,any ] }; // + key <AE12> { [ plus, asterisk, any,any ] }; // + + key <AB08> { [ comma, semicolon, any,any ] }; // + key <AB09> { [ period, colon, any,any ] }; // + key <AB10> { [ minus, underscore, any,any ] }; // + + include "kpdl(comma)" +}; + +partial hidden alphanumeric_keys +xkb_symbols "cyralpha" { + + key.type[Group1] = "FOUR_LEVEL_ALPHABETIC"; + + key <AD01> { [ Cyrillic_lje, Cyrillic_LJE, any,any ] }; // q + key <AD02> { [ Cyrillic_nje, Cyrillic_NJE, any,any ] }; // w + key <AD03> { [ Cyrillic_ie, Cyrillic_IE, any,any ] }; // e + key <AD04> { [ Cyrillic_er, Cyrillic_ER, any,any ] }; // r + key <AD05> { [ Cyrillic_te, Cyrillic_TE, any,any ] }; // t + key <AD06> { [ Cyrillic_ze, Cyrillic_ZE, any,any ] }; // y + key <AD07> { [ Cyrillic_u, Cyrillic_U, any,any ] }; // u + key <AD08> { [ Cyrillic_i, Cyrillic_I, any,any ] }; // i + key <AD09> { [ Cyrillic_o, Cyrillic_O, any,any ] }; // o + key <AD10> { [ Cyrillic_pe, Cyrillic_PE, any,any ] }; // p + key <AD11> { [ Cyrillic_sha, Cyrillic_SHA, any,any ] }; // [ { + key <AD12> { [ Serbian_dje, Serbian_DJE, any,any ] }; // ] } + + key <AC01> { [ Cyrillic_a, Cyrillic_A, any,any ] }; // a + key <AC02> { [ Cyrillic_es, Cyrillic_ES, any,any ] }; // s + key <AC03> { [ Cyrillic_de, Cyrillic_DE, any,any ] }; // d + key <AC04> { [ Cyrillic_ef, Cyrillic_EF, any,any ] }; // f + key <AC05> { [ Cyrillic_ghe, Cyrillic_GHE, any,any ] }; // g + key <AC06> { [ Cyrillic_ha, Cyrillic_HA, any,any ] }; // h + key <AC07> { [ Cyrillic_je, Cyrillic_JE, any,any ] }; // j + key <AC08> { [ Cyrillic_ka, Cyrillic_KA, any,any ] }; // k + key <AC09> { [ Cyrillic_el, Cyrillic_EL, any,any ] }; // l + key <AC10> { [ Cyrillic_che, Cyrillic_CHE, any,any ] }; // ; : + key <AC11> { [ Serbian_tshe, Serbian_TSHE, any,any ] }; // ' " + key <BKSL> { [ Cyrillic_zhe, Cyrillic_ZHE, any,any ] }; // \ | + + key <AB01> { [ Cyrillic_zhe, Cyrillic_ZHE, any,any ] }; // z + key <AB02> { [ Cyrillic_dzhe, Cyrillic_DZHE, any,any ] }; // x + key <AB03> { [ Cyrillic_tse, Cyrillic_TSE, any,any ] }; // c + key <AB04> { [ Cyrillic_ve, Cyrillic_VE, any,any ] }; // v + key <AB05> { [ Cyrillic_be, Cyrillic_BE, any,any ] }; // b + key <AB06> { [ Cyrillic_en, Cyrillic_EN, any,any ] }; // n + key <AB07> { [ Cyrillic_em, Cyrillic_EM, any,any ] }; // m +}; + + +partial hidden alphanumeric_keys +xkb_symbols "latalpha" { + + key.type[Group1] = "FOUR_LEVEL_ALPHABETIC"; + + key <AD11> { [ scaron, Scaron, any,any ] }; // + key <AD12> { [ dstroke, Dstroke, any,any ] }; // + + key <AC10> { [ ccaron, Ccaron, any,any ] }; // + key <AC11> { [ cacute, Cacute, any,any ] }; // + key <BKSL> { [ zcaron, Zcaron, any,any ] }; // + +}; + +partial hidden alphanumeric_keys +xkb_symbols "twoletter" { + // These are letters which are written in latin transcription with two-characters. + + key <AD01> { type[Group1] = "SEPARATE_CAPS_AND_SHIFT_ALPHABETIC", + [ U1C9, U1C8, any, U1C7 ] }; // q + key <AD02> { type[Group1] = "SEPARATE_CAPS_AND_SHIFT_ALPHABETIC", + [ U1CC, U1CB, any, U1CA ] }; // w + key <AB02> { type[Group1] = "SEPARATE_CAPS_AND_SHIFT_ALPHABETIC", + [ U1C6, U1C5, any, U1C4 ] }; // x + + // Also replace letter Y with Zcaron, since Y is of no use any longer + key <AB01> { [ zcaron, Zcaron, any,any ] }; // +}; + +partial hidden alphanumeric_keys +xkb_symbols "latlevel3" { + key <TLDE> { [ any,any, notsign, notsign ] }; // ` ~ + key <AE01> { [ any,any, dead_tilde, asciitilde ] }; // 1 ! + key <AE02> { [ any,any, dead_caron, caron ] }; // 2 @ + key <AE03> { [ any,any, dead_circumflex, asciicircum ] }; // 3 # + key <AE04> { [ any,any, dead_breve, breve ] }; // 4 $ + key <AE05> { [ any,any, dead_abovering, degree ] }; // 5 % + key <AE06> { [ any,any, dead_ogonek, ogonek ] }; // 6 ^ + key <AE07> { [ any,any, dead_grave, grave ] }; // 7 & + key <AE08> { [ any,any, dead_abovedot, abovedot ] }; // 8 * + key <AE09> { [ any,any, dead_acute, apostrophe ] }; // 9 ( + key <AE10> { [ any,any, dead_doubleacute, doubleacute ] }; // 0 ) + key <AE11> { [ any,any, dead_diaeresis, diaeresis ] }; // - _ + key <AE12> { [ any,any, dead_cedilla, cedilla ] }; // = + + + key <AD01> { [ any,any, backslash, Greek_OMEGA ] }; // q + key <AD02> { [ any,any, bar, Lstroke ] }; // w + key <AD03> { [ any,any, EuroSign, EuroSign ] }; // e + key <AD04> { [ any,any, paragraph, registered ] }; // r + key <AD05> { [ any,any, tslash, Tslash ] }; // t // ALPHABETIC + key <AD06> { [ any,any, leftarrow, yen ] }; // y + key <AD07> { [ any,any, downarrow, uparrow ] }; // u + key <AD08> { [ any,any, rightarrow, idotless ] }; // i + key <AD09> { [ any,any, oslash, Ooblique ] }; // o // ALPHABETIC + key <AD10> { [ any,any, thorn, THORN ] }; // p // ALPHABETIC + key <AD11> { [ any,any, division, dead_abovering ] }; // [ + key <AD12> { [ any,any, multiply, dead_macron ] }; // ] + + key <AC01> { [ any,any, ae, AE ] }; // a // ALPHABETIC + key <AC02> { [ any,any, doublelowquotemark, guillemotright ] }; // s + key <AC03> { [ any,any, leftdoublequotemark, guillemotleft ] }; // d + key <AC04> { [ any,any, bracketleft, ordfeminine ] }; // f + key <AC05> { [ any,any, bracketright, ENG ] }; // g + key <AC06> { [ any,any, hstroke, Hstroke ] }; // h // ALPHABETIC + key <AC07> { [ any,any, NoSymbol, NoSymbol ] }; // j + key <AC08> { [ any,any, lstroke, ampersand ] }; // k + key <AC09> { [ any,any, lstroke, Lstroke ] }; // l + key <AC10> { [ any,any, dead_acute, dead_doubleacute ] }; // ; + key <AC11> { [ any,any, ssharp, dead_caron ] }; // ' + key <BKSL> { [ any,any, currency, dead_breve ] }; // \ + + key <AB01> { [ any,any, leftsinglequotemark, guillemotright ] }; // z + key <AB02> { [ any,any, rightsinglequotemark,guillemotleft ] }; // x + key <AB03> { [ any,any, cent, copyright ] }; // c + key <AB04> { [ any,any, at, grave ] }; // v + key <AB05> { [ any,any, braceleft, apostrophe ] }; // b + key <AB06> { [ any,any, braceright, braceright ] }; // n + key <AB07> { [ any,any, asciicircum, masculine ] }; // m + key <AB08> { [ any,any, less, multiply ] }; // , < + key <AB09> { [ any,any, greater, division ] }; // . > + key <AB10> { [ any,any, emdash, endash ] }; // / ? + +}; + +partial hidden alphanumeric_keys +xkb_symbols "cyrlevel3" { + key <TLDE> { [ any,any, degree, notsign ] }; // ` ~ + key <AE03> { [ any,any, dead_circumflex, NoSymbol ] }; // 3 # + key <AE07> { [ any,any, dead_grave, NoSymbol ] }; // 7 & + key <AE08> { [ any,any, dead_doublegrave, NoSymbol ] }; // 8 * + key <AE09> { [ any,any, dead_acute, NoSymbol ] }; // 9 ( + key <AE10> { [ any,any, dead_invertedbreve, NoSymbol ] }; // 0 ) + key <AE11> { [ any,any, dead_macron, NoSymbol ] }; // - _ + + key <AD01> { [ any,any, backslash, NoSymbol ] }; // q + key <AD02> { [ any,any, bar, NoSymbol ] }; // w + key <AD03> { [ any,any, EuroSign, sterling ] }; // e + key <AD04> { [ any,any, paragraph, registered ] }; // r + key <AD05> { [ any,any, ellipsis, NoSymbol ] }; // t // ALPHABETIC + key <AD06> { [ any,any, leftarrow, yen ] }; // y + key <AD07> { [ any,any, downarrow, uparrow ] }; // u + key <AD08> { [ any,any, rightarrow, NoSymbol ] }; // i + key <AD09> { [ any,any, section, NoSymbol ] }; // o // ALPHABETIC + key <AD11> { [ any,any, division, NoSymbol ] }; // [ + key <AD12> { [ any,any, multiply, NoSymbol ] }; // ] + + key <AC02> { [ any,any, doublelowquotemark, guillemotright ] }; // s + key <AC03> { [ any,any, leftdoublequotemark, guillemotleft ] }; // d + key <AC04> { [ any,any, bracketleft, NoSymbol ] }; // f + key <AC05> { [ any,any, bracketright, NoSymbol ] }; // g + key <BKSL> { [ any,any, currency, NoSymbol ] }; // \ + + key <AB01> { [ any,any, leftsinglequotemark, NoSymbol ] }; // z + key <AB02> { [ any,any, rightsinglequotemark,NoSymbol ] }; // x + key <AB03> { [ any,any, cent, copyright ] }; // c + key <AB04> { [ any,any, at, NoSymbol ] }; // v + key <AB05> { [ any,any, braceleft, NoSymbol ] }; // b + key <AB06> { [ any,any, braceright, NoSymbol ] }; // n + key <AB07> { [ any,any, asciicircum, NoSymbol ] }; // m + key <AB08> { [ any,any, less, NoSymbol ] }; // , < + key <AB09> { [ any,any, greater, NoSymbol ] }; // . > + key <AB10> { [ any,any, emdash, endash ] }; // / ? +}; + +partial alphanumeric_keys +xkb_symbols "latinunicode" { + // This mapping supports the Unicode characters 0x1c4-0x1cc (dz, lj, and nj + // as single character). You get the title form with AltGr+Shift. + + name[Group1]= "Serbia - Latin Unicode"; + + include "rs(latin)" + include "rs(twoletter)" +}; + +partial alphanumeric_keys +xkb_symbols "latinyz" { + // For those who insist on using "english-position" Z and Y. + + name[Group1]= "Serbia - Latin qwerty"; + + include "rs(latin)" + + key <AD06> { [ y, Y, any,any ] }; // y + key <AB01> { [ z, Z, any,any ] }; // z +}; + +partial alphanumeric_keys +xkb_symbols "latinunicodeyz" { + // Unicode, ZHE and Z swapped. + + name[Group1]= "Serbia - Latin Unicode qwerty"; + + include "rs(latinunicode)" + + key <AD06> { [ zcaron, Zcaron, any,any ] }; // y + key <AB01> { [ z, Z, any,any ] }; // z +}; + +xkb_symbols "alternatequotes" { + // Another acceptable »pair of quotes« for Serbian + + name[Group1]= "Serbia - With guillemets"; + + include "rs(basic)" + + key <AC02> { [ any,any, guillemotright, NoSymbol ] }; // s + key <AC03> { [ any,any, guillemotleft, NoSymbol ] }; // d +}; + +xkb_symbols "latinalternatequotes" { + // Another acceptable »pair of quotes« for Serbian + + name[Group1]= "Serbia - Latin with guillemets"; + + include "rs(latin)" + + key <AC02> { [ any,any, guillemotright, NoSymbol ] }; // s + key <AC03> { [ any,any, guillemotleft, NoSymbol ] }; // d +}; + +xkb_symbols "rue" { + // Homophonic layout for Pannonian Rusyn (spoken mainly in Serbia and + // Croatia by the Rusyn people), based on Ukrainian homophonic. + // Author: Ljubomir J. Papuga (Любомир Я. Папуґа) <papuga.rs@gmail.com> + + name[Group1]= "Serbia - Pannonian Rusyn Homophonic"; + + include "ua(homophonic)" + + key <TLDE> { [ grave, asciitilde ] }; + key <AE03> { [ 3, doublelowquotemark ] }; + key <AE04> { [ 4, rightdoublequotemark ] }; + key <AE07> { [ 7, EuroSign ] }; + key <AE11> { [ 0x002D, emdash ] }; + key <AE12> { [ equal, plus ] }; + + key <AD02> { [ Ukrainian_ie, Ukrainian_IE ] }; + key <AD06> { [ Cyrillic_yu, Cyrillic_YU ] }; + key <AD08> { [ Cyrillic_i, Cyrillic_I ] }; + key <AD11> { [ Cyrillic_sha, Cyrillic_SHA ] }; + key <AD12> { [ Cyrillic_shcha, Cyrillic_SHCHA ] }; + + key <LSGT> { [ Ukrainian_yi, Ukrainian_YI ] }; + key <AB08> { [ comma, semicolon ] }; + key <AB09> { [ period, colon ] }; +}; + +// EXTRAS: + +xkb_symbols "combiningkeys" { + // Raw combining characters instead of dead keys, + // especially good for post-accenting texts. + + name[Group1]= "Serbia - Combining accents instead of dead keys"; + + include "rs(basic)" + + key <AE03> { [ any,any, U0302, dead_circumflex ] }; // 3, U0302 = COMBINING CIRCUMFLEX ACCENT + key <AE07> { [ any,any, U0300, NoSymbol ] }; // 7, U0300 = COMBINING GRAVE ACCENT + key <AE08> { [ any,any, U030F, NoSymbol ] }; // 8, U030F = COMBINING DOUBLE GRAVE ACCENT + key <AE09> { [ any,any, U0301, NoSymbol ] }; // 9, U0301 = COMBINING ACUTE ACCENT + key <AE10> { [ any,any, U0311, NoSymbol ] }; // 0, U0311 = COMBINING INVERTED BREVE + key <AE11> { [ any,any, U0304, NoSymbol ] }; // -, U0304 = COMBINING MACRON +}; diff --git a/xorg-server/xkeyboard-config/symbols/ru b/xorg-server/xkeyboard-config/symbols/ru index 9cc7683dd..79323ca89 100644 --- a/xorg-server/xkeyboard-config/symbols/ru +++ b/xorg-server/xkeyboard-config/symbols/ru @@ -1,527 +1,588 @@ -// based on
-// russian standard keyboard
-// AEN <aen@logic.ru>
-// 2001/12/23 by Leon Kanter <leon@blackcatlinux.com>
-// 2005/12/09 Valery Inozemtsev <shrek@altlinux.ru>
-
-// Windows layout
-partial default alphanumeric_keys
-xkb_symbols "winkeys" {
- include "ru(common)"
-
- name[Group1]= "Russia";
-
- key <AE03> { [ 3, numerosign ] };
- key <AE04> { [ 4, semicolon ] };
- key <AE05> { [ 5, percent ] };
- key <AE06> { [ 6, colon ] };
- key <AE07> { [ 7, question ] };
- key <AE08> { [ 8, asterisk ] };
-
- key <AB10> { [ period, comma ] };
- key <BKSL> { [ backslash, slash ] };
-};
-
-partial hidden alphanumeric_keys
-xkb_symbols "common" {
-
- key <AE01> { [ 1, exclam ] };
- key <AE02> { [ 2, quotedbl ] };
- key <AE03> { [ 3, numbersign ] };
- key <AE04> { [ 4, asterisk ] };
- key <AE05> { [ 5, colon ] };
- key <AE06> { [ 6, comma ] };
- key <AE07> { [ 7, period ] };
- key <AE08> { [ 8, semicolon ] };
- key <AE09> { [ 9, parenleft ] };
- key <AE10> { [ 0, parenright ] };
- key <AE11> { [ minus, underscore ] };
- key <AE12> { [ equal, plus ] };
- key <BKSL> { [ backslash, bar ] };
- key <AB10> { [ slash, question ] };
- key <LSGT> { [ slash, bar ] };
-
- key <TLDE> { [ Cyrillic_io, Cyrillic_IO ] };
- key <AD01> { [ Cyrillic_shorti, Cyrillic_SHORTI ] };
- key <AD02> { [ Cyrillic_tse, Cyrillic_TSE ] };
- key <AD03> { [ Cyrillic_u, Cyrillic_U ] };
- key <AD04> { [ Cyrillic_ka, Cyrillic_KA ] };
- key <AD05> { [ Cyrillic_ie, Cyrillic_IE ] };
- key <AD06> { [ Cyrillic_en, Cyrillic_EN ] };
- key <AD07> { [ Cyrillic_ghe, Cyrillic_GHE ] };
- key <AD08> { [ Cyrillic_sha, Cyrillic_SHA ] };
- key <AD09> { [ Cyrillic_shcha, Cyrillic_SHCHA ] };
- key <AD10> { [ Cyrillic_ze, Cyrillic_ZE ] };
- key <AD11> { [ Cyrillic_ha, Cyrillic_HA ] };
- key <AD12> { [Cyrillic_hardsign,Cyrillic_HARDSIGN ] };
- key <AC01> { [ Cyrillic_ef, Cyrillic_EF ] };
- key <AC02> { [ Cyrillic_yeru, Cyrillic_YERU ] };
- key <AC03> { [ Cyrillic_ve, Cyrillic_VE ] };
- key <AC04> { [ Cyrillic_a, Cyrillic_A ] };
- key <AC05> { [ Cyrillic_pe, Cyrillic_PE ] };
- key <AC06> { [ Cyrillic_er, Cyrillic_ER ] };
- key <AC07> { [ Cyrillic_o, Cyrillic_O ] };
- key <AC08> { [ Cyrillic_el, Cyrillic_EL ] };
- key <AC09> { [ Cyrillic_de, Cyrillic_DE ] };
- key <AC10> { [ Cyrillic_zhe, Cyrillic_ZHE ] };
- key <AC11> { [ Cyrillic_e, Cyrillic_E ] };
- key <AB01> { [ Cyrillic_ya, Cyrillic_YA ] };
- key <AB02> { [ Cyrillic_che, Cyrillic_CHE ] };
- key <AB03> { [ Cyrillic_es, Cyrillic_ES ] };
- key <AB04> { [ Cyrillic_em, Cyrillic_EM ] };
- key <AB05> { [ Cyrillic_i, Cyrillic_I ] };
- key <AB06> { [ Cyrillic_te, Cyrillic_TE ] };
- key <AB07> { [Cyrillic_softsign,Cyrillic_SOFTSIGN ] };
- key <AB08> { [ Cyrillic_be, Cyrillic_BE ] };
- key <AB09> { [ Cyrillic_yu, Cyrillic_YU ] };
-
- key.type[group1]="TWO_LEVEL";
-
- include "kpdl(comma)"
-};
-
-partial alphanumeric_keys
-xkb_symbols "legacy" {
- include "ru(common)"
-
- name[Group1]= "Russia - Legacy";
-};
-
-partial alphanumeric_keys
-xkb_symbols "olpc" {
-
- include "ru(common)"
-
- key <TLDE> { [ 0x01000451, 0x01000401, grave ] }; // Ñ‘, Ð
- key <AE03> { [ 3, numbersign, 0x01002116 ] }; // â„–
- key <AE04> { [ 4, dollar, semicolon ] };
- key <AE06> { [ 6, asciicircum, colon ] };
- key <AE07> { [ 7, ampersand ] };
- key <AE09> { [ 9, parenleft, acute ] };
- key <AC12> { [ backslash, bar, slash ] };
-
- include "group(olpc)"
-};
-
-partial alphanumeric_keys
-xkb_symbols "typewriter" {
- include "ru(common)"
- name[Group1]= "Russia - Typewriter";
- key <TLDE> { [ bar, plus ] };
- key <AE01> { [ numerosign, 1 ] };
- key <AE02> { [ minus, 2 ] };
- key <AE03> { [ slash, 3 ] };
- key <AE04> { [ quotedbl, 4 ] };
- key <AE05> { [ colon, 5 ] };
- key <AE06> { [ comma, 6 ] };
- key <AE07> { [ period, 7 ] };
- key <AE08> { [ underscore, 8 ] };
- key <AE09> { [ question, 9 ] };
- key <AE10> { [ percent, 0 ] };
- key <AE11> { [ exclam, equal ] };
- key <AE12> { [ semicolon, backslash ] };
-
- key <BKSL> { [ parenright, parenleft ] };
-
- key <AD12> { [Cyrillic_hardsign,Cyrillic_HARDSIGN ] };
- key <AB10> { [ Cyrillic_io, Cyrillic_IO ] };
-};
-
-partial alphanumeric_keys
-xkb_symbols "typewriter-legacy" {
- include "ru(common)"
- name[Group1]= "Russia - Typewriter, legacy";
- key <TLDE> { [ apostrophe, quotedbl ] };
- key <AE01> { [ exclam, 1 ] };
- key <AE02> { [ numerosign, 2 ] };
- key <AE03> { [ slash, 3 ] };
- key <AE04> { [ semicolon, 4 ] };
- key <AE05> { [ colon, 5 ] };
- key <AE06> { [ comma, 6 ] };
- key <AE07> { [ period, 7 ] };
- key <AE08> { [ underscore, 8 ] };
- key <AE09> { [ question, 9 ] };
- key <AE10> { [ percent, 0 ] };
- key <BKSL> { [ parenleft, parenright ] };
-
- key <AD12> { [Cyrillic_hardsign,Cyrillic_HARDSIGN ] };
- key <AB10> { [ Cyrillic_io, Cyrillic_IO ] };
-};
-
-partial alphanumeric_keys
-xkb_symbols "phonetic" {
-
- name[Group1]= "Russia - Phonetic";
-
- key <AE01> { [ 1, exclam ] };
- key <AE02> { [ 2, at ] };
- key <AE03> { [ 3, Cyrillic_io ] };
- key <AE04> { [ 4, Cyrillic_IO ] };
- key <AE05> { [ 5, Cyrillic_hardsign ] };
- key <AE06> { [ 6, Cyrillic_HARDSIGN ] };
- key <AE07> { [ 7, ampersand ] };
- key <AE08> { [ 8, asterisk ] };
- key <AE09> { [ 9, parenleft ] };
- key <AE10> { [ 0, parenright ] };
- key <AE11> { [ minus, underscore ] };
-
- key <AB09> { [ period, greater ] };
- key <AB10> { [ slash, question ] };
- key <AB08> { [ comma, less ] };
- key <AC10> { [ semicolon, colon ] };
- key <AC11> { [ apostrophe, quotedbl ] };
- key <LSGT> { [ bar, brokenbar ] };
-
- key <TLDE> { [ Cyrillic_yu, Cyrillic_YU ] };
- key <LatQ> { [ Cyrillic_ya, Cyrillic_YA ] };
- key <LatZ> { [ Cyrillic_ze, Cyrillic_ZE ] };
- key <LatS> { [ Cyrillic_es, Cyrillic_ES ] };
- key <LatA> { [ Cyrillic_a, Cyrillic_A ] };
- key <LatW> { [ Cyrillic_ve, Cyrillic_VE ] };
- key <LatC> { [ Cyrillic_tse, Cyrillic_TSE ] };
- key <LatX> { [Cyrillic_softsign,Cyrillic_SOFTSIGN ] };
- key <LatD> { [ Cyrillic_de, Cyrillic_DE ] };
- key <LatE> { [ Cyrillic_ie, Cyrillic_IE ] };
- key <LatV> { [ Cyrillic_zhe, Cyrillic_ZHE ] };
- key <LatF> { [ Cyrillic_ef, Cyrillic_EF ] };
- key <LatT> { [ Cyrillic_te, Cyrillic_TE ] };
- key <LatR> { [ Cyrillic_er, Cyrillic_ER ] };
- key <LatN> { [ Cyrillic_en, Cyrillic_EN ] };
- key <LatB> { [ Cyrillic_be, Cyrillic_BE ] };
- key <LatH> { [ Cyrillic_ha, Cyrillic_HA ] };
- key <LatG> { [ Cyrillic_ghe, Cyrillic_GHE ] };
- key <LatY> { [ Cyrillic_yeru, Cyrillic_YERU ] };
- key <LatM> { [ Cyrillic_em, Cyrillic_EM ] };
- key <LatJ> { [ Cyrillic_shorti, Cyrillic_SHORTI ] };
- key <LatU> { [ Cyrillic_u, Cyrillic_U ] };
- key <LatK> { [ Cyrillic_ka, Cyrillic_KA ] };
- key <LatI> { [ Cyrillic_i, Cyrillic_I ] };
- key <LatO> { [ Cyrillic_o, Cyrillic_O ] };
- key <LatL> { [ Cyrillic_el, Cyrillic_EL ] };
- key <LatP> { [ Cyrillic_pe, Cyrillic_PE ] };
-
- key <AD11> { [ Cyrillic_sha, Cyrillic_SHA ] };
- key <AE12> { [ Cyrillic_che, Cyrillic_CHE ] };
- key <AD12> { [ Cyrillic_shcha, Cyrillic_SHCHA ] };
- key <BKSL> { [ Cyrillic_e, Cyrillic_E ] };
-};
-
-partial alphanumeric_keys
-xkb_symbols "phonetic_winkeys" {
-
- include "ru(phonetic)"
- name[Group1]= "Russia - Phonetic Winkeys";
-
- key <LatX> { [ Cyrillic_ha, Cyrillic_HA ] };
- key <LatH> { [ Cyrillic_che, Cyrillic_CHE ] };
- key <AE12> { [ Cyrillic_softsign, Cyrillic_softsign ] };
-
-};
-
-partial alphanumeric_keys
-xkb_symbols "tt" {
- include "ru(winkeys)"
- name[Group1]= "Russia - Tatar";
-
- key.type[group1]="FOUR_LEVEL";
-
- key <TLDE> { [ 0x010004bb, 0x010004ba,
- Cyrillic_io, Cyrillic_IO ] };
- key <AD02> { [ 0x010004e9, 0x010004e8,
- Cyrillic_tse, Cyrillic_TSE ] };
- key <AD09> { [ 0x010004d9, 0x010004d8,
- Cyrillic_shcha, Cyrillic_SHCHA ] };
- key <AD12> { [ 0x010004af, 0x010004ae,
- Cyrillic_hardsign,Cyrillic_HARDSIGN ] };
- key <AC10> { [ 0x010004a3, 0x010004a2,
- Cyrillic_zhe, Cyrillic_ZHE ] };
- key <AB07> { [ 0x01000497, 0x01000496,
- Cyrillic_softsign,Cyrillic_SOFTSIGN ] };
-
- include "level3(ralt_switch)"
-
-};
-
-partial alphanumeric_keys
-xkb_symbols "os_legacy" {
- include "ru(common)"
-
- name[Group1]= "Russia - Ossetian, legacy";
-
- key <TLDE> { [ Cyrillic_e, Cyrillic_E ] };
- key <AC07> { [ Cyrillic_o, Cyrillic_O, Cyrillic_io, Cyrillic_IO ] };
- key <AC11> { [ 0x010004D5, 0x010004D4 ] };
-};
-
-partial alphanumeric_keys
-xkb_symbols "os_winkeys" {
- include "ru(winkeys)"
-
- name[Group1]= "Russia - Ossetian, Winkeys";
-
- key <TLDE> { [ Cyrillic_e, Cyrillic_E ] };
- key <AC07> { [ Cyrillic_o, Cyrillic_O, Cyrillic_io, Cyrillic_IO ] };
- key <AC11> { [ 0x010004D5, 0x010004D4 ] };
-};
-
-partial alphanumeric_keys
-xkb_symbols "cv" {
- include "ru(winkeys)"
-
- name[Group1]= "Russia - Chuvash";
-
- key.type[group1]="FOUR_LEVEL";
-
- key <AD03> { [ Cyrillic_u, Cyrillic_U,
- 0x010004f3, 0x010004f2 ] };
- key <AD05> { [ Cyrillic_ie, Cyrillic_IE,
- 0x01000115, 0x01000114 ] };
- key <AC04> { [ Cyrillic_a, Cyrillic_A,
- abreve, Abreve ] };
- key <AB03> { [ Cyrillic_es, Cyrillic_ES,
- ccedilla, Ccedilla ] };
-
- include "level3(ralt_switch)"
-};
-
-partial alphanumeric_keys
-xkb_symbols "udm" {
- include "ru(winkeys)"
-
- name[Group1]= "Russia - Udmurt";
-
- key.type[group1]="FOUR_LEVEL";
-
- key <AE01> { [ question, exclam, 1, 1 ] };
- key <AE02> { [ parenleft, quotedbl, 2, 2 ] };
- key <AE03> { [ parenright, numerosign, 3, 3 ] };
- key <AE04> { [ colon, semicolon, 4, 4 ] };
- key <AE05> { [ asterisk, percent, 5, 5 ] };
- key <AE06> { [ 0x010004dd, 0x010004dc, 6, 6 ] };
- key <AE07> { [ 0x010004e7, 0x010004e6, 7, 7 ] };
- key <AE08> { [ 0x010004f5, 0x010004f4, 8, 8 ] };
- key <AE09> { [ 0x010004e5, 0x010004e4, 9, 9 ] };
- key <AE10> { [ 0x010004df, 0x010004de, 0, 0 ] };
-
- include "level3(ralt_switch)"
-};
-
-partial alphanumeric_keys
-xkb_symbols "cv_latin" {
- include "us(alt-intl)"
-
- name[Group1]= "Russia - Chuvash Latin";
-
- key.type[group1]="FOUR_LEVEL";
-
- key <AD01> { [ q, Q, 0x01000161, 0x01000160 ] };
- key <AD02> { [ w, W, udiaeresis, Udiaeresis ] };
- key <AD03> { [ e, E, 0x01000115, 0x01000114 ] };
- key <AD07> { [ u, U, udiaeresis, Udiaeresis ] };
- key <AD08> { [ i, I, 0x0100012d, 0x0100012c ] };
- key <AD09> { [ o, O, odiaeresis, Odiaeresis ] };
- key <AC01> { [ a, A, abreve, Abreve ] };
- key <AC02> { [ s, S, scedilla, Scedilla ] };
- key <AC05> { [ g, G, gbreve, Gbreve ] };
- key <AC07> { [ j, J, 0x01000131, 0x01000130 ] };
- key <AB03> { [ c, C, ccedilla, Ccedilla ] };
-
- include "level3(ralt_switch)"
-
-};
-
-// Komi language layout
-// based on
-// russian standard keyboard
-// Vlad Shakhov <lumpen.intellectual@gmail.com>
-// Last Changes 2007/10/23 by Vlad Shakhov <lumpen.intellectual@gmail.com>
-
-partial alphanumeric_keys
-xkb_symbols "kom" {
-
- include "ru(winkeys)"
-
- name[Group1]= "Russia - Komi";
-
- key.type[group1]="FOUR_LEVEL_ALPHABETIC";
-
-// cyrilllic o with diaeresis
- key <AC07> { [ Cyrillic_o, Cyrillic_O,
- U04E7, U04E6 ] };
-
-// hard I as additional key for soft Cyrillic_I
- key <AB05> { [ Cyrillic_i, Cyrillic_I,
- Ukrainian_i, Ukrainian_I ] };
-
- include "level3(ralt_switch)"
-};
-
-// Yakut language layout
-// 2008/04/23 Yakov Aleksandrov <bertjickty@yandex.ru>
-// 2008/04/23 Anatoliy Zhozhikov <jav@sitc.ru>
-// 2008/04/23 Aleksandr Varlamov
-partial alphanumeric_keys
-xkb_symbols "sah" {
-
- include "ru(winkeys)"
-
- name[Group1]= "Russia - Yakut";
-
- key.type[group1]="FOUR_LEVEL_ALPHABETIC";
-
- key <TLDE> { [ Cyrillic_io, Cyrillic_IO,
- U04EB, U04EA ] };
- key <AD01> { [ Cyrillic_shorti, Cyrillic_SHORTI,
- U048B, U048A ] };
- key <AD03> { [ Cyrillic_u, Cyrillic_U,
- Cyrillic_u_straight, Cyrillic_U_straight ] };
- key <AD04> { [ Cyrillic_ka, Cyrillic_KA,
- U04C4, U04C3 ] };
- key <AD06> { [ Cyrillic_en, Cyrillic_EN,
- U04A5, U04A4 ] };
- key <AD07> { [ Cyrillic_ghe, Cyrillic_GHE,
- U0495, U0494 ] };
- key <AD10> { [ Cyrillic_ze, Cyrillic_ZE,
- U04E1, U04E0 ] };
- key <AD11> { [ Cyrillic_ha, Cyrillic_HA,
- Cyrillic_shha, Cyrillic_SHHA ] };
- key <AC07> { [ Cyrillic_o, Cyrillic_O,
- Cyrillic_o_bar, Cyrillic_O_bar ] };
- key <AC10> { [ Cyrillic_zhe, Cyrillic_ZHE,
- U0461, U0460 ] };
- key <AB02> { [ Cyrillic_che, Cyrillic_CHE,
- Cyrillic_u_macron, Cyrillic_U_macron ] };
- key <AB04> { [ Cyrillic_em, Cyrillic_EM,
- U04C8, U04C7 ] };
- key <AB05> { [ Cyrillic_i, Cyrillic_I,
- Cyrillic_i_macron, Cyrillic_I_macron ] };
-
- include "level3(ralt_switch)"
-};
-
-
-//Kalmyk language layout
-//based on the Kalmyk language layout: http://soft.oyrat.org/
-//Nikolay Korneev <halmg@oyrat.org>
-//Toli Miron <mirontoli@gmail.com>
-
-partial alphanumeric_keys
-xkb_symbols "xal" {
- include "ru(winkeys)"
-
- name[Group1]= "Russia - Kalmyk";
-
- key.type[group1]="FOUR_LEVEL";
-
- key <AE01> { [ question, exclam, 1 ] };
- key <AE02> { [ numerosign, quotedbl, 2 ] };
- key <AE03> { [ Cyrillic_u_straight, Cyrillic_U_straight, 3 ] };
- key <AE04> { [ Cyrillic_schwa, Cyrillic_SCHWA, 4 ] };
- key <AE05> { [ asterisk, percent, 5 ] };
- key <AE06> { [ Cyrillic_en_descender, Cyrillic_EN_descender, 6 ] };
- key <AE07> { [ Cyrillic_o_bar, Cyrillic_O_bar, 7 ] };
- key <AE08> { [ Cyrillic_shha, Cyrillic_SHHA, 8 ] };
- key <AE09> { [ Cyrillic_zhe_descender, Cyrillic_ZHE_descender, 9 ] };
- key <AE10> { [ semicolon, colon, 0 ] };
-
- key <TLDE> { [ parenleft, parenright, Cyrillic_io, Cyrillic_IO ] };
-
- key <AD02> { [ Cyrillic_tse, Cyrillic_TSE, dollar ] };
- key <AD03> { [ Cyrillic_u, Cyrillic_U, EuroSign ] };
- key <AD04> { [ Cyrillic_ka, Cyrillic_KA, registered ] };
- key <AD05> { [ Cyrillic_ie, Cyrillic_IE, trademark ] };
- key <AD11> { [ Cyrillic_ha, Cyrillic_HA, bracketleft ] };
- key <AD12> { [ Cyrillic_hardsign, Cyrillic_HARDSIGN, bracketright ] };
- key <AC11> { [ Cyrillic_e, Cyrillic_E, apostrophe ] };
- key <AB03> { [ Cyrillic_es, Cyrillic_ES, copyright ] };
- key <AB08> { [ Cyrillic_be, Cyrillic_BE, less ] };
- key <AB09> { [ Cyrillic_yu, Cyrillic_YU, greater ] };
-
- include "level3(ralt_switch)"
-};
-
-partial alphanumeric_keys
-xkb_symbols "dos" {
-
- include "ru(common)"
-
- name[Group1]= "Russia - DOS";
-
- key <TLDE> { [ parenright, parenleft ] };
- key <AE04> { [ 4, currency ] };
- key <AE09> { [ 9, question ] };
- key <AE10> { [ 0, percent ] };
-
- key <AB10> { [ Cyrillic_io, Cyrillic_IO ] };
-};
-
-partial alphanumeric_keys
-xkb_symbols "bak" {
- include "ru(winkeys)"
-
- name[Group1]= "Russia - Bashkirian";
- key.type[group1]="FOUR_LEVEL";
-
- key <TLDE> { [ 0x010004d9, 0x010004d8, Cyrillic_io, Cyrillic_IO ] };
- key <AE01> { [ exclam, quotedbl, 1, 1 ] };
- key <AE02> { [ 0x010004e9, 0x010004e8, 2, 2 ] };
- key <AE03> { [ 0x010004a1, 0x010004a0, 3, 3 ] };
- key <AE04> { [ 0x01000493, 0x01000492, 4, 4 ] };
- key <AE05> { [ 0x010004ab, 0x010004aa, 5, 5 ] };
- key <AE06> { [ colon, semicolon, 6, 6 ] };
- key <AE07> { [ 0x01000499, 0x01000498, 7, 7 ] };
- key <AE08> { [ 0x010004bb, 0x010004ba, 8, 8 ] };
- key <AE09> { [ question, parenleft, 9, 9 ] };
- key <AE10> { [ numerosign, parenright, 0, 0 ] };
- key <AE11> { [ minus, percent, minus, underscore ]};
- key <AE12> { [ 0x010004af, 0x010004ae, equal, plus ]};
- key <BKSL> { [ 0x010004a3, 0x010004a2, backslash, slash ]};
-
- include "level3(ralt_switch)"
-};
-
-// Serbian charecters added as third level symbols to Russian keyboard layout.
-
-partial alphanumeric_keys
-xkb_symbols "srp" {
- include "ru(common)"
- include "level3(ralt_switch)"
-
- name[Group1]= "Russia - Serbian";
-
- key <AE03> { [ 3, numerosign ] };
- key <AE04> { [ 4, semicolon ] };
- key <AE05> { [ 5, percent ] };
- key <AE06> { [ 6, colon ] };
- key <AE07> { [ 7, question ] };
- key <AE08> { [ 8, asterisk ] };
- key <AB10> { [ period, comma ] };
- key <BKSL> { [ backslash, slash ] };
- key <AD01> { [ Cyrillic_shorti, Cyrillic_SHORTI, U458, U408 ] };
- key <AD06> { [ Cyrillic_en, Cyrillic_EN, U45A, U40A ] };
- key <AC08> { [ Cyrillic_el, Cyrillic_EL, U459, U409 ] };
- key <AC09> { [ Cyrillic_de, Cyrillic_DE, U45F, U40F ] };
- key <AC10> { [ Cyrillic_zhe, Cyrillic_ZHE, U452, U402 ] };
- key <AB02> { [ Cyrillic_che, Cyrillic_CHE, U45B, U40B ] };
-};
-
-// Mari language layout
-// based on Russian standard keyboard
-// http://www.marlamuter.ru/
-partial alphanumeric_keys
-xkb_symbols "chm" {
- include "ru(common)"
-
- name[Group1]= "Russia - Mari";
-
- key.type[group1]="FOUR_LEVEL_ALPHABETIC";
- key <AC04> { [ Cyrillic_a, Cyrillic_A, U04D3, U04D2 ] };
- key <AD03> { [ Cyrillic_u, Cyrillic_U, U04F1, U04F0 ] };
- key <AC02> { [ Cyrillic_ui, Cyrillic_UI, U04F9, U04F8 ] };
- key <AD06> { [ Cyrillic_n, Cyrillic_N, U04A5, U04A4 ] };
- key <AC11> { [ Cyrillic_e, Cyrillic_E, U04E9, U04E8 ] };
- key <AC10> { [ Cyrillic_zh, Cyrillic_ZH, U04EB, U04EA ] };
- key <AC01> { [ Cyrillic_f, Cyrillic_F, UF537, UF536 ] };
-
- include "level3(ralt_switch)"
-};
+// based on +// russian standard keyboard +// AEN <aen@logic.ru> +// 2001/12/23 by Leon Kanter <leon@blackcatlinux.com> +// 2005/12/09 Valery Inozemtsev <shrek@altlinux.ru> + +// Windows layout +partial default alphanumeric_keys +xkb_symbols "winkeys" { + include "ru(common)" + + name[Group1]= "Russia"; + + key <AE03> { [ 3, numerosign ] }; + key <AE04> { [ 4, semicolon ] }; + key <AE05> { [ 5, percent ] }; + key <AE06> { [ 6, colon ] }; + key <AE07> { [ 7, question ] }; + key <AE08> { [ 8, asterisk ] }; + + key <AB10> { [ period, comma ] }; + key <BKSL> { [ backslash, slash ] }; +}; + +partial hidden alphanumeric_keys +xkb_symbols "common" { + + key <AE01> { [ 1, exclam ] }; + key <AE02> { [ 2, quotedbl ] }; + key <AE03> { [ 3, numbersign ] }; + key <AE04> { [ 4, asterisk ] }; + key <AE05> { [ 5, colon ] }; + key <AE06> { [ 6, comma ] }; + key <AE07> { [ 7, period ] }; + key <AE08> { [ 8, semicolon ] }; + key <AE09> { [ 9, parenleft ] }; + key <AE10> { [ 0, parenright ] }; + key <AE11> { [ minus, underscore ] }; + key <AE12> { [ equal, plus ] }; + key <BKSL> { [ backslash, bar ] }; + key <AB10> { [ slash, question ] }; + key <LSGT> { [ slash, bar ] }; + + key <TLDE> { [ Cyrillic_io, Cyrillic_IO ] }; + key <AD01> { [ Cyrillic_shorti, Cyrillic_SHORTI ] }; + key <AD02> { [ Cyrillic_tse, Cyrillic_TSE ] }; + key <AD03> { [ Cyrillic_u, Cyrillic_U ] }; + key <AD04> { [ Cyrillic_ka, Cyrillic_KA ] }; + key <AD05> { [ Cyrillic_ie, Cyrillic_IE ] }; + key <AD06> { [ Cyrillic_en, Cyrillic_EN ] }; + key <AD07> { [ Cyrillic_ghe, Cyrillic_GHE ] }; + key <AD08> { [ Cyrillic_sha, Cyrillic_SHA ] }; + key <AD09> { [ Cyrillic_shcha, Cyrillic_SHCHA ] }; + key <AD10> { [ Cyrillic_ze, Cyrillic_ZE ] }; + key <AD11> { [ Cyrillic_ha, Cyrillic_HA ] }; + key <AD12> { [Cyrillic_hardsign,Cyrillic_HARDSIGN ] }; + key <AC01> { [ Cyrillic_ef, Cyrillic_EF ] }; + key <AC02> { [ Cyrillic_yeru, Cyrillic_YERU ] }; + key <AC03> { [ Cyrillic_ve, Cyrillic_VE ] }; + key <AC04> { [ Cyrillic_a, Cyrillic_A ] }; + key <AC05> { [ Cyrillic_pe, Cyrillic_PE ] }; + key <AC06> { [ Cyrillic_er, Cyrillic_ER ] }; + key <AC07> { [ Cyrillic_o, Cyrillic_O ] }; + key <AC08> { [ Cyrillic_el, Cyrillic_EL ] }; + key <AC09> { [ Cyrillic_de, Cyrillic_DE ] }; + key <AC10> { [ Cyrillic_zhe, Cyrillic_ZHE ] }; + key <AC11> { [ Cyrillic_e, Cyrillic_E ] }; + key <AB01> { [ Cyrillic_ya, Cyrillic_YA ] }; + key <AB02> { [ Cyrillic_che, Cyrillic_CHE ] }; + key <AB03> { [ Cyrillic_es, Cyrillic_ES ] }; + key <AB04> { [ Cyrillic_em, Cyrillic_EM ] }; + key <AB05> { [ Cyrillic_i, Cyrillic_I ] }; + key <AB06> { [ Cyrillic_te, Cyrillic_TE ] }; + key <AB07> { [Cyrillic_softsign,Cyrillic_SOFTSIGN ] }; + key <AB08> { [ Cyrillic_be, Cyrillic_BE ] }; + key <AB09> { [ Cyrillic_yu, Cyrillic_YU ] }; + + key.type[group1]="TWO_LEVEL"; + + include "kpdl(comma)" +}; + +partial alphanumeric_keys +xkb_symbols "legacy" { + include "ru(common)" + + name[Group1]= "Russia - Legacy"; +}; + +partial alphanumeric_keys +xkb_symbols "olpc" { + + include "ru(common)" + + key <TLDE> { [ 0x01000451, 0x01000401, grave ] }; // Ñ‘, Ð + key <AE03> { [ 3, numbersign, 0x01002116 ] }; // â„– + key <AE04> { [ 4, dollar, semicolon ] }; + key <AE06> { [ 6, asciicircum, colon ] }; + key <AE07> { [ 7, ampersand ] }; + key <AE09> { [ 9, parenleft, acute ] }; + key <AC12> { [ backslash, bar, slash ] }; + + include "group(olpc)" +}; + +partial alphanumeric_keys +xkb_symbols "typewriter" { + include "ru(common)" + name[Group1]= "Russia - Typewriter"; + key <TLDE> { [ bar, plus ] }; + key <AE01> { [ numerosign, 1 ] }; + key <AE02> { [ minus, 2 ] }; + key <AE03> { [ slash, 3 ] }; + key <AE04> { [ quotedbl, 4 ] }; + key <AE05> { [ colon, 5 ] }; + key <AE06> { [ comma, 6 ] }; + key <AE07> { [ period, 7 ] }; + key <AE08> { [ underscore, 8 ] }; + key <AE09> { [ question, 9 ] }; + key <AE10> { [ percent, 0 ] }; + key <AE11> { [ exclam, equal ] }; + key <AE12> { [ semicolon, backslash ] }; + + key <BKSL> { [ parenright, parenleft ] }; + + key <AD12> { [Cyrillic_hardsign,Cyrillic_HARDSIGN ] }; + key <AB10> { [ Cyrillic_io, Cyrillic_IO ] }; +}; + +partial alphanumeric_keys +xkb_symbols "typewriter-legacy" { + include "ru(common)" + name[Group1]= "Russia - Typewriter, legacy"; + key <TLDE> { [ apostrophe, quotedbl ] }; + key <AE01> { [ exclam, 1 ] }; + key <AE02> { [ numerosign, 2 ] }; + key <AE03> { [ slash, 3 ] }; + key <AE04> { [ semicolon, 4 ] }; + key <AE05> { [ colon, 5 ] }; + key <AE06> { [ comma, 6 ] }; + key <AE07> { [ period, 7 ] }; + key <AE08> { [ underscore, 8 ] }; + key <AE09> { [ question, 9 ] }; + key <AE10> { [ percent, 0 ] }; + key <BKSL> { [ parenleft, parenright ] }; + + key <AD12> { [Cyrillic_hardsign,Cyrillic_HARDSIGN ] }; + key <AB10> { [ Cyrillic_io, Cyrillic_IO ] }; +}; + +partial alphanumeric_keys +xkb_symbols "phonetic" { + + name[Group1]= "Russia - Phonetic"; + + key <AE01> { [ 1, exclam ] }; + key <AE02> { [ 2, at ] }; + key <AE03> { [ 3, Cyrillic_io ] }; + key <AE04> { [ 4, Cyrillic_IO ] }; + key <AE05> { [ 5, Cyrillic_hardsign ] }; + key <AE06> { [ 6, Cyrillic_HARDSIGN ] }; + key <AE07> { [ 7, ampersand ] }; + key <AE08> { [ 8, asterisk ] }; + key <AE09> { [ 9, parenleft ] }; + key <AE10> { [ 0, parenright ] }; + key <AE11> { [ minus, underscore ] }; + + key <AB09> { [ period, greater ] }; + key <AB10> { [ slash, question ] }; + key <AB08> { [ comma, less ] }; + key <AC10> { [ semicolon, colon ] }; + key <AC11> { [ apostrophe, quotedbl ] }; + key <LSGT> { [ bar, brokenbar ] }; + + key <TLDE> { [ Cyrillic_yu, Cyrillic_YU ] }; + key <LatQ> { [ Cyrillic_ya, Cyrillic_YA ] }; + key <LatZ> { [ Cyrillic_ze, Cyrillic_ZE ] }; + key <LatS> { [ Cyrillic_es, Cyrillic_ES ] }; + key <LatA> { [ Cyrillic_a, Cyrillic_A ] }; + key <LatW> { [ Cyrillic_ve, Cyrillic_VE ] }; + key <LatC> { [ Cyrillic_tse, Cyrillic_TSE ] }; + key <LatX> { [Cyrillic_softsign,Cyrillic_SOFTSIGN ] }; + key <LatD> { [ Cyrillic_de, Cyrillic_DE ] }; + key <LatE> { [ Cyrillic_ie, Cyrillic_IE ] }; + key <LatV> { [ Cyrillic_zhe, Cyrillic_ZHE ] }; + key <LatF> { [ Cyrillic_ef, Cyrillic_EF ] }; + key <LatT> { [ Cyrillic_te, Cyrillic_TE ] }; + key <LatR> { [ Cyrillic_er, Cyrillic_ER ] }; + key <LatN> { [ Cyrillic_en, Cyrillic_EN ] }; + key <LatB> { [ Cyrillic_be, Cyrillic_BE ] }; + key <LatH> { [ Cyrillic_ha, Cyrillic_HA ] }; + key <LatG> { [ Cyrillic_ghe, Cyrillic_GHE ] }; + key <LatY> { [ Cyrillic_yeru, Cyrillic_YERU ] }; + key <LatM> { [ Cyrillic_em, Cyrillic_EM ] }; + key <LatJ> { [ Cyrillic_shorti, Cyrillic_SHORTI ] }; + key <LatU> { [ Cyrillic_u, Cyrillic_U ] }; + key <LatK> { [ Cyrillic_ka, Cyrillic_KA ] }; + key <LatI> { [ Cyrillic_i, Cyrillic_I ] }; + key <LatO> { [ Cyrillic_o, Cyrillic_O ] }; + key <LatL> { [ Cyrillic_el, Cyrillic_EL ] }; + key <LatP> { [ Cyrillic_pe, Cyrillic_PE ] }; + + key <AD11> { [ Cyrillic_sha, Cyrillic_SHA ] }; + key <AE12> { [ Cyrillic_che, Cyrillic_CHE ] }; + key <AD12> { [ Cyrillic_shcha, Cyrillic_SHCHA ] }; + key <BKSL> { [ Cyrillic_e, Cyrillic_E ] }; +}; + +partial alphanumeric_keys +xkb_symbols "phonetic_winkeys" { + + include "ru(phonetic)" + name[Group1]= "Russia - Phonetic Winkeys"; + + key <LatX> { [ Cyrillic_ha, Cyrillic_HA ] }; + key <LatH> { [ Cyrillic_che, Cyrillic_CHE ] }; + key <AE12> { [ Cyrillic_softsign, Cyrillic_softsign ] }; + +}; + +partial alphanumeric_keys +xkb_symbols "tt" { + include "ru(winkeys)" + name[Group1]= "Russia - Tatar"; + + key.type[group1]="FOUR_LEVEL"; + + key <TLDE> { [ 0x010004bb, 0x010004ba, + Cyrillic_io, Cyrillic_IO ] }; + key <AD02> { [ 0x010004e9, 0x010004e8, + Cyrillic_tse, Cyrillic_TSE ] }; + key <AD09> { [ 0x010004d9, 0x010004d8, + Cyrillic_shcha, Cyrillic_SHCHA ] }; + key <AD12> { [ 0x010004af, 0x010004ae, + Cyrillic_hardsign,Cyrillic_HARDSIGN ] }; + key <AC10> { [ 0x010004a3, 0x010004a2, + Cyrillic_zhe, Cyrillic_ZHE ] }; + key <AB07> { [ 0x01000497, 0x01000496, + Cyrillic_softsign,Cyrillic_SOFTSIGN ] }; + + include "level3(ralt_switch)" + +}; + +partial alphanumeric_keys +xkb_symbols "os_legacy" { + include "ru(common)" + + name[Group1]= "Russia - Ossetian, legacy"; + + key <TLDE> { [ Cyrillic_e, Cyrillic_E ] }; + key <AC07> { [ Cyrillic_o, Cyrillic_O, Cyrillic_io, Cyrillic_IO ] }; + key <AC11> { [ 0x010004D5, 0x010004D4 ] }; +}; + +partial alphanumeric_keys +xkb_symbols "os_winkeys" { + include "ru(winkeys)" + + name[Group1]= "Russia - Ossetian, Winkeys"; + + key <TLDE> { [ Cyrillic_e, Cyrillic_E ] }; + key <AC07> { [ Cyrillic_o, Cyrillic_O, Cyrillic_io, Cyrillic_IO ] }; + key <AC11> { [ 0x010004D5, 0x010004D4 ] }; +}; + +partial alphanumeric_keys +xkb_symbols "cv" { + include "ru(winkeys)" + + name[Group1]= "Russia - Chuvash"; + + key.type[group1]="FOUR_LEVEL"; + + key <AD03> { [ Cyrillic_u, Cyrillic_U, + 0x010004f3, 0x010004f2 ] }; + key <AD05> { [ Cyrillic_ie, Cyrillic_IE, + 0x01000115, 0x01000114 ] }; + key <AC04> { [ Cyrillic_a, Cyrillic_A, + abreve, Abreve ] }; + key <AB03> { [ Cyrillic_es, Cyrillic_ES, + ccedilla, Ccedilla ] }; + + include "level3(ralt_switch)" +}; + +partial alphanumeric_keys +xkb_symbols "udm" { + include "ru(winkeys)" + + name[Group1]= "Russia - Udmurt"; + + key.type[group1]="FOUR_LEVEL"; + + key <AE01> { [ question, exclam, 1, 1 ] }; + key <AE02> { [ parenleft, quotedbl, 2, 2 ] }; + key <AE03> { [ parenright, numerosign, 3, 3 ] }; + key <AE04> { [ colon, semicolon, 4, 4 ] }; + key <AE05> { [ asterisk, percent, 5, 5 ] }; + key <AE06> { [ 0x010004dd, 0x010004dc, 6, 6 ] }; + key <AE07> { [ 0x010004e7, 0x010004e6, 7, 7 ] }; + key <AE08> { [ 0x010004f5, 0x010004f4, 8, 8 ] }; + key <AE09> { [ 0x010004e5, 0x010004e4, 9, 9 ] }; + key <AE10> { [ 0x010004df, 0x010004de, 0, 0 ] }; + + include "level3(ralt_switch)" +}; + +partial alphanumeric_keys +xkb_symbols "cv_latin" { + include "us(alt-intl)" + + name[Group1]= "Russia - Chuvash Latin"; + + key.type[group1]="FOUR_LEVEL"; + + key <AD01> { [ q, Q, 0x01000161, 0x01000160 ] }; + key <AD02> { [ w, W, udiaeresis, Udiaeresis ] }; + key <AD03> { [ e, E, 0x01000115, 0x01000114 ] }; + key <AD07> { [ u, U, udiaeresis, Udiaeresis ] }; + key <AD08> { [ i, I, 0x0100012d, 0x0100012c ] }; + key <AD09> { [ o, O, odiaeresis, Odiaeresis ] }; + key <AC01> { [ a, A, abreve, Abreve ] }; + key <AC02> { [ s, S, scedilla, Scedilla ] }; + key <AC05> { [ g, G, gbreve, Gbreve ] }; + key <AC07> { [ j, J, 0x01000131, 0x01000130 ] }; + key <AB03> { [ c, C, ccedilla, Ccedilla ] }; + + include "level3(ralt_switch)" + +}; + +// Komi language layout +// based on +// russian standard keyboard +// Vlad Shakhov <lumpen.intellectual@gmail.com> +// Last Changes 2007/10/23 by Vlad Shakhov <lumpen.intellectual@gmail.com> + +partial alphanumeric_keys +xkb_symbols "kom" { + + include "ru(winkeys)" + + name[Group1]= "Russia - Komi"; + + key.type[group1]="FOUR_LEVEL_ALPHABETIC"; + +// cyrilllic o with diaeresis + key <AC07> { [ Cyrillic_o, Cyrillic_O, + U04E7, U04E6 ] }; + +// hard I as additional key for soft Cyrillic_I + key <AB05> { [ Cyrillic_i, Cyrillic_I, + Ukrainian_i, Ukrainian_I ] }; + + include "level3(ralt_switch)" +}; + +// Yakut language layout +// 2008/04/23 Yakov Aleksandrov <bertjickty@yandex.ru> +// 2008/04/23 Anatoliy Zhozhikov <jav@sitc.ru> +// 2008/04/23 Aleksandr Varlamov +partial alphanumeric_keys +xkb_symbols "sah" { + + include "ru(winkeys)" + + name[Group1]= "Russia - Yakut"; + + key.type[group1]="FOUR_LEVEL_ALPHABETIC"; + + key <TLDE> { [ Cyrillic_io, Cyrillic_IO, + U04EB, U04EA ] }; + key <AD01> { [ Cyrillic_shorti, Cyrillic_SHORTI, + U048B, U048A ] }; + key <AD03> { [ Cyrillic_u, Cyrillic_U, + Cyrillic_u_straight, Cyrillic_U_straight ] }; + key <AD04> { [ Cyrillic_ka, Cyrillic_KA, + U04C4, U04C3 ] }; + key <AD06> { [ Cyrillic_en, Cyrillic_EN, + U04A5, U04A4 ] }; + key <AD07> { [ Cyrillic_ghe, Cyrillic_GHE, + U0495, U0494 ] }; + key <AD10> { [ Cyrillic_ze, Cyrillic_ZE, + U04E1, U04E0 ] }; + key <AD11> { [ Cyrillic_ha, Cyrillic_HA, + Cyrillic_shha, Cyrillic_SHHA ] }; + key <AC07> { [ Cyrillic_o, Cyrillic_O, + Cyrillic_o_bar, Cyrillic_O_bar ] }; + key <AC10> { [ Cyrillic_zhe, Cyrillic_ZHE, + U0461, U0460 ] }; + key <AB02> { [ Cyrillic_che, Cyrillic_CHE, + Cyrillic_u_macron, Cyrillic_U_macron ] }; + key <AB04> { [ Cyrillic_em, Cyrillic_EM, + U04C8, U04C7 ] }; + key <AB05> { [ Cyrillic_i, Cyrillic_I, + Cyrillic_i_macron, Cyrillic_I_macron ] }; + + include "level3(ralt_switch)" +}; + + +//Kalmyk language layout +//based on the Kalmyk language layout: http://soft.oyrat.org/ +//Nikolay Korneev <halmg@oyrat.org> +//Toli Miron <mirontoli@gmail.com> + +partial alphanumeric_keys +xkb_symbols "xal" { + include "ru(winkeys)" + + name[Group1]= "Russia - Kalmyk"; + + key.type[group1]="FOUR_LEVEL"; + + key <AE01> { [ question, exclam, 1 ] }; + key <AE02> { [ numerosign, quotedbl, 2 ] }; + key <AE03> { [ Cyrillic_u_straight, Cyrillic_U_straight, 3 ] }; + key <AE04> { [ Cyrillic_schwa, Cyrillic_SCHWA, 4 ] }; + key <AE05> { [ asterisk, percent, 5 ] }; + key <AE06> { [ Cyrillic_en_descender, Cyrillic_EN_descender, 6 ] }; + key <AE07> { [ Cyrillic_o_bar, Cyrillic_O_bar, 7 ] }; + key <AE08> { [ Cyrillic_shha, Cyrillic_SHHA, 8 ] }; + key <AE09> { [ Cyrillic_zhe_descender, Cyrillic_ZHE_descender, 9 ] }; + key <AE10> { [ semicolon, colon, 0 ] }; + + key <TLDE> { [ parenleft, parenright, Cyrillic_io, Cyrillic_IO ] }; + + key <AD02> { [ Cyrillic_tse, Cyrillic_TSE, dollar ] }; + key <AD03> { [ Cyrillic_u, Cyrillic_U, EuroSign ] }; + key <AD04> { [ Cyrillic_ka, Cyrillic_KA, registered ] }; + key <AD05> { [ Cyrillic_ie, Cyrillic_IE, trademark ] }; + key <AD11> { [ Cyrillic_ha, Cyrillic_HA, bracketleft ] }; + key <AD12> { [ Cyrillic_hardsign, Cyrillic_HARDSIGN, bracketright ] }; + key <AC11> { [ Cyrillic_e, Cyrillic_E, apostrophe ] }; + key <AB03> { [ Cyrillic_es, Cyrillic_ES, copyright ] }; + key <AB08> { [ Cyrillic_be, Cyrillic_BE, less ] }; + key <AB09> { [ Cyrillic_yu, Cyrillic_YU, greater ] }; + + include "level3(ralt_switch)" +}; + +partial alphanumeric_keys +xkb_symbols "dos" { + + include "ru(common)" + + name[Group1]= "Russia - DOS"; + + key <TLDE> { [ parenright, parenleft ] }; + key <AE04> { [ 4, currency ] }; + key <AE09> { [ 9, question ] }; + key <AE10> { [ 0, percent ] }; + + key <AB10> { [ Cyrillic_io, Cyrillic_IO ] }; +}; + +partial alphanumeric_keys +xkb_symbols "bak" { + include "ru(winkeys)" + + name[Group1]= "Russia - Bashkirian"; + key.type[group1]="FOUR_LEVEL"; + + key <TLDE> { [ 0x010004d9, 0x010004d8, Cyrillic_io, Cyrillic_IO ] }; + key <AE01> { [ exclam, quotedbl, 1, 1 ] }; + key <AE02> { [ 0x010004e9, 0x010004e8, 2, 2 ] }; + key <AE03> { [ 0x010004a1, 0x010004a0, 3, 3 ] }; + key <AE04> { [ 0x01000493, 0x01000492, 4, 4 ] }; + key <AE05> { [ 0x010004ab, 0x010004aa, 5, 5 ] }; + key <AE06> { [ colon, semicolon, 6, 6 ] }; + key <AE07> { [ 0x01000499, 0x01000498, 7, 7 ] }; + key <AE08> { [ 0x010004bb, 0x010004ba, 8, 8 ] }; + key <AE09> { [ question, parenleft, 9, 9 ] }; + key <AE10> { [ numerosign, parenright, 0, 0 ] }; + key <AE11> { [ minus, percent, minus, underscore ]}; + key <AE12> { [ 0x010004af, 0x010004ae, equal, plus ]}; + key <BKSL> { [ 0x010004a3, 0x010004a2, backslash, slash ]}; + + include "level3(ralt_switch)" +}; + +// Serbian charecters added as third level symbols to Russian keyboard layout. + +partial alphanumeric_keys +xkb_symbols "srp" { + include "ru(common)" + include "level3(ralt_switch)" + + name[Group1]= "Russia - Serbian"; + + key <AE03> { [ 3, numerosign ] }; + key <AE04> { [ 4, semicolon ] }; + key <AE05> { [ 5, percent ] }; + key <AE06> { [ 6, colon ] }; + key <AE07> { [ 7, question ] }; + key <AE08> { [ 8, asterisk ] }; + key <AB10> { [ period, comma ] }; + key <BKSL> { [ backslash, slash ] }; + key <AD01> { [ Cyrillic_shorti, Cyrillic_SHORTI, U458, U408 ] }; + key <AD06> { [ Cyrillic_en, Cyrillic_EN, U45A, U40A ] }; + key <AC08> { [ Cyrillic_el, Cyrillic_EL, U459, U409 ] }; + key <AC09> { [ Cyrillic_de, Cyrillic_DE, U45F, U40F ] }; + key <AC10> { [ Cyrillic_zhe, Cyrillic_ZHE, U452, U402 ] }; + key <AB02> { [ Cyrillic_che, Cyrillic_CHE, U45B, U40B ] }; +}; + +// Mari language layout +// based on Russian standard keyboard +// http://www.marlamuter.ru/ +partial alphanumeric_keys +xkb_symbols "chm" { + include "ru(common)" + + name[Group1]= "Russia - Mari"; + + key.type[group1]="FOUR_LEVEL_ALPHABETIC"; + key <AC04> { [ Cyrillic_a, Cyrillic_A, U04D3, U04D2 ] }; + key <AD03> { [ Cyrillic_u, Cyrillic_U, U04F1, U04F0 ] }; + key <AC02> { [ Cyrillic_ui, Cyrillic_UI, U04F9, U04F8 ] }; + key <AD06> { [ Cyrillic_n, Cyrillic_N, U04A5, U04A4 ] }; + key <AC11> { [ Cyrillic_e, Cyrillic_E, U04E9, U04E8 ] }; + key <AC10> { [ Cyrillic_zh, Cyrillic_ZH, U04EB, U04EA ] }; + key <AC01> { [ Cyrillic_f, Cyrillic_F, UF537, UF536 ] }; + + include "level3(ralt_switch)" +}; + +// EXTRAS: + +// Church Slavonic language layout +// based on +// russian standard keyboard +// Aleksandr Andreev and Yuri Shardt +// Last Changes 2010/08/01. Contact <aleksandr.andreev@gmail.com> + +partial alphanumeric_keys +xkb_symbols "chu" +{ + name[Group1]= "Russia - Church Slavonic"; + key <TLDE> { [ U0457, U0407, U0482, U20DD ] }; // ї Ї ҂ e.g: а⃝ where the last is a combining ten thousands sign + key <AE01> { [ U0461, U0460, U047D, U047C] }; // ѡ Ѡ ѽ Ѽ + key <AE02> { [ U0454, U0404, U0465, U0464] }; // є Є ѥ Ѥ + key <AE03> { [ U046F, U046E, U0469, U0468] }; // ѯ Ѯ ѩ Ѩ + key <AE04> { [ U0471, U0470, U046D, U046C] }; // ѱ Ѱ ѭ Ѭ + key <AE05> { [ U0473, U0472, UA657, UA656] }; // ѳ Ѳ iotified A + key <AE06> { [ U0475, U0474, U0477, U0476] }; // ѵ Ѵ ѷ Ѷ + key <AE07> { [ U047B, U047A, UA64D, UA64C] }; // ѻ Ѻ ꙍ Ꙍ + key <AE08> { [ U047F, U047E, U046B, U046A] }; // ѿ Ѿ ѫ Ѫ + key <AE09> { [ U0455, U0405, parenleft, U002A ] }; // ѕ Ѕ ( * + key <AE10> { [ Cyrillic_u, Cyrillic_U, parenright, U0488 ] }; // у У ) NB: for diagraph Ouk, use Cyrillic_o + Cyrillic_u + key <AE11> { [ U0483, U0486, U0487, U005F] }; // а҃ а҆ а҇, _ (titlo, psili, pokrytie, underscore) + key <AE12> { [ U0301, U0300, U0484, UA67E] }; // а̀ а́ а҄ ꙾ (oxia, varia, kamora, kavyka) + key <AD01> { [ Cyrillic_shorti, Cyrillic_SHORTI, U0456 ] }; + key <AD02> { [ Cyrillic_tse, Cyrillic_TSE, U2DF0 ] }; + key <AD03> { [ UA64B, UA64A, U2DF9 ] }; // Cyrillic monograph Uk (not U)! + key <AD04> { [ Cyrillic_ka, Cyrillic_KA, U2DE6 ] }; + key <AD05> { [ Cyrillic_ie, Cyrillic_IE, U2DF7 ] }; + key <AD06> { [ Cyrillic_en, Cyrillic_EN, U2DE9 ] }; + key <AD07> { [ Cyrillic_ghe, Cyrillic_GHE, U2DE2 ] }; + key <AD08> { [ Cyrillic_sha, Cyrillic_SHA, U2DF2 ] }; + key <AD09> { [ Cyrillic_shcha, Cyrillic_SHCHA, U2DF3 ] }; + key <AD10> { [ Cyrillic_ze, Cyrillic_ZE, U2DE5 ] }; + key <AD11> { [ Cyrillic_ha, Cyrillic_HA, U2DEF ] }; + key <AD12> { [Cyrillic_hardsign,Cyrillic_HARDSIGN, UA67D ] }; // Payerok + key <BKSL> { [backslash, slash, colon, question] }; // \ / : ? (note, for Slavonic question use semicolon + key <AC01> { [ Cyrillic_ef, Cyrillic_EF ] }; + key <AC02> { [ Cyrillic_yeru, Cyrillic_YERU ] }; + key <AC03> { [ Cyrillic_ve, Cyrillic_VE, U2DE1 ] }; + key <AC04> { [ Cyrillic_a, Cyrillic_A, U2DF6 ] }; + key <AC05> { [ Cyrillic_pe, Cyrillic_PE, U2DEB ] }; + key <AC06> { [ Cyrillic_er, Cyrillic_ER, U2DEC ] }; + key <AC07> { [ Cyrillic_o, Cyrillic_O, U2DEA ] }; + key <AC08> { [ Cyrillic_el, Cyrillic_EL, U2DE7 ] }; + key <AC09> { [ Cyrillic_de, Cyrillic_DE, U2DE3 ] }; + key <AC10> { [ Cyrillic_zhe, Cyrillic_ZHE, U2DE4 ] }; + key <AC11> { [ U0463, U0462, U2DFA ] }; // Yat + key <AB01> { [ U0467, U0466, U2DFD ] }; // Small Yus + key <AB02> { [ Cyrillic_che, Cyrillic_CHE, U2DF1 ] }; + key <AB03> { [ Cyrillic_es, Cyrillic_ES, U2DED ] }; + key <AB04> { [ Cyrillic_em, Cyrillic_EM, U2DE8 ] }; + key <AB05> { [ Cyrillic_i, Cyrillic_I ] }; + key <AB06> { [ Cyrillic_te, Cyrillic_TE, U2DEE ] }; + key <AB07> { [Cyrillic_softsign,Cyrillic_SOFTSIGN ] }; + key <AB08> { [ Cyrillic_be, Cyrillic_BE, U2DE0 ] }; + key <AB09> { [ Cyrillic_yu, Cyrillic_YU, U2DFB ] }; + key <AB10> { [ period, comma, semicolon, exclam ] }; +}; diff --git a/xorg-server/xkeyboard-config/symbols/us b/xorg-server/xkeyboard-config/symbols/us index 8ff7ae537..871dfbdc6 100644 --- a/xorg-server/xkeyboard-config/symbols/us +++ b/xorg-server/xkeyboard-config/symbols/us @@ -1,1188 +1,1337 @@ -default
-partial alphanumeric_keys modifier_keys
-xkb_symbols "basic" {
-
- name[Group1]= "USA";
-
- // Alphanumeric section
- key <TLDE> { [ grave, asciitilde ] };
- key <AE01> { [ 1, exclam ] };
- key <AE02> { [ 2, at ] };
- key <AE03> { [ 3, numbersign ] };
- key <AE04> { [ 4, dollar ] };
- key <AE05> { [ 5, percent ] };
- key <AE06> { [ 6, asciicircum ] };
- key <AE07> { [ 7, ampersand ] };
- key <AE08> { [ 8, asterisk ] };
- key <AE09> { [ 9, parenleft ] };
- key <AE10> { [ 0, parenright ] };
- key <AE11> { [ minus, underscore ] };
- key <AE12> { [ equal, plus ] };
-
- key <AD01> { [ q, Q ] };
- key <AD02> { [ w, W ] };
- key <AD03> { [ e, E ] };
- key <AD04> { [ r, R ] };
- key <AD05> { [ t, T ] };
- key <AD06> { [ y, Y ] };
- key <AD07> { [ u, U ] };
- key <AD08> { [ i, I ] };
- key <AD09> { [ o, O ] };
- key <AD10> { [ p, P ] };
- key <AD11> { [ bracketleft, braceleft ] };
- key <AD12> { [ bracketright, braceright ] };
-
- key <AC01> { [ a, A ] };
- key <AC02> { [ s, S ] };
- key <AC03> { [ d, D ] };
- key <AC04> { [ f, F ] };
- key <AC05> { [ g, G ] };
- key <AC06> { [ h, H ] };
- key <AC07> { [ j, J ] };
- key <AC08> { [ k, K ] };
- key <AC09> { [ l, L ] };
- key <AC10> { [ semicolon, colon ] };
- key <AC11> { [ apostrophe, quotedbl ] };
-
- key <AB01> { [ z, Z ] };
- key <AB02> { [ x, X ] };
- key <AB03> { [ c, C ] };
- key <AB04> { [ v, V ] };
- key <AB05> { [ b, B ] };
- key <AB06> { [ n, N ] };
- key <AB07> { [ m, M ] };
- key <AB08> { [ comma, less ] };
- key <AB09> { [ period, greater ] };
- key <AB10> { [ slash, question ] };
-
- key <BKSL> { [ backslash, bar ] };
- // End alphanumeric section
-};
-
-partial alphanumeric_keys
-xkb_symbols "euro" {
-
- name[Group1]= "USA - With EuroSign on 5";
-
- include "us(basic)"
-
- include "eurosign(5)"
-
- include "level3(ralt_switch)"
-};
-
-
-partial alphanumeric_keys
-xkb_symbols "intl" {
-
- name[Group1]= "USA - International (with dead keys)";
-
- include "us(basic)"
-
- // Alphanumeric section
- key <TLDE> { [dead_grave, dead_tilde, grave, asciitilde ] };
- key <AE01> { [ 1, exclam, exclamdown, onesuperior ] };
- key <AE02> { [ 2, at, twosuperior, dead_doubleacute ] };
- key <AE03> { [ 3, numbersign, threesuperior, dead_macron ] };
- key <AE04> { [ 4, dollar, currency, sterling ] };
- key <AE05> { [ 5, percent, EuroSign, dead_cedilla ] };
- key <AE06> { [ 6, dead_circumflex, onequarter, asciicircum ] };
- key <AE07> { [ 7, ampersand, onehalf, dead_horn ] };
- key <AE08> { [ 8, asterisk, threequarters, dead_ogonek ] };
- key <AE09> { [ 9, parenleft, leftsinglequotemark, dead_breve ] };
- key <AE10> { [ 0, parenright, rightsinglequotemark, dead_abovering ] };
- key <AE11> { [ minus, underscore, yen, dead_belowdot ] };
- key <AE12> { [ equal, plus, multiply, division ] };
-
- key <AD01> { [ q, Q, adiaeresis, Adiaeresis ] };
- key <AD02> { [ w, W, aring, Aring ] };
- key <AD03> { [ e, E, eacute, Eacute ] };
- key <AD04> { [ r, R, registered, registered ] };
- key <AD05> { [ t, T, thorn, THORN ] };
- key <AD06> { [ y, Y, udiaeresis, Udiaeresis ] };
- key <AD07> { [ u, U, uacute, Uacute ] };
- key <AD08> { [ i, I, iacute, Iacute ] };
- key <AD09> { [ o, O, oacute, Oacute ] };
- key <AD10> { [ p, P, odiaeresis, Odiaeresis ] };
- key <AD11> { [ bracketleft, braceleft, guillemotleft, leftdoublequotemark ] };
- key <AD12> { [bracketright, braceright, guillemotright, rightdoublequotemark ] };
-
- key <AC01> { [ a, A, aacute, Aacute ] };
- key <AC02> { [ s, S, ssharp, section ] };
- key <AC03> { [ d, D, eth, ETH ] };
- key <AC04> { [ f, F, f, F ] };
- key <AC05> { [ g, G, g, G ] };
- key <AC06> { [ h, H, h, H ] };
- key <AC07> { [ j, J, j, J ] };
- key <AC08> { [ k, K, oe, OE ] };
-
- key <AC09> { [ l, L, oslash, Ooblique ] };
- key <AC10> { [ semicolon, colon, paragraph, degree ] };
- key <AC11> { [dead_acute, dead_diaeresis, apostrophe, quotedbl ] };
-
- key <AB01> { [ z, Z, ae, AE ] };
- key <AB02> { [ x, X, x, X ] };
- key <AB03> { [ c, C, copyright, cent ] };
- key <AB04> { [ v, V, v, V ] };
- key <AB05> { [ b, B, b, B ] };
- key <AB06> { [ n, N, ntilde, Ntilde ] };
- key <AB07> { [ m, M, mu, mu ] };
- key <AB08> { [ comma, less, ccedilla, Ccedilla ] };
- key <AB09> { [ period, greater, dead_abovedot, dead_caron ] };
- key <AB10> { [ slash, question, questiondown, dead_hook ] };
- key <BKSL> { [ backslash, bar, notsign, brokenbar ] };
-
- include "level3(ralt_switch)"
-};
-
-// Based on symbols/us_intl keyboard map:
-// Dead-keys definition for a very simple US/ASCII layout.
-// by Conectiva (http://www.conectiva.com.br)
-// modified by Ricardo Y. Igarashi (iga@that.com.br)
-
-// Added the following deadkeys, to make it truly international:
-//
-// dead_macron: on AltGr-minus
-// dead_breve: on AltGr-parenleft
-// dead_abovedot: on AltGr-period
-// dead_abovering: on AltGr-0
-// dead_doubleacute: on AltGr-equal (as quotedbl is already used)
-// dead_caron: on AltGr-less (AltGr-shift-comma)
-// dead_cedilla: on AltGr-comma
-// dead_ogonek: on AltGr-semicolon
-// dead_belowdot: on AltGr-underscore (AltGr-shift-minus)
-// dead_hook: on AltGr-question
-// dead_horn: on AltGr-plus (AltGr-shift-equal)
-// dead_diaeresis: on AltGr-colon (Alt-shift-semicolon)
-//
-// those were already there:
-// dead_grave
-// dead_acute
-// dead_circumflex
-// dead_tilde
-// dead_diaeresis
-
-partial alphanumeric_keys
-xkb_symbols "alt-intl" {
-
- name[Group1]= "USA - Alternative international";
-
- include "us"
-
- key <TLDE> { [ dead_grave, dead_tilde, grave, asciitilde ] };
- key <AE05> { [ 5, percent, EuroSign ] };
- key <AE06> { [ 6, dead_circumflex, asciicircum, asciicircum ] };
- key <AE09> { [ 9, parenleft, leftsinglequotemark, dead_breve ] };
- key <AE10> { [ 0, parenright, rightsinglequotemark, dead_abovering ] };
- key <AE11> { [ minus, underscore, dead_macron, dead_belowdot ] };
- key <AE12> { [ equal, plus, dead_doubleacute, dead_horn ] };
-
- key <AD03> { [ e, E, EuroSign, cent ] };
-
- key <AC10> { [ semicolon, colon, dead_ogonek, dead_diaeresis ] };
- key <AC11> { [ dead_acute, dead_diaeresis, apostrophe, quotedbl ] };
-
- key <AB08> { [ comma, less, dead_cedilla, dead_caron ] };
- key <AB09> { [ period, greater, dead_abovedot, dead_circumflex ] };
- key <AB10> { [ slash, question, dead_hook, dead_hook ] };
-
- include "level3(ralt_switch)"
-};
-
-// based on a keyboard map from an 'xkb/symbols/dk' file
-
-partial alphanumeric_keys
-xkb_symbols "dvorak" {
-
- name[Group1]= "USA - Dvorak";
-
- // Alphanumeric section
-
- key <TLDE> { [ grave, asciitilde, dead_grave, dead_tilde ] };
-
- key <AE01> { [ 1, exclam ] };
- key <AE02> { [ 2, at ] };
- key <AE03> { [ 3, numbersign ] };
- key <AE04> { [ 4, dollar ] };
- key <AE05> { [ 5, percent ] };
- key <AE06> { [ 6, asciicircum, dead_circumflex, dead_circumflex ] };
- key <AE07> { [ 7, ampersand ] };
- key <AE08> { [ 8, asterisk ] };
- key <AE09> { [ 9, parenleft, dead_grave] };
- key <AE10> { [ 0, parenright ] };
- key <AE11> { [ bracketleft, braceleft ] };
- key <AE12> { [ bracketright, braceright, dead_tilde] };
-
- key <AD01> { [ apostrophe, quotedbl, dead_acute, dead_diaeresis ] };
- key <AD02> { [ comma, less, dead_cedilla, dead_caron ] };
- key <AD03> { [ period, greater, dead_abovedot, periodcentered ] };
- key <AD04> { [ p, P ] };
- key <AD05> { [ y, Y ] };
- key <AD06> { [ f, F ] };
- key <AD07> { [ g, G ] };
- key <AD08> { [ c, C ] };
- key <AD09> { [ r, R ] };
- key <AD10> { [ l, L ] };
- key <AD11> { [ slash, question ] };
- key <AD12> { [ equal, plus ] };
-
- key <AC01> { [ a, A ] };
- key <AC02> { [ o, O ] };
- key <AC03> { [ e, E ] };
- key <AC04> { [ u, U ] };
- key <AC05> { [ i, I ] };
- key <AC06> { [ d, D ] };
- key <AC07> { [ h, H ] };
- key <AC08> { [ t, T ] };
- key <AC09> { [ n, N ] };
- key <AC10> { [ s, S ] };
- key <AC11> { [ minus, underscore ] };
-
- key <AB01> { [ semicolon, colon, dead_ogonek, dead_doubleacute ] };
- key <AB02> { [ q, Q ] };
- key <AB03> { [ j, J ] };
- key <AB04> { [ k, K ] };
- key <AB05> { [ x, X ] };
- key <AB06> { [ b, B ] };
- key <AB07> { [ m, M ] };
- key <AB08> { [ w, W ] };
- key <AB09> { [ v, V ] };
- key <AB10> { [ z, Z ] };
-
- key <BKSL> { [ backslash, bar ] };
-};
-
-// Dvorak international with dead keys
-// Olivier Mehani (shtrom-xorg@ssji.net)
-// Reproduce the per-key mapping of us(intl) for the dvorak layout
-// aka "I just swapped my keys over"
-partial alphanumeric_keys
-xkb_symbols "dvorak-intl" {
-
- name[Group1]= "USA - Dvorak international (with dead keys)";
-
- include "us(dvorak)"
-
- key <TLDE> { [dead_grave, dead_tilde, grave, asciitilde ] };
-
- key <AE01> { [ 1, exclam, exclamdown, onesuperior ] };
- key <AE02> { [ 2, at, twosuperior, dead_doubleacute ] };
- key <AE03> { [ 3, numbersign, threesuperior, dead_macron ] };
- key <AE04> { [ 4, dollar, currency, sterling ] };
- key <AE05> { [ 5, percent, EuroSign, dead_cedilla ] };
- key <AE06> { [ 6, dead_circumflex, onequarter, asciicircum ] };
- key <AE07> { [ 7, ampersand, onehalf, dead_horn ] };
- key <AE08> { [ 8, asterisk, threequarters, dead_ogonek ] };
- key <AE09> { [ 9, parenleft, leftsinglequotemark, dead_breve ] };
- key <AE10> { [ 0, parenright, rightsinglequotemark, dead_abovering ] };
- key <AE11> { [ bracketleft, braceleft, guillemotleft, leftdoublequotemark ] };
- key <AE12> { [bracketright, braceright, guillemotright, rightdoublequotemark ] };
-
- key <AD01> { [dead_acute, dead_diaeresis, apostrophe, quotedbl ] };
- key <AD02> { [ comma, less, ccedilla, Ccedilla ] };
- key <AD03> { [ period, greater, dead_abovedot, dead_caron ] };
- key <AD04> { [ p, P, odiaeresis, Odiaeresis ] };
- key <AD05> { [ y, Y, udiaeresis, Udiaeresis ] };
- // key <AD06> { [ f, F ] };
- // key <AD07> { [ g, G ] };
- key <AD08> { [ c, C, copyright, cent ] };
- key <AD09> { [ r, R, registered, registered ] };
- key <AD10> { [ l, L, oslash, Ooblique ] };
- key <AD11> { [ slash, question, questiondown, dead_hook ] };
- // key <AD12> { [ equal, plus, multiply, division ] };
-
- key <AC01> { [ a, A, aacute, Aacute ] };
- key <AC02> { [ o, O, oacute, Oacute ] };
- key <AC03> { [ e, E, eacute, Eacute ] };
- key <AC04> { [ u, U, uacute, Uacute ] };
- key <AC05> { [ i, I, iacute, Iacute ] };
- key <AC06> { [ d, D, eth, ETH ] };
- // key <AC07> { [ h, H ] };
- key <AC08> { [ t, T, thorn, THORN ] };
- key <AC09> { [ n, N, ntilde, Ntilde ] };
- key <AC10> { [ s, S, ssharp, section ] };
- // key <AC11> { [ minus, underscore, yen, dead_belowdot ] };
-
- key <AB01> { [ semicolon, colon, paragraph, degree ] };
- key <AB02> { [ q, Q, adiaeresis, Adiaeresis ] };
- // key <AB03> { [ j, J ] };
- key <AB04> { [ k, K, oe, OE ] };
- // key <AB05> { [ x, X ] };
- // key <AB06> { [ b, B ] };
- key <AB07> { [ m, M, mu, mu ] };
- key <AB08> { [ w, W, aring, Aring ] };
- // key <AB09> { [ v, V ] };
- key <AB10> { [ z, Z, ae, AE ] };
-
- key <BKSL> { [ backslash, bar, notsign, brokenbar ] };
-
- include "level3(ralt_switch)"
-};
-
-// Dvorak international without dead keys
-// Stephane Magnenat (stephane at magnenat dot net, http://stephane.magnenat.net)
-// Based on information from http://www.poupinou.org/dvorak/index.html
-//
-// ` 1 2 3 4 5 6 7 8 9 0 [ ] \
-// €
-//
-// ' , . p y f g c r l / =
-// ä ê ë ü ç
-//
-// a o e u i d h t n s -
-// à ô é û î ß
-//
-// ; q j k x b m w v z
-// â ö è ù ï
-
-partial alphanumeric_keys
-xkb_symbols "dvorak-alt-intl" {
-
- name[Group1]= "USA - Dvorak alternative international (no dead keys)";
-
- include "us(dvorak)"
-
- key <AE04> { [ 4, dollar, EuroSign ] };
-
- key <AD02> { [ comma, less, adiaeresis, dead_caron ] };
- key <AD03> { [ period, greater, ecircumflex, periodcentered ] };
- key <AD04> { [ p, P, ediaeresis, dead_cedilla ] };
- key <AD05> { [ y, Y, udiaeresis ] };
- key <AD08> { [ c, C, ccedilla, dead_abovedot ] };
-
- key <AC01> { [ a, A, agrave ] };
- key <AC02> { [ o, O, ocircumflex ] };
- key <AC03> { [ e, E, eacute ] };
- key <AC04> { [ u, U, ucircumflex ] };
- key <AC05> { [ i, I, icircumflex ] };
- key <AC10> { [ s, S, ssharp ] };
-
- key <AB01> { [ semicolon, colon, acircumflex ] };
- key <AB02> { [ q, Q, odiaeresis, dead_ogonek ] };
- key <AB03> { [ j, J, egrave, dead_doubleacute ] };
- key <AB04> { [ k, K, ugrave ] };
- key <AB05> { [ x, X, idiaeresis ] };
-
- include "level3(ralt_switch)"
-};
-
-// Left and right handed dvorak layouts
-// by sqweek <sqweek@gmail.com> 2006-01-30
-// Based on the corresponding layouts in the console-tools package.
-partial alphanumeric_keys
-xkb_symbols "dvorak-l" {
-
- include "us(dvorak)"
- name[Group1]= "USA - Left handed Dvorak";
-
- key <AE01> { [ bracketleft, braceleft ] };
- key <AE02> { [ bracketright, braceright ] };
- key <AE03> { [ slash, question ] };
- key <AE04> { [ p, P ] };
- key <AE05> { [ f, F ] };
- key <AE06> { [ m, M ] };
- key <AE07> { [ l, L ] };
- key <AE08> { [ j, J ] };
- key <AE09> { [ 4, dollar ] };
- key <AE10> { [ 3, numbersign ] };
- key <AE11> { [ 2, at ] };
- key <AE12> { [ 1, exclam ] };
-
- key <AD01> { [ semicolon, colon ] };
- key <AD02> { [ q, Q ] };
- key <AD03> { [ b, B ] };
- key <AD04> { [ y, Y ] };
- key <AD05> { [ u, U ] };
- key <AD06> { [ r, R ] };
- key <AD07> { [ s, S ] };
- key <AD08> { [ o, O ] };
- key <AD09> { [ period, greater ] };
- key <AD10> { [ 6, asciicircum ] };
- key <AD11> { [ 5, percent ] };
- key <AD12> { [ equal, plus ] };
-
- key <AC01> { [ minus, underscore ] };
- key <AC02> { [ k, K ] };
- key <AC03> { [ c, C ] };
- key <AC04> { [ d, D ] };
- key <AC05> { [ t, T ] };
- key <AC06> { [ h, H ] };
- key <AC07> { [ e, E ] };
- key <AC08> { [ a, A ] };
- key <AC09> { [ z, Z ] };
- key <AC10> { [ 8, asterisk ] };
- key <AC11> { [ 7, ampersand ] };
-
- key <AB01> { [ apostrophe, quotedbl ] };
- key <AB02> { [ x, X ] };
- key <AB03> { [ g, G ] };
- key <AB04> { [ v, V ] };
- key <AB05> { [ w, W ] };
- key <AB06> { [ n, N ] };
- key <AB07> { [ i, I ] };
- key <AB08> { [ comma, less ] };
- key <AB09> { [ 0, parenright ] };
- key <AB10> { [ 9, parenleft ] };
-};
-
-partial alphanumeric_keys
-xkb_symbols "dvorak-r" {
-
- include "us(dvorak)"
- name[Group1]= "USA - Right handed Dvorak";
-
- key <AE01> { [ 1, exclam ] };
- key <AE02> { [ 2, at ] };
- key <AE03> { [ 3, numbersign ] };
- key <AE04> { [ 4, dollar ] };
- key <AE05> { [ j, J ] };
- key <AE06> { [ l, L ] };
- key <AE07> { [ m, M ] };
- key <AE08> { [ f, F ] };
- key <AE09> { [ p, P ] };
- key <AE10> { [ slash, question ] };
- key <AE11> { [ bracketleft, braceleft ] };
- key <AE12> { [ bracketright, braceright ] };
-
- key <AD01> { [ 5, percent ] };
- key <AD02> { [ 6, asciicircum ] };
- key <AD03> { [ q, Q ] };
- key <AD04> { [ period, greater ] };
- key <AD05> { [ o, O ] };
- key <AD06> { [ r, R ] };
- key <AD07> { [ s, S ] };
- key <AD08> { [ u, U ] };
- key <AD09> { [ y, Y ] };
- key <AD10> { [ b, B ] };
- key <AD11> { [ semicolon, colon ] };
- key <AD12> { [ equal, plus ] };
-
- key <AC01> { [ 7, ampersand ] };
- key <AC02> { [ 8, asterisk ] };
- key <AC03> { [ z, Z ] };
- key <AC04> { [ a, A ] };
- key <AC05> { [ e, E ] };
- key <AC06> { [ h, H ] };
- key <AC07> { [ t, T ] };
- key <AC08> { [ d, D ] };
- key <AC09> { [ c, C ] };
- key <AC10> { [ k, K ] };
- key <AC11> { [ minus, underscore ] };
-
- key <AB01> { [ 9, parenleft ] };
- key <AB02> { [ 0, parenright ] };
- key <AB03> { [ x, X ] };
- key <AB04> { [ comma, less ] };
- key <AB05> { [ i, I ] };
- key <AB06> { [ n, N ] };
- key <AB07> { [ w, W ] };
- key <AB08> { [ v, V ] };
- key <AB09> { [ g, G ] };
- key <AB10> { [ apostrophe, quotedbl ] };
-};
-
-// Classic dvorak layout
-// by Piter Punk <piterpk@terra.com.br> - 2006-07-06
-// Based on dvorak layout and e-mail from Russel L. Harris rlharris@oplink.net
-// on xorg list.
-partial alphanumeric_keys
-xkb_symbols "dvorak-classic" {
-
- name[Group1]= "USA - Classic Dvorak";
-
- // Alphanumeric section
-
- key <TLDE> { [ grave, asciitilde, dead_grave, dead_tilde ] };
-
- key <AE01> { [ bracketleft, braceleft ] };
- key <AE02> { [ 7, ampersand ] };
- key <AE03> { [ 5, percent ] };
- key <AE04> { [ 3, numbersign ] };
- key <AE05> { [ 1, exclam ] };
- key <AE06> { [ 9, parenleft, dead_grave] };
- key <AE07> { [ 0, parenright ] };
- key <AE08> { [ 2, at ] };
- key <AE09> { [ 4, dollar ] };
- key <AE10> { [ 6, asciicircum, dead_circumflex, dead_circumflex ] };
- key <AE11> { [ 8, asterisk ] };
- key <AE12> { [ bracketright, braceright, dead_tilde] };
-
- key <AD01> { [ slash, question ] };
- key <AD02> { [ comma, less, dead_cedilla, dead_caron ] };
- key <AD03> { [ period, greater, dead_abovedot, periodcentered ] };
- key <AD04> { [ p, P ] };
- key <AD05> { [ y, Y ] };
- key <AD06> { [ f, F ] };
- key <AD07> { [ g, G ] };
- key <AD08> { [ c, C ] };
- key <AD09> { [ r, R ] };
- key <AD10> { [ l, L ] };
- key <AD11> { [ apostrophe, quotedbl, dead_acute, dead_diaeresis ] };
- key <AD12> { [ equal, plus ] };
-
- key <AC01> { [ a, A ] };
- key <AC02> { [ o, O ] };
- key <AC03> { [ e, E ] };
- key <AC04> { [ u, U ] };
- key <AC05> { [ i, I ] };
- key <AC06> { [ d, D ] };
- key <AC07> { [ h, H ] };
- key <AC08> { [ t, T ] };
- key <AC09> { [ n, N ] };
- key <AC10> { [ s, S ] };
- key <AC11> { [ minus, underscore ] };
-
- key <AB01> { [ semicolon, colon, dead_ogonek, dead_doubleacute ] };
- key <AB02> { [ q, Q ] };
- key <AB03> { [ j, J ] };
- key <AB04> { [ k, K ] };
- key <AB05> { [ x, X ] };
- key <AB06> { [ b, B ] };
- key <AB07> { [ m, M ] };
- key <AB08> { [ w, W ] };
- key <AB09> { [ v, V ] };
- key <AB10> { [ z, Z ] };
- key <BKSL> { [ backslash, bar ] };
-};
-
-// Programmer Dvorak, by Roland Kaufmann <rlndkfmn at gmail dot com>
-// License: BSD, available at <http://www.kaufmann.no/roland/dvorak/license.html>
-// Main features: Numbers are in shift position (like French), symbols have been
-// placed in locations that give good hand-alternation and finger rolling with
-// symbols that usually follows, accented characters are possible for I18N.
-partial alphanumeric_keys
-xkb_symbols "dvp" {
- include "us(dvorak)"
-
- name[Group1] = "USA - Programmer Dvorak";
-
- // Unmodified Shift AltGr Shift+AltGr
- // symbols row, left side
- key <TLDE> { [ dollar, asciitilde, dead_tilde ] };
- key <AE01> { [ ampersand, percent ] };
- key <AE02> { [ bracketleft, 7, currency ], type[Group1] = "FOUR_LEVEL_ALPHABETIC" };
- key <AE03> { [ braceleft, 5, cent ], type[Group1] = "FOUR_LEVEL_ALPHABETIC" };
- key <AE04> { [ braceright, 3, yen ], type[Group1] = "FOUR_LEVEL_ALPHABETIC" };
- key <AE05> { [ parenleft, 1, EuroSign ], type[Group1] = "FOUR_LEVEL_ALPHABETIC" };
- key <AE06> { [ equal, 9, sterling ], type[Group1] = "FOUR_LEVEL_ALPHABETIC" };
-
- // symbols row, right side
- key <AE07> { [ asterisk, 0 ], type[Group1] = "FOUR_LEVEL_ALPHABETIC" };
- key <AE08> { [ parenright, 2, onehalf ], type[Group1] = "FOUR_LEVEL_ALPHABETIC" };
- key <AE09> { [ plus, 4 ], type[Group1] = "FOUR_LEVEL_ALPHABETIC" };
- key <AE10> { [ bracketright, 6 ], type[Group1] = "FOUR_LEVEL_ALPHABETIC" };
- key <AE11> { [ exclam, 8, exclamdown ], type[Group1] = "FOUR_LEVEL_ALPHABETIC" };
- key <AE12> { [ numbersign, grave, dead_grave ] };
- key <BKSP> { [ BackSpace ] };
-
- // upper row, left side
- key <AD01> { [ semicolon, colon, dead_diaeresis ] };
- key <AD02> { [ comma, less, guillemotleft ] };
- key <AD03> { [ period, greater, guillemotright ] };
- key <AD04> { [ p, P, paragraph, section ] };
- key <AD05> { [ y, Y, udiaeresis, Udiaeresis ] };
-
- // upper row, right side
- key <AD08> { [ c, C, ccedilla, Ccedilla ] };
- key <AD09> { [ r, R, registered, trademark ] };
- key <AD11> { [ slash, question, questiondown ] };
- key <AD12> { [ at, asciicircum, dead_circumflex, dead_caron ] };
-
- // home row, left side
- key <AC01> { [ a, A, aring, Aring ] };
- key <AC02> { [ o, O, oslash, Ooblique ] };
- key <AC03> { [ e, E, ae, AE ] };
- key <AC04> { [ u, U, eacute, Eacute ] };
-
- // home row, right side
- key <AC06> { [ d, D, eth, ETH ] };
- key <AC07> { [ h, H, dead_acute ] };
- key <AC08> { [ t, T, thorn, THORN ] };
- key <AC09> { [ n, N, ntilde, Ntilde ] };
- key <AC10> { [ s, S, ssharp ] };
- key <AC11> { [ minus, underscore, hyphen ], type[Group1] = "FOUR_LEVEL_ALPHABETIC" };
- key <BKSL> { [ backslash, bar ] };
-
- // lower row, left side
- key <AB01> { [ apostrophe, quotedbl, dead_acute ] };
-};
-
-// phonetic layout for Russian letters on an US keyboard
-// by Ivan Popov <pin@konvalo.org> 2005-07-17
-
-// level3 modifier is a shortcut to the "us" meaning of the keys where
-// we place cyrillic letters, handy for accessing the corresponding
-// punctuation marks.
-// It is important to have access to punctuation marks, and the rest of
-// alphabetical keys are added for being consequent so that the users
-// can expect the level3 modifier to give what the key label shows.
-
-partial alphanumeric_keys
-xkb_symbols "rus" {
-
- name[Group1]= "USA - Russian phonetic";
-
- include "us(basic)"
-
-key.type[group1]="FOUR_LEVEL_ALPHABETIC";
-
- key <LatA> { [ Cyrillic_a, Cyrillic_A ] };
- key <LatB> { [ Cyrillic_be, Cyrillic_BE ] };
- key <LatW> { [ Cyrillic_ve, Cyrillic_VE ] };
- key <LatG> { [ Cyrillic_ghe, Cyrillic_GHE ] };
- key <LatD> { [ Cyrillic_de, Cyrillic_DE ] };
- key <LatE> { [ Cyrillic_ie, Cyrillic_IE ] };
- key <TLDE> { [ Cyrillic_io, Cyrillic_IO, grave, asciitilde ] };
- key <LatV> { [ Cyrillic_zhe, Cyrillic_ZHE ] };
- key <LatZ> { [ Cyrillic_ze, Cyrillic_ZE ] };
- key <LatI> { [ Cyrillic_i, Cyrillic_I ] };
- key <LatJ> { [ Cyrillic_shorti, Cyrillic_SHORTI ] };
- key <LatK> { [ Cyrillic_ka, Cyrillic_KA ] };
- key <LatL> { [ Cyrillic_el, Cyrillic_EL ] };
- key <LatM> { [ Cyrillic_em, Cyrillic_EM ] };
- key <LatN> { [ Cyrillic_en, Cyrillic_EN ] };
- key <LatO> { [ Cyrillic_o, Cyrillic_O ] };
- key <LatP> { [ Cyrillic_pe, Cyrillic_PE ] };
- key <LatR> { [ Cyrillic_er, Cyrillic_ER ] };
- key <LatS> { [ Cyrillic_es, Cyrillic_ES ] };
- key <LatT> { [ Cyrillic_te, Cyrillic_TE ] };
- key <LatU> { [ Cyrillic_u, Cyrillic_U ] };
- key <LatF> { [ Cyrillic_ef, Cyrillic_EF ] };
- key <LatH> { [ Cyrillic_ha, Cyrillic_HA ] };
- key <LatC> { [ Cyrillic_tse, Cyrillic_TSE ] };
- key <AC10> { [ Cyrillic_che, Cyrillic_CHE, semicolon, colon ] };
- key <AD11> { [ Cyrillic_sha, Cyrillic_SHA, bracketleft, braceleft] };
- key <AD12> { [ Cyrillic_shcha, Cyrillic_SHCHA, bracketright, braceright ] };
- key <AE12> { [ Cyrillic_hardsign, Cyrillic_HARDSIGN, equal, plus ] };
- key <LatY> { [ Cyrillic_yeru, Cyrillic_YERU ] };
- key <LatX> { [ Cyrillic_softsign, Cyrillic_SOFTSIGN ] };
- key <BKSL> { [ Cyrillic_e, Cyrillic_E, backslash, bar ] };
- key <AC11> { [ Cyrillic_yu, Cyrillic_YU, apostrophe, quotedbl ] };
- key <LatQ> { [ Cyrillic_ya, Cyrillic_YA ] };
-
- include "level3(ralt_switch)"
-};
-
-partial alphanumeric_keys
-xkb_symbols "mac" {
-
- include "us(basic)"
- name[Group1]= "USA - Macintosh";
- key.type[group1]="FOUR_LEVEL";
-
- // Slightly improvised from http://homepage.mac.com/thgewecke/kblayout.jpg
- key <LSGT> { [ section, plusminus, section, plusminus ] };
- key <TLDE> { [ grave, asciitilde, dead_grave, dead_horn ] };
- key <AE01> { [ 1, exclam, exclamdown, U2044 ] };
- key <AE02> { [ 2, at, trademark, EuroSign ] };
- key <AE03> { [ 3, numbersign, sterling, U2039 ] };
- key <AE04> { [ 4, dollar, cent, U203A ] };
- key <AE05> { [ 5, percent, infinity, UFB01 ] };
- key <AE06> { [ 6,asciicircum, section, UFB02 ] };
- key <AE07> { [ 7, ampersand, paragraph, doubledagger ] };
- key <AE08> { [ 8, asterisk, enfilledcircbullet, degree ] };
- key <AE09> { [ 9, parenleft, ordfeminine, periodcentered ] };
- key <AE10> { [ 0, parenright, masculine,singlelowquotemark] };
- key <AE11> { [ minus, underscore, endash, emdash ] };
- key <AE12> { [ equal, plus, notequal, plusminus ] };
-
- key <AD01> { [ q, Q, oe, OE ] };
- key <AD02> { [ w, W, U2211,doublelowquotemark] };
- key <AD03> { [ e, E, dead_acute, acute ] };
- key <AD04> { [ r, R, registered, U2030 ] };
- key <AD05> { [ t, T, dagger, dead_caron ] };
- key <AD06> { [ y, Y, yen, onequarter ] };
- key <AD07> { [ u, U, dead_diaeresis, diaeresis ] };
- key <AD08> { [ i, I, dead_circumflex, U02C6 ] };
- key <AD09> { [ o, O, oslash, Ooblique ] };
- key <AD10> { [ p, P, Greek_pi, U220F ] };
- key <AD11> { [ bracketleft, braceleft, leftdoublequotemark, rightdoublequotemark ] };
- key <AD12> { [bracketright, braceright, leftsinglequotemark, rightsinglequotemark ] };
- key <BKSL> { [ backslash, bar, guillemotleft, guillemotright ] };
-
- key <AC01> { [ a, A, aring, Aring ] };
- key <AC02> { [ s, S, ssharp, dead_stroke ] };
- key <AC03> { [ d, D, partialderivative, eth ] };
- key <AC04> { [ f, F, function, dead_hook ] };
- key <AC05> { [ g, G, copyright, dead_doubleacute ] };
- key <AC06> { [ h, H, dead_abovedot, dead_belowdot ] };
- key <AC07> { [ j, J, U2206, onehalf ] };
- key <AC08> { [ k, K,dead_abovering, UF8FF ] };
-
- key <AC09> { [ l, L, notsign, THORN ] };
- key <AC10> { [ semicolon, colon, U2026, thorn ] };
- key <AC11> { [apostrophe, quotedbl, ae, AE ] };
-
- key <AB01> { [ z, Z, Greek_OMEGA, dead_cedilla ] };
- key <AB02> { [ x, X, U2248, dead_ogonek ] };
- // unclear whether "approxeq" is 2248 or 2245
- key <AB03> { [ c, C, ccedilla, Ccedilla ] };
- key <AB04> { [ v, V, squareroot, U25CA ] };
- key <AB05> { [ b, B, integral, idotless ] };
- key <AB06> { [ n, N, dead_tilde, U02DC ] };
- key <AB07> { [ m, M, mu, threequarters ] };
- key <AB08> { [ comma, less, lessthanequal, dead_macron ] };
- key <AB09> { [ period, greater, greaterthanequal, dead_breve ] };
- key <AB10> { [ slash, question, division, questiondown ] };
-
- include "level3(ralt_switch)"
-};
-
-// Colemak symbols for xkb on X.Org Server 7.x
-// 2006-01-01 Shai Coleman, http://colemak.com/ . Public domain.
-
-partial alphanumeric_keys
-xkb_symbols "colemak" {
- include "us"
- name[Group1]= "USA - Colemak";
-
- // Alphanumeric section
- key <TLDE> { [ grave, asciitilde, dead_tilde, asciitilde ] };
- key <AE01> { [ 1, exclam, exclamdown, onesuperior ] };
- key <AE02> { [ 2, at, masculine, twosuperior ] };
- key <AE03> { [ 3, numbersign, ordfeminine, threesuperior ] };
- key <AE04> { [ 4, dollar, cent, sterling ] };
- key <AE05> { [ 5, percent, EuroSign, yen ] };
- key <AE06> { [ 6, asciicircum, hstroke, Hstroke ] };
- key <AE07> { [ 7, ampersand, eth, ETH ] };
- key <AE08> { [ 8, asterisk, thorn, THORN ] };
- key <AE09> { [ 9, parenleft, leftsinglequotemark, leftdoublequotemark ] };
- key <AE10> { [ 0, parenright, rightsinglequotemark, rightdoublequotemark ] };
- key <AE11> { [ minus, underscore, endash, emdash ] };
- key <AE12> { [ equal, plus, multiply, division ] };
-
- key <AD01> { [ q, Q, adiaeresis, Adiaeresis ] };
- key <AD02> { [ w, W, aring, Aring ] };
- key <AD03> { [ f, F, atilde, Atilde ] };
- key <AD04> { [ p, P, oslash, Ooblique ] };
- key <AD05> { [ g, G, dead_ogonek, asciitilde ] };
- key <AD06> { [ j, J, dstroke, Dstroke ] };
- key <AD07> { [ l, L, lstroke, Lstroke ] };
- key <AD08> { [ u, U, uacute, Uacute ] };
- key <AD09> { [ y, Y, udiaeresis, Udiaeresis ] };
- key <AD10> { [ semicolon, colon, odiaeresis, Odiaeresis ] };
- key <AD11> { [ bracketleft, braceleft, guillemotleft, 0x1002039 ] };
- key <AD12> { [ bracketright, braceright, guillemotright, 0x100203a ] };
- key <BKSL> { [ backslash, bar, asciitilde, asciitilde ] };
-
- key <AC01> { [ a, A, aacute, Aacute ] };
- key <AC02> { [ r, R, dead_grave, asciitilde ] };
- key <AC03> { [ s, S, ssharp, asciitilde ] };
- key <AC04> { [ t, T, dead_acute, dead_doubleacute ] };
- key <AC05> { [ d, D, dead_diaeresis, asciitilde ] };
- key <AC06> { [ h, H, dead_caron, asciitilde ] };
- key <AC07> { [ n, N, ntilde, Ntilde ] };
- key <AC08> { [ e, E, eacute, Eacute ] };
- key <AC09> { [ i, I, iacute, Iacute ] };
- key <AC10> { [ o, O, oacute, Oacute ] };
- key <AC11> { [ apostrophe, quotedbl, otilde, Otilde ] };
-
- key <AB01> { [ z, Z, ae, AE ] };
- key <AB02> { [ x, X, dead_circumflex, asciitilde ] };
- key <AB03> { [ c, C, ccedilla, Ccedilla ] };
- key <AB04> { [ v, V, oe, OE ] };
- key <AB05> { [ b, B, dead_breve, asciitilde ] };
- key <AB06> { [ k, K, dead_abovering, asciitilde ] };
- key <AB07> { [ m, M, dead_macron, asciitilde ] };
- key <AB08> { [ comma, less, dead_cedilla, asciitilde ] };
- key <AB09> { [ period, greater, dead_abovedot, asciitilde ] };
- key <AB10> { [ slash, question, questiondown, asciitilde ] };
-
- key <CAPS> { [ BackSpace, BackSpace, BackSpace, BackSpace ] };
- key <LSGT> { [ minus, underscore, endash, emdash ] };
- key <SPCE> { [ space, space, space, nobreakspace ] };
-
- include "level3(ralt_switch)"
-};
-
-// I do NOT like dead-keys - the International keyboard as defined by Microsoft
-// doesn't fit my needs. Why use two keystrokes for all simple characters (eg '
-// and <space> generates a single ') just to have an é (eacute) in two strokes
-// as well? I type ' more often than é (eacute).
-//
-// This file works just like a regular keyboard, BUT has all dead-keys
-// accessible at level3 (through AltGr). An ë (ediaeresis) is now: AltGr+"
-// followed by an e. In other words, this keyboard is not international as long
-// as you leave the right Alt key alone.
-//
-// The original MS International keyboard was intended for Latin1 (iso8859-1).
-// With the introduction of iso8859-15, the (important) ligature oe (and OE)
-// became available. I added them next to ae. Because I write ediaeresis more
-// often than registered, I moved registered to be next to copyright and added
-// ediaeresis and idiaeresis. - Adriaan
-
-partial alphanumeric_keys
-xkb_symbols "altgr-intl" {
-
- name[Group1]= "USA - International (AltGr dead keys)";
-
- include "us(intl)"
-
-// five dead keys moved into level3:
-
- key <TLDE> { [ grave, asciitilde, dead_grave, dead_tilde ] };
- key <AC11> { [apostrophe,quotedbl, dead_acute, dead_diaeresis ] };
-
-// diversions from the MS Intl keyboard:
-
- key <AE01> { [ 1, exclam, onesuperior, exclamdown ] };
- key <AD04> { [ r, R, ediaeresis, Ediaeresis ] };
- key <AC07> { [ j, J, idiaeresis, Idiaeresis ] };
- key <AB02> { [ x, X, oe, OE ] };
- key <AB04> { [ v, V, registered, registered ] };
-
-// onequarter etc (not in iso8859-15) moved to get three unshifted deadkeys:
-
- key <AE06> { [ 6, asciicircum, dead_circumflex, onequarter ] };
- key <AE07> { [ 7, ampersand, dead_horn, onehalf ] };
- key <AE08> { [ 8, asterisk, dead_ogonek, threequarters ] };
-
- include "level3(ralt_switch)"
-};
-
-// Intel ClassmatePC Keyboard Layout
-// by Piter PUNK <piterpk@terra.com.br>
-//
-// The keyboard layouts below maps the us(basic), us(intl) and us(alt-intl)
-// to ClassmatePC keyboard. All layouts uses RCTL as level3(switch) since
-// the keyboard doesn't have AltGr key. The EuroSign is engraved at 5 key.
-
-// classmate - us(basic)
-partial alphanumeric_keys
-xkb_symbols "classmate" {
- include "us(basic)"
- name[Group1]= "USA - ClassmatePC";
-
- key <LSGT> { [ backslash, bar, backslash, bar ] };
-
- include "eurosign(5)"
- include "level3(switch)"
-};
-
-// classmate-intl - us(intl)
-// RCTL is generated by Fn+Alt, because that, when trying to access
-// the level3 symbols at 7,8,9,0,u,i,o,p,j,k,l,;,m,. and / we got
-// the keypad keycodes. The keypad is changed to make Fn+Alt+<KP_key>
-// generate the same symbol as the original key.
-partial alphanumeric_keys
-xkb_symbols "classmate-intl" {
- include "us(intl)"
- name[Group1]= "USA - ClassmatePC (International)";
- key.type[Group1]="FOUR_LEVEL";
-
- key <LSGT> { [ backslash, bar, backslash, bar ] };
-
- key <KP7> { [ KP_Home, KP_7,
- onehalf, dead_horn ] };
- key <KP8> { [ KP_Up, KP_8,
- threequarters, dead_ogonek ] };
- key <KP9> { [ KP_Prior, KP_9,
- leftsinglequotemark, dead_breve ] };
- key <KPMU> { [ KP_Multiply, KP_Multiply,
- rightsinglequotemark, dead_abovering ] };
-
- key <KP4> { [ KP_Left, KP_4,
- uacute, Uacute ] };
- key <KP5> { [ KP_Begin, KP_5,
- iacute, Iacute ] };
- key <KP6> { [ KP_Right, KP_6,
- oacute, Oacute ] };
- key <KPSU> { [ KP_Subtract, KP_Subtract,
- odiaeresis, Odiaeresis ] };
-
- key <KP2> { [ KP_Down, KP_2,
- oe, OE ] };
- key <KP3> { [ KP_Next, KP_3,
- oslash, Ooblique ] };
- key <KPAD> { [ KP_Add, KP_Add,
- paragraph, degree ] };
-
- key <KP0> { [ KP_Insert, KP_0,
- mu, mu ] };
- key <KPDL> { [ KP_Delete, KP_Decimal,
- dead_abovedot, dead_caron ] };
- key <KPDV> { [ KP_Divide, KP_Divide,
- questiondown, dead_hook ] };
-
- include "level3(switch)"
-};
-
-// classmate-alt-intl - us(alt-intl)
-// RCTL is generated by Fn+Alt, because that, when trying to access
-// the level3 symbols at 7,8,9,0,u,i,o,p,j,k,l,;,m,. and / we got
-// the keypad keycodes. The keypad is changed to make Fn+Alt+<KP_key>
-// generate the same symbol as the original key.
-partial alphanumeric_keys
-xkb_symbols "classmate-alt-intl" {
- include "us(alt-intl)"
- name[Group1]= "USA - ClassmatePC (Alternative international)";
- key.type[Group1]="FOUR_LEVEL";
-
- key <LSGT> { [ backslash, bar, backslash, bar ] };
-
- key <KPSU> { [ KP_Subtract, KP_Subtract ] };
-
- key <KP9> { [ KP_Prior, KP_9,
- leftsinglequotemark, dead_breve ] };
- key <KPMU> { [ KP_Multiply, KP_Multiply,
- rightsinglequotemark, dead_abovering ] };
-
- key <KPAD> { [ KP_Add, KP_Add,
- dead_ogonek, dead_diaeresis ] };
-
- key <KPDL> { [ KP_Delete, KP_Decimal,
- dead_abovedot, dead_circumflex ] };
- key <KPDV> { [ KP_Divide, KP_Divide,
- dead_hook, dead_hook ] };
-
- include "level3(switch)"
-};
-
-// classmate-altgr-intl - us(altgr-intl)
-// RCTL is generated by Fn+Alt, because that, when trying to access
-// the level3 symbols at 7,8,9,0,u,i,o,p,j,k,l,;,m,. and / we got
-// the keypad keycodes. The keypad is changed to make Fn+Alt+<KP_key>
-// generate the same symbol as the original key.
-partial alphanumeric_keys
-xkb_symbols "classmate-altgr-intl" {
- include "us(altgr-intl)"
- name[Group1]= "USA - ClassmatePC (International Fn+Alt dead-keys)";
- key.type[Group1]="FOUR_LEVEL";
-
- key <LSGT> { [ backslash, bar, backslash, bar ] };
-
- key <KP7> { [ KP_Home, KP_7,
- dead_horn, dead_horn ] };
- key <KP8> { [ KP_Up, KP_8,
- dead_ogonek, dead_ogonek ] };
- key <KP9> { [ KP_Prior, KP_9,
- leftsinglequotemark, dead_breve ] };
- key <KPMU> { [ KP_Multiply, KP_Multiply,
- rightsinglequotemark, dead_abovering ] };
-
- key <KP4> { [ KP_Left, KP_4,
- uacute, Uacute ] };
- key <KP5> { [ KP_Begin, KP_5,
- iacute, Iacute ] };
- key <KP6> { [ KP_Right, KP_6,
- oacute, Oacute ] };
- key <KPSU> { [ KP_Subtract, KP_Subtract,
- odiaeresis, Odiaeresis ] };
-
- key <KP1> { [ KP_End, KP_1,
- idiaeresis, Idiaeresis ] };
- key <KP2> { [ KP_Down, KP_2,
- oe, OE ] };
- key <KP3> { [ KP_Next, KP_3,
- oslash, Ooblique ] };
- key <KPAD> { [ KP_Add, KP_Add,
- paragraph, degree ] };
-
- key <KP0> { [ KP_Insert, KP_0,
- mu, mu ] };
- key <KPDL> { [ KP_Delete, KP_Decimal,
- dead_abovedot, dead_caron ] };
- key <KPDV> { [ KP_Divide, KP_Divide,
- questiondown, dead_hook ] };
-
- include "level3(switch)"
-};
-
-partial alphanumeric_keys
-xkb_symbols "olpc" {
-
- include "us(basic)"
- name[Group1]= "USA";
-
- // OLPC international US English keyboard layout.
- // It's a little different from the usual international layout.
- // See: http://wiki.laptop.org/go/Image:Keyboard_english.png
-
- key <TLDE> { [ grave, asciitilde, dead_grave, dead_tilde ] };
- key <AE01> { [ 1, exclam, exclamdown, exclamdown ] };
- key <AE02> { [ 2, at, notsign, notsign ] };
- key <AE03> { [ 3, numbersign, 0x1000300, 0x1000300 ] }; // combining grave
- key <AE04> { [ 4, dollar, 0x1000301, 0x1000301 ] }; // combining acute
- key <AE05> { [ 5, percent, 0x1000306, 0x1000306 ] }; // combining breve above
- key <AE06> { [ 6,asciicircum, 0x100030A, 0x100030A ] }; // combining ring above
- key <AE07> { [ 7, ampersand, 0x1000302, 0x1000302 ] }; // combining circumflex above
- key <AE08> { [ 8, asterisk, 0x100030C, 0x100030C ] }; // combining caron above
- key <AE09> { [ 9, parenleft, 0x1000307, 0x1000307 ] }; // combining dot above
- key <AE10> { [ 0, parenright, 0x1000308, 0x1000308 ] }; // combining diaeresis above
- key <AE11> { [ minus, underscore, 0x1000304, 0x1000304 ] }; // combining macron above
- key <AE12> { [ equal, plus, 0x1000303, 0x1000303 ] }; // combining tilde above
-
- key <AD01> { [ q, Q, Greek_omega, Greek_OMEGA ] };
- key <AD02> { [ w, W, oslash, Oslash ] };
- key <AD03> { [ e, E, oe, OE ] };
- key <AD04> { [ r, R, 0x1000327, 0x1000327 ] }; // combining cedilla
- key <AD05> { [ t, T, 0x100032E, 0x100032E ] }; // combining breve below
- key <AD06> { [ y, Y, 0x1000325, 0x1000325 ] }; // combining ring below
- key <AD07> { [ u, U, 0x100032D, 0x100032D ] }; // combining circumflex below
- key <AD08> { [ i, I, 0x100032C, 0x100032C ] }; // combining caron below
- key <AD09> { [ o, O, 0x1000323, 0x1000323 ] }; // combining dot below
- key <AD10> { [ p, P, 0x1000324, 0x1000324 ] }; // combining diaeresis below
- key <AD11> { [ bracketleft, braceleft, 0x1000331, 0x1000331 ] }; // combining macron below
- key <AD12> { [bracketright, braceright, 0x1000330, 0x1000330 ] }; // combining tilde below
-
- key <AC01> { [ a, A, ae, AE ] };
- key <AC02> { [ s, S, ssharp, 0x1001E9C ] }; // uppercase S sharp
- key <AC03> { [ d, D, eth, ETH ] };
- key <AC04> { [ f, F, thorn, THORN ] };
- key <AC06> { [ h, H, sterling, sterling ] };
- key <AC07> { [ j, J, EuroSign, EuroSign ] };
- key <AC10> { [ semicolon, colon, masculine, ordfeminine ] };
- key <AC11> { [ apostrophe, quotedbl, currency, currency ] };
- key <BKSL> { [ backslash, bar, section, section ] };
-
- key <AB03> { [ c, C, ccedilla, Ccedilla ] };
- key <AB06> { [ n, N, ntilde, Ntilde ] };
- key <AB07> { [ m, M, mu, mu ] };
- key <AB08> { [ comma, less, guillemotleft, guillemotleft ] };
- key <AB09> { [ period, greater, guillemotright, guillemotright ] };
- key <AB10> { [ slash, question, questiondown, questiondown ] };
-
- key <I219> { [ multiply, division, ISO_Next_Group, ISO_Prev_Group ] };
-
- include "level3(ralt_switch)"
-};
-
-partial alphanumeric_keys
-xkb_symbols "olpc2" {
- include "us(olpc)"
- name[Group1]= "USA - Layout toggle on multiply/divide key";
- include "group(olpc)"
-};
-
-// Based on Cherokee Nation Official Layout
-// http://www.cherokee.org/extras/downloads/font/Keyboard.htm
-
-partial alphanumeric_keys modifier_keys
-xkb_symbols "chr" {
-
- name[Group1]= "USA - Cherokee";
- key.type[group1]="ALPHABETIC";
-
- // Alphanumeric section
- key <TLDE> { [ grave, U13CA ] };
- key <AE01> { [ 1, U13B1 ] };
- key <AE02> { [ 2, U13C7 ] };
- key <AE03> { [ 3, U13E7 ] };
- key <AE04> { [ U13D9, U13B0 ] };
- key <AE05> { [ U13E6, U13B9 ] };
- key <AE06> { [ U13DC, U13DD ] };
- key <AE07> { [ U13CB, U13E1 ] };
- key <AE08> { [ U13D6, U13BA ] };
- key <AE09> { [ U13D2, parenleft ] };
- key <AE10> { [ U13C4, parenright ] };
- key <AE11> { [ U13BF, U13BC ] };
- key <AE12> { [ U13F3, U13BD ] };
-
- key <AD01> { [ U13AA, U13C6 ] };
- key <AD02> { [ U13B3, U13EB ] };
- key <AD03> { [ U13A1, U13E3 ] };
- key <AD04> { [ U13DB, U13CF ] };
- key <AD05> { [ U13D4, U13D8 ] };
- key <AD06> { [ U13EF, U13F2 ] };
- key <AD07> { [ U13A4, U13AD ] };
- key <AD08> { [ U13A2, U13F1 ] };
- key <AD09> { [ U13A3, U13EC ] };
- key <AD10> { [ U13C1, U13EA ] };
- key <AD11> { [ U13D5, U13D1 ] };
- key <AD12> { [ U13B6, U13E4 ] };
- key <BKSL> { [ U13E9, U13EE ] };
-
- key <AC01> { [ U13A0, U13CC ] };
- key <AC02> { [ U13CD, U13CE ] };
- key <AC03> { [ U13D7, U13D0 ] };
- key <AC04> { [ U13A9, U13C8 ] };
- key <AC05> { [ U13A6, U13E5 ] };
- key <AC06> { [ U13AF, U13B2 ] };
- key <AC07> { [ U13DA, U13AB ] };
- key <AC08> { [ U13B8, U13A7 ] };
- key <AC09> { [ U13B5, U13AE ] };
- key <AC10> { [ U13E8, U13E0 ] };
- key <AC11> { [ apostrophe, quotedbl ] };
-
- key <AB01> { [ U13AC, U13C3 ] };
- key <AB02> { [ U13F4, U13ED ] };
- key <AB03> { [ U13D3, U13DF ] };
- key <AB04> { [ U13A5, U13DE ] };
- key <AB05> { [ U13A8, U13F0 ] };
- key <AB06> { [ U13BE, U13BB ] };
- key <AB07> { [ U13C5, U13B7 ] };
- key <AB08> { [ comma, U13E2 ] };
- key <AB09> { [ period, U13B4 ] };
- key <AB10> { [ U13C2, U13C9 ] };
-
- // End alphanumeric section
-};
-
-// Serbian charecters added as third level symbols to US keyboard layout.
-
-partial alphanumeric_keys
-xkb_symbols "hbs" {
-
- name[Group1]= "USA - Serbo-Croatian";
-
- include "us"
-
- key <TLDE> { [ grave, asciitilde ] };
- key <AE06> { [ 6, dead_caron, asciicircum, asciicircum ] };
- key <AC09> { [ l, L, U1C9, U1C8 ] };
- key <AB06> { [ n, N, U1CC, U1CB ] };
- key <AB01> { [ z, Z, U1C6, U1C5 ] };
- key <AD03> { [ e, E, EuroSign, cent ] };
- key <AC03> { [ d, D, dstroke, Dstroke ] };
- key <AC11> { [ dead_acute, quotedbl, apostrophe, apostrophe ] };
- key <SPCE> { [ space, space, nobreakspace, nobreakspace ] };
- key <AB08> { [ comma, less, NoSymbol, guillemotright ] };
- key <AB09> { [ period, greater, NoSymbol, guillemotleft ] };
-
- include "level3(ralt_switch)"
-};
-
-//based on http://upload.wikimedia.org/wikipedia/commons/1/18/T-Mobile_G1_launch_event_2.jpg
-partial alphanumeric_keys
-xkb_symbols "htcdream" {
- include "inet(htcdream)"
- name[Group1]= "USA - htcdream";
-
- //second row
- key <AD01> { [ q, Q, Tab, Tab ] };
- key <AD02> { [ w, W, grave, grave ] };
- key <AD03> { [ e, E, underscore, underscore ] };
- key <AD04> { [ r, R, sterling, sterling ] };
- key <AD05> { [ t, T, EuroSign, EuroSign ] };
- key <AD06> { [ y, Y, division, division ] };
- key <AD07> { [ u, U, multiply, multiply ] };
- key <AD08> { [ i, I, minus, minus ] };
- key <AD09> { [ o, O, plus, plus ] };
- key <AD10> { [ p, P, equal, equal ] };
-
- //third row
- key <AC01> { [ a, A, NoSymbol, NoSymbol ] };
- key <AC02> { [ s, S, bar, bar ] };
- key <AC03> { [ d ,D, backslash, backslash ] };
- key <AC04> { [ f, F, braceleft, braceleft ] };
- key <AC05> { [ g, G, braceright, braceright ] };
- key <AC06> { [ h, H, colon, colon ] };
- key <AC07> { [ j, J, semicolon, semicolon ] };
- key <AC08> { [ k, K, quotedbl, quotedbl ] };
- key <AC09> { [ l, L, apostrophe, apostrophe ] };
-
- //forth row
- key <AB01> { [ z, Z, NoSymbol, NoSymbol ] };
- key <AB02> { [ x, X, NoSymbol, NoSymbol ] };
- key <AB03> { [ c, C, NoSymbol, NoSymbol ] };
- key <AB04> { [ v, V, bracketleft, bracketleft ] };
- key <AB05> { [ b, B, bracketright, bracketright ] };
- key <AB06> { [ n, N, less, less ] };
- key <AB07> { [ m, M, greater, greater ] };
- key <AB08> { [ comma, comma, question, question ] };
-
- //fifth row
- key <FK15> { [ at, at, asciitilde, asciitilde ] };
-
- include "level3(alt_switch)"
-};
+default +partial alphanumeric_keys modifier_keys +xkb_symbols "basic" { + + name[Group1]= "USA"; + + // Alphanumeric section + key <TLDE> { [ grave, asciitilde ] }; + key <AE01> { [ 1, exclam ] }; + key <AE02> { [ 2, at ] }; + key <AE03> { [ 3, numbersign ] }; + key <AE04> { [ 4, dollar ] }; + key <AE05> { [ 5, percent ] }; + key <AE06> { [ 6, asciicircum ] }; + key <AE07> { [ 7, ampersand ] }; + key <AE08> { [ 8, asterisk ] }; + key <AE09> { [ 9, parenleft ] }; + key <AE10> { [ 0, parenright ] }; + key <AE11> { [ minus, underscore ] }; + key <AE12> { [ equal, plus ] }; + + key <AD01> { [ q, Q ] }; + key <AD02> { [ w, W ] }; + key <AD03> { [ e, E ] }; + key <AD04> { [ r, R ] }; + key <AD05> { [ t, T ] }; + key <AD06> { [ y, Y ] }; + key <AD07> { [ u, U ] }; + key <AD08> { [ i, I ] }; + key <AD09> { [ o, O ] }; + key <AD10> { [ p, P ] }; + key <AD11> { [ bracketleft, braceleft ] }; + key <AD12> { [ bracketright, braceright ] }; + + key <AC01> { [ a, A ] }; + key <AC02> { [ s, S ] }; + key <AC03> { [ d, D ] }; + key <AC04> { [ f, F ] }; + key <AC05> { [ g, G ] }; + key <AC06> { [ h, H ] }; + key <AC07> { [ j, J ] }; + key <AC08> { [ k, K ] }; + key <AC09> { [ l, L ] }; + key <AC10> { [ semicolon, colon ] }; + key <AC11> { [ apostrophe, quotedbl ] }; + + key <AB01> { [ z, Z ] }; + key <AB02> { [ x, X ] }; + key <AB03> { [ c, C ] }; + key <AB04> { [ v, V ] }; + key <AB05> { [ b, B ] }; + key <AB06> { [ n, N ] }; + key <AB07> { [ m, M ] }; + key <AB08> { [ comma, less ] }; + key <AB09> { [ period, greater ] }; + key <AB10> { [ slash, question ] }; + + key <BKSL> { [ backslash, bar ] }; + // End alphanumeric section +}; + +partial alphanumeric_keys +xkb_symbols "euro" { + + name[Group1]= "USA - With EuroSign on 5"; + + include "us(basic)" + + include "eurosign(5)" + + include "level3(ralt_switch)" +}; + + +partial alphanumeric_keys +xkb_symbols "intl" { + + name[Group1]= "USA - International (with dead keys)"; + + include "us(basic)" + + // Alphanumeric section + key <TLDE> { [dead_grave, dead_tilde, grave, asciitilde ] }; + key <AE01> { [ 1, exclam, exclamdown, onesuperior ] }; + key <AE02> { [ 2, at, twosuperior, dead_doubleacute ] }; + key <AE03> { [ 3, numbersign, threesuperior, dead_macron ] }; + key <AE04> { [ 4, dollar, currency, sterling ] }; + key <AE05> { [ 5, percent, EuroSign, dead_cedilla ] }; + key <AE06> { [ 6, dead_circumflex, onequarter, asciicircum ] }; + key <AE07> { [ 7, ampersand, onehalf, dead_horn ] }; + key <AE08> { [ 8, asterisk, threequarters, dead_ogonek ] }; + key <AE09> { [ 9, parenleft, leftsinglequotemark, dead_breve ] }; + key <AE10> { [ 0, parenright, rightsinglequotemark, dead_abovering ] }; + key <AE11> { [ minus, underscore, yen, dead_belowdot ] }; + key <AE12> { [ equal, plus, multiply, division ] }; + + key <AD01> { [ q, Q, adiaeresis, Adiaeresis ] }; + key <AD02> { [ w, W, aring, Aring ] }; + key <AD03> { [ e, E, eacute, Eacute ] }; + key <AD04> { [ r, R, registered, registered ] }; + key <AD05> { [ t, T, thorn, THORN ] }; + key <AD06> { [ y, Y, udiaeresis, Udiaeresis ] }; + key <AD07> { [ u, U, uacute, Uacute ] }; + key <AD08> { [ i, I, iacute, Iacute ] }; + key <AD09> { [ o, O, oacute, Oacute ] }; + key <AD10> { [ p, P, odiaeresis, Odiaeresis ] }; + key <AD11> { [ bracketleft, braceleft, guillemotleft, leftdoublequotemark ] }; + key <AD12> { [bracketright, braceright, guillemotright, rightdoublequotemark ] }; + + key <AC01> { [ a, A, aacute, Aacute ] }; + key <AC02> { [ s, S, ssharp, section ] }; + key <AC03> { [ d, D, eth, ETH ] }; + key <AC04> { [ f, F, f, F ] }; + key <AC05> { [ g, G, g, G ] }; + key <AC06> { [ h, H, h, H ] }; + key <AC07> { [ j, J, j, J ] }; + key <AC08> { [ k, K, oe, OE ] }; + + key <AC09> { [ l, L, oslash, Ooblique ] }; + key <AC10> { [ semicolon, colon, paragraph, degree ] }; + key <AC11> { [dead_acute, dead_diaeresis, apostrophe, quotedbl ] }; + + key <AB01> { [ z, Z, ae, AE ] }; + key <AB02> { [ x, X, x, X ] }; + key <AB03> { [ c, C, copyright, cent ] }; + key <AB04> { [ v, V, v, V ] }; + key <AB05> { [ b, B, b, B ] }; + key <AB06> { [ n, N, ntilde, Ntilde ] }; + key <AB07> { [ m, M, mu, mu ] }; + key <AB08> { [ comma, less, ccedilla, Ccedilla ] }; + key <AB09> { [ period, greater, dead_abovedot, dead_caron ] }; + key <AB10> { [ slash, question, questiondown, dead_hook ] }; + key <BKSL> { [ backslash, bar, notsign, brokenbar ] }; + + include "level3(ralt_switch)" +}; + +// Based on symbols/us_intl keyboard map: +// Dead-keys definition for a very simple US/ASCII layout. +// by Conectiva (http://www.conectiva.com.br) +// modified by Ricardo Y. Igarashi (iga@that.com.br) + +// Added the following deadkeys, to make it truly international: +// +// dead_macron: on AltGr-minus +// dead_breve: on AltGr-parenleft +// dead_abovedot: on AltGr-period +// dead_abovering: on AltGr-0 +// dead_doubleacute: on AltGr-equal (as quotedbl is already used) +// dead_caron: on AltGr-less (AltGr-shift-comma) +// dead_cedilla: on AltGr-comma +// dead_ogonek: on AltGr-semicolon +// dead_belowdot: on AltGr-underscore (AltGr-shift-minus) +// dead_hook: on AltGr-question +// dead_horn: on AltGr-plus (AltGr-shift-equal) +// dead_diaeresis: on AltGr-colon (Alt-shift-semicolon) +// +// those were already there: +// dead_grave +// dead_acute +// dead_circumflex +// dead_tilde +// dead_diaeresis + +partial alphanumeric_keys +xkb_symbols "alt-intl" { + + name[Group1]= "USA - Alternative international"; + + include "us" + + key <TLDE> { [ dead_grave, dead_tilde, grave, asciitilde ] }; + key <AE05> { [ 5, percent, EuroSign ] }; + key <AE06> { [ 6, dead_circumflex, asciicircum, asciicircum ] }; + key <AE09> { [ 9, parenleft, leftsinglequotemark, dead_breve ] }; + key <AE10> { [ 0, parenright, rightsinglequotemark, dead_abovering ] }; + key <AE11> { [ minus, underscore, dead_macron, dead_belowdot ] }; + key <AE12> { [ equal, plus, dead_doubleacute, dead_horn ] }; + + key <AD03> { [ e, E, EuroSign, cent ] }; + + key <AC10> { [ semicolon, colon, dead_ogonek, dead_diaeresis ] }; + key <AC11> { [ dead_acute, dead_diaeresis, apostrophe, quotedbl ] }; + + key <AB08> { [ comma, less, dead_cedilla, dead_caron ] }; + key <AB09> { [ period, greater, dead_abovedot, dead_circumflex ] }; + key <AB10> { [ slash, question, dead_hook, dead_hook ] }; + + include "level3(ralt_switch)" +}; + +// based on a keyboard map from an 'xkb/symbols/dk' file + +partial alphanumeric_keys +xkb_symbols "dvorak" { + + name[Group1]= "USA - Dvorak"; + + // Alphanumeric section + + key <TLDE> { [ grave, asciitilde, dead_grave, dead_tilde ] }; + + key <AE01> { [ 1, exclam ] }; + key <AE02> { [ 2, at ] }; + key <AE03> { [ 3, numbersign ] }; + key <AE04> { [ 4, dollar ] }; + key <AE05> { [ 5, percent ] }; + key <AE06> { [ 6, asciicircum, dead_circumflex, dead_circumflex ] }; + key <AE07> { [ 7, ampersand ] }; + key <AE08> { [ 8, asterisk ] }; + key <AE09> { [ 9, parenleft, dead_grave] }; + key <AE10> { [ 0, parenright ] }; + key <AE11> { [ bracketleft, braceleft ] }; + key <AE12> { [ bracketright, braceright, dead_tilde] }; + + key <AD01> { [ apostrophe, quotedbl, dead_acute, dead_diaeresis ] }; + key <AD02> { [ comma, less, dead_cedilla, dead_caron ] }; + key <AD03> { [ period, greater, dead_abovedot, periodcentered ] }; + key <AD04> { [ p, P ] }; + key <AD05> { [ y, Y ] }; + key <AD06> { [ f, F ] }; + key <AD07> { [ g, G ] }; + key <AD08> { [ c, C ] }; + key <AD09> { [ r, R ] }; + key <AD10> { [ l, L ] }; + key <AD11> { [ slash, question ] }; + key <AD12> { [ equal, plus ] }; + + key <AC01> { [ a, A ] }; + key <AC02> { [ o, O ] }; + key <AC03> { [ e, E ] }; + key <AC04> { [ u, U ] }; + key <AC05> { [ i, I ] }; + key <AC06> { [ d, D ] }; + key <AC07> { [ h, H ] }; + key <AC08> { [ t, T ] }; + key <AC09> { [ n, N ] }; + key <AC10> { [ s, S ] }; + key <AC11> { [ minus, underscore ] }; + + key <AB01> { [ semicolon, colon, dead_ogonek, dead_doubleacute ] }; + key <AB02> { [ q, Q ] }; + key <AB03> { [ j, J ] }; + key <AB04> { [ k, K ] }; + key <AB05> { [ x, X ] }; + key <AB06> { [ b, B ] }; + key <AB07> { [ m, M ] }; + key <AB08> { [ w, W ] }; + key <AB09> { [ v, V ] }; + key <AB10> { [ z, Z ] }; + + key <BKSL> { [ backslash, bar ] }; +}; + +// Dvorak international with dead keys +// Olivier Mehani (shtrom-xorg@ssji.net) +// Reproduce the per-key mapping of us(intl) for the dvorak layout +// aka "I just swapped my keys over" +partial alphanumeric_keys +xkb_symbols "dvorak-intl" { + + name[Group1]= "USA - Dvorak international (with dead keys)"; + + include "us(dvorak)" + + key <TLDE> { [dead_grave, dead_tilde, grave, asciitilde ] }; + + key <AE01> { [ 1, exclam, exclamdown, onesuperior ] }; + key <AE02> { [ 2, at, twosuperior, dead_doubleacute ] }; + key <AE03> { [ 3, numbersign, threesuperior, dead_macron ] }; + key <AE04> { [ 4, dollar, currency, sterling ] }; + key <AE05> { [ 5, percent, EuroSign, dead_cedilla ] }; + key <AE06> { [ 6, dead_circumflex, onequarter, asciicircum ] }; + key <AE07> { [ 7, ampersand, onehalf, dead_horn ] }; + key <AE08> { [ 8, asterisk, threequarters, dead_ogonek ] }; + key <AE09> { [ 9, parenleft, leftsinglequotemark, dead_breve ] }; + key <AE10> { [ 0, parenright, rightsinglequotemark, dead_abovering ] }; + key <AE11> { [ bracketleft, braceleft, guillemotleft, leftdoublequotemark ] }; + key <AE12> { [bracketright, braceright, guillemotright, rightdoublequotemark ] }; + + key <AD01> { [dead_acute, dead_diaeresis, apostrophe, quotedbl ] }; + key <AD02> { [ comma, less, ccedilla, Ccedilla ] }; + key <AD03> { [ period, greater, dead_abovedot, dead_caron ] }; + key <AD04> { [ p, P, odiaeresis, Odiaeresis ] }; + key <AD05> { [ y, Y, udiaeresis, Udiaeresis ] }; + // key <AD06> { [ f, F ] }; + // key <AD07> { [ g, G ] }; + key <AD08> { [ c, C, copyright, cent ] }; + key <AD09> { [ r, R, registered, registered ] }; + key <AD10> { [ l, L, oslash, Ooblique ] }; + key <AD11> { [ slash, question, questiondown, dead_hook ] }; + // key <AD12> { [ equal, plus, multiply, division ] }; + + key <AC01> { [ a, A, aacute, Aacute ] }; + key <AC02> { [ o, O, oacute, Oacute ] }; + key <AC03> { [ e, E, eacute, Eacute ] }; + key <AC04> { [ u, U, uacute, Uacute ] }; + key <AC05> { [ i, I, iacute, Iacute ] }; + key <AC06> { [ d, D, eth, ETH ] }; + // key <AC07> { [ h, H ] }; + key <AC08> { [ t, T, thorn, THORN ] }; + key <AC09> { [ n, N, ntilde, Ntilde ] }; + key <AC10> { [ s, S, ssharp, section ] }; + // key <AC11> { [ minus, underscore, yen, dead_belowdot ] }; + + key <AB01> { [ semicolon, colon, paragraph, degree ] }; + key <AB02> { [ q, Q, adiaeresis, Adiaeresis ] }; + // key <AB03> { [ j, J ] }; + key <AB04> { [ k, K, oe, OE ] }; + // key <AB05> { [ x, X ] }; + // key <AB06> { [ b, B ] }; + key <AB07> { [ m, M, mu, mu ] }; + key <AB08> { [ w, W, aring, Aring ] }; + // key <AB09> { [ v, V ] }; + key <AB10> { [ z, Z, ae, AE ] }; + + key <BKSL> { [ backslash, bar, notsign, brokenbar ] }; + + include "level3(ralt_switch)" +}; + +// Dvorak international without dead keys +// Stephane Magnenat (stephane at magnenat dot net, http://stephane.magnenat.net) +// Based on information from http://www.poupinou.org/dvorak/index.html +// +// ` 1 2 3 4 5 6 7 8 9 0 [ ] \ +// € +// +// ' , . p y f g c r l / = +// ä ê ë ü ç +// +// a o e u i d h t n s - +// à ô é û î ß +// +// ; q j k x b m w v z +// â ö è ù ï + +partial alphanumeric_keys +xkb_symbols "dvorak-alt-intl" { + + name[Group1]= "USA - Dvorak alternative international (no dead keys)"; + + include "us(dvorak)" + + key <AE04> { [ 4, dollar, EuroSign ] }; + + key <AD02> { [ comma, less, adiaeresis, dead_caron ] }; + key <AD03> { [ period, greater, ecircumflex, periodcentered ] }; + key <AD04> { [ p, P, ediaeresis, dead_cedilla ] }; + key <AD05> { [ y, Y, udiaeresis ] }; + key <AD08> { [ c, C, ccedilla, dead_abovedot ] }; + + key <AC01> { [ a, A, agrave ] }; + key <AC02> { [ o, O, ocircumflex ] }; + key <AC03> { [ e, E, eacute ] }; + key <AC04> { [ u, U, ucircumflex ] }; + key <AC05> { [ i, I, icircumflex ] }; + key <AC10> { [ s, S, ssharp ] }; + + key <AB01> { [ semicolon, colon, acircumflex ] }; + key <AB02> { [ q, Q, odiaeresis, dead_ogonek ] }; + key <AB03> { [ j, J, egrave, dead_doubleacute ] }; + key <AB04> { [ k, K, ugrave ] }; + key <AB05> { [ x, X, idiaeresis ] }; + + include "level3(ralt_switch)" +}; + +// Left and right handed dvorak layouts +// by sqweek <sqweek@gmail.com> 2006-01-30 +// Based on the corresponding layouts in the console-tools package. +partial alphanumeric_keys +xkb_symbols "dvorak-l" { + + include "us(dvorak)" + name[Group1]= "USA - Left handed Dvorak"; + + key <AE01> { [ bracketleft, braceleft ] }; + key <AE02> { [ bracketright, braceright ] }; + key <AE03> { [ slash, question ] }; + key <AE04> { [ p, P ] }; + key <AE05> { [ f, F ] }; + key <AE06> { [ m, M ] }; + key <AE07> { [ l, L ] }; + key <AE08> { [ j, J ] }; + key <AE09> { [ 4, dollar ] }; + key <AE10> { [ 3, numbersign ] }; + key <AE11> { [ 2, at ] }; + key <AE12> { [ 1, exclam ] }; + + key <AD01> { [ semicolon, colon ] }; + key <AD02> { [ q, Q ] }; + key <AD03> { [ b, B ] }; + key <AD04> { [ y, Y ] }; + key <AD05> { [ u, U ] }; + key <AD06> { [ r, R ] }; + key <AD07> { [ s, S ] }; + key <AD08> { [ o, O ] }; + key <AD09> { [ period, greater ] }; + key <AD10> { [ 6, asciicircum ] }; + key <AD11> { [ 5, percent ] }; + key <AD12> { [ equal, plus ] }; + + key <AC01> { [ minus, underscore ] }; + key <AC02> { [ k, K ] }; + key <AC03> { [ c, C ] }; + key <AC04> { [ d, D ] }; + key <AC05> { [ t, T ] }; + key <AC06> { [ h, H ] }; + key <AC07> { [ e, E ] }; + key <AC08> { [ a, A ] }; + key <AC09> { [ z, Z ] }; + key <AC10> { [ 8, asterisk ] }; + key <AC11> { [ 7, ampersand ] }; + + key <AB01> { [ apostrophe, quotedbl ] }; + key <AB02> { [ x, X ] }; + key <AB03> { [ g, G ] }; + key <AB04> { [ v, V ] }; + key <AB05> { [ w, W ] }; + key <AB06> { [ n, N ] }; + key <AB07> { [ i, I ] }; + key <AB08> { [ comma, less ] }; + key <AB09> { [ 0, parenright ] }; + key <AB10> { [ 9, parenleft ] }; +}; + +partial alphanumeric_keys +xkb_symbols "dvorak-r" { + + include "us(dvorak)" + name[Group1]= "USA - Right handed Dvorak"; + + key <AE01> { [ 1, exclam ] }; + key <AE02> { [ 2, at ] }; + key <AE03> { [ 3, numbersign ] }; + key <AE04> { [ 4, dollar ] }; + key <AE05> { [ j, J ] }; + key <AE06> { [ l, L ] }; + key <AE07> { [ m, M ] }; + key <AE08> { [ f, F ] }; + key <AE09> { [ p, P ] }; + key <AE10> { [ slash, question ] }; + key <AE11> { [ bracketleft, braceleft ] }; + key <AE12> { [ bracketright, braceright ] }; + + key <AD01> { [ 5, percent ] }; + key <AD02> { [ 6, asciicircum ] }; + key <AD03> { [ q, Q ] }; + key <AD04> { [ period, greater ] }; + key <AD05> { [ o, O ] }; + key <AD06> { [ r, R ] }; + key <AD07> { [ s, S ] }; + key <AD08> { [ u, U ] }; + key <AD09> { [ y, Y ] }; + key <AD10> { [ b, B ] }; + key <AD11> { [ semicolon, colon ] }; + key <AD12> { [ equal, plus ] }; + + key <AC01> { [ 7, ampersand ] }; + key <AC02> { [ 8, asterisk ] }; + key <AC03> { [ z, Z ] }; + key <AC04> { [ a, A ] }; + key <AC05> { [ e, E ] }; + key <AC06> { [ h, H ] }; + key <AC07> { [ t, T ] }; + key <AC08> { [ d, D ] }; + key <AC09> { [ c, C ] }; + key <AC10> { [ k, K ] }; + key <AC11> { [ minus, underscore ] }; + + key <AB01> { [ 9, parenleft ] }; + key <AB02> { [ 0, parenright ] }; + key <AB03> { [ x, X ] }; + key <AB04> { [ comma, less ] }; + key <AB05> { [ i, I ] }; + key <AB06> { [ n, N ] }; + key <AB07> { [ w, W ] }; + key <AB08> { [ v, V ] }; + key <AB09> { [ g, G ] }; + key <AB10> { [ apostrophe, quotedbl ] }; +}; + +// Classic dvorak layout +// by Piter Punk <piterpk@terra.com.br> - 2006-07-06 +// Based on dvorak layout and e-mail from Russel L. Harris rlharris@oplink.net +// on xorg list. +partial alphanumeric_keys +xkb_symbols "dvorak-classic" { + + name[Group1]= "USA - Classic Dvorak"; + + // Alphanumeric section + + key <TLDE> { [ grave, asciitilde, dead_grave, dead_tilde ] }; + + key <AE01> { [ bracketleft, braceleft ] }; + key <AE02> { [ 7, ampersand ] }; + key <AE03> { [ 5, percent ] }; + key <AE04> { [ 3, numbersign ] }; + key <AE05> { [ 1, exclam ] }; + key <AE06> { [ 9, parenleft, dead_grave] }; + key <AE07> { [ 0, parenright ] }; + key <AE08> { [ 2, at ] }; + key <AE09> { [ 4, dollar ] }; + key <AE10> { [ 6, asciicircum, dead_circumflex, dead_circumflex ] }; + key <AE11> { [ 8, asterisk ] }; + key <AE12> { [ bracketright, braceright, dead_tilde] }; + + key <AD01> { [ slash, question ] }; + key <AD02> { [ comma, less, dead_cedilla, dead_caron ] }; + key <AD03> { [ period, greater, dead_abovedot, periodcentered ] }; + key <AD04> { [ p, P ] }; + key <AD05> { [ y, Y ] }; + key <AD06> { [ f, F ] }; + key <AD07> { [ g, G ] }; + key <AD08> { [ c, C ] }; + key <AD09> { [ r, R ] }; + key <AD10> { [ l, L ] }; + key <AD11> { [ apostrophe, quotedbl, dead_acute, dead_diaeresis ] }; + key <AD12> { [ equal, plus ] }; + + key <AC01> { [ a, A ] }; + key <AC02> { [ o, O ] }; + key <AC03> { [ e, E ] }; + key <AC04> { [ u, U ] }; + key <AC05> { [ i, I ] }; + key <AC06> { [ d, D ] }; + key <AC07> { [ h, H ] }; + key <AC08> { [ t, T ] }; + key <AC09> { [ n, N ] }; + key <AC10> { [ s, S ] }; + key <AC11> { [ minus, underscore ] }; + + key <AB01> { [ semicolon, colon, dead_ogonek, dead_doubleacute ] }; + key <AB02> { [ q, Q ] }; + key <AB03> { [ j, J ] }; + key <AB04> { [ k, K ] }; + key <AB05> { [ x, X ] }; + key <AB06> { [ b, B ] }; + key <AB07> { [ m, M ] }; + key <AB08> { [ w, W ] }; + key <AB09> { [ v, V ] }; + key <AB10> { [ z, Z ] }; + key <BKSL> { [ backslash, bar ] }; +}; + +// Programmer Dvorak, by Roland Kaufmann <rlndkfmn at gmail dot com> +// License: BSD, available at <http://www.kaufmann.no/roland/dvorak/license.html> +// Main features: Numbers are in shift position (like French), symbols have been +// placed in locations that give good hand-alternation and finger rolling with +// symbols that usually follows, accented characters are possible for I18N. +partial alphanumeric_keys +xkb_symbols "dvp" { + include "us(dvorak)" + + name[Group1] = "USA - Programmer Dvorak"; + + // Unmodified Shift AltGr Shift+AltGr + // symbols row, left side + key <TLDE> { [ dollar, asciitilde, dead_tilde ] }; + key <AE01> { [ ampersand, percent ] }; + key <AE02> { [ bracketleft, 7, currency ], type[Group1] = "FOUR_LEVEL_ALPHABETIC" }; + key <AE03> { [ braceleft, 5, cent ], type[Group1] = "FOUR_LEVEL_ALPHABETIC" }; + key <AE04> { [ braceright, 3, yen ], type[Group1] = "FOUR_LEVEL_ALPHABETIC" }; + key <AE05> { [ parenleft, 1, EuroSign ], type[Group1] = "FOUR_LEVEL_ALPHABETIC" }; + key <AE06> { [ equal, 9, sterling ], type[Group1] = "FOUR_LEVEL_ALPHABETIC" }; + + // symbols row, right side + key <AE07> { [ asterisk, 0 ], type[Group1] = "FOUR_LEVEL_ALPHABETIC" }; + key <AE08> { [ parenright, 2, onehalf ], type[Group1] = "FOUR_LEVEL_ALPHABETIC" }; + key <AE09> { [ plus, 4 ], type[Group1] = "FOUR_LEVEL_ALPHABETIC" }; + key <AE10> { [ bracketright, 6 ], type[Group1] = "FOUR_LEVEL_ALPHABETIC" }; + key <AE11> { [ exclam, 8, exclamdown ], type[Group1] = "FOUR_LEVEL_ALPHABETIC" }; + key <AE12> { [ numbersign, grave, dead_grave ] }; + key <BKSP> { [ BackSpace ] }; + + // upper row, left side + key <AD01> { [ semicolon, colon, dead_diaeresis ] }; + key <AD02> { [ comma, less, guillemotleft ] }; + key <AD03> { [ period, greater, guillemotright ] }; + key <AD04> { [ p, P, paragraph, section ] }; + key <AD05> { [ y, Y, udiaeresis, Udiaeresis ] }; + + // upper row, right side + key <AD08> { [ c, C, ccedilla, Ccedilla ] }; + key <AD09> { [ r, R, registered, trademark ] }; + key <AD11> { [ slash, question, questiondown ] }; + key <AD12> { [ at, asciicircum, dead_circumflex, dead_caron ] }; + + // home row, left side + key <AC01> { [ a, A, aring, Aring ] }; + key <AC02> { [ o, O, oslash, Ooblique ] }; + key <AC03> { [ e, E, ae, AE ] }; + key <AC04> { [ u, U, eacute, Eacute ] }; + + // home row, right side + key <AC06> { [ d, D, eth, ETH ] }; + key <AC07> { [ h, H, dead_acute ] }; + key <AC08> { [ t, T, thorn, THORN ] }; + key <AC09> { [ n, N, ntilde, Ntilde ] }; + key <AC10> { [ s, S, ssharp ] }; + key <AC11> { [ minus, underscore, hyphen ], type[Group1] = "FOUR_LEVEL_ALPHABETIC" }; + key <BKSL> { [ backslash, bar ] }; + + // lower row, left side + key <AB01> { [ apostrophe, quotedbl, dead_acute ] }; +}; + +// phonetic layout for Russian letters on an US keyboard +// by Ivan Popov <pin@konvalo.org> 2005-07-17 + +// level3 modifier is a shortcut to the "us" meaning of the keys where +// we place cyrillic letters, handy for accessing the corresponding +// punctuation marks. +// It is important to have access to punctuation marks, and the rest of +// alphabetical keys are added for being consequent so that the users +// can expect the level3 modifier to give what the key label shows. + +partial alphanumeric_keys +xkb_symbols "rus" { + + name[Group1]= "USA - Russian phonetic"; + + include "us(basic)" + +key.type[group1]="FOUR_LEVEL_ALPHABETIC"; + + key <LatA> { [ Cyrillic_a, Cyrillic_A ] }; + key <LatB> { [ Cyrillic_be, Cyrillic_BE ] }; + key <LatW> { [ Cyrillic_ve, Cyrillic_VE ] }; + key <LatG> { [ Cyrillic_ghe, Cyrillic_GHE ] }; + key <LatD> { [ Cyrillic_de, Cyrillic_DE ] }; + key <LatE> { [ Cyrillic_ie, Cyrillic_IE ] }; + key <TLDE> { [ Cyrillic_io, Cyrillic_IO, grave, asciitilde ] }; + key <LatV> { [ Cyrillic_zhe, Cyrillic_ZHE ] }; + key <LatZ> { [ Cyrillic_ze, Cyrillic_ZE ] }; + key <LatI> { [ Cyrillic_i, Cyrillic_I ] }; + key <LatJ> { [ Cyrillic_shorti, Cyrillic_SHORTI ] }; + key <LatK> { [ Cyrillic_ka, Cyrillic_KA ] }; + key <LatL> { [ Cyrillic_el, Cyrillic_EL ] }; + key <LatM> { [ Cyrillic_em, Cyrillic_EM ] }; + key <LatN> { [ Cyrillic_en, Cyrillic_EN ] }; + key <LatO> { [ Cyrillic_o, Cyrillic_O ] }; + key <LatP> { [ Cyrillic_pe, Cyrillic_PE ] }; + key <LatR> { [ Cyrillic_er, Cyrillic_ER ] }; + key <LatS> { [ Cyrillic_es, Cyrillic_ES ] }; + key <LatT> { [ Cyrillic_te, Cyrillic_TE ] }; + key <LatU> { [ Cyrillic_u, Cyrillic_U ] }; + key <LatF> { [ Cyrillic_ef, Cyrillic_EF ] }; + key <LatH> { [ Cyrillic_ha, Cyrillic_HA ] }; + key <LatC> { [ Cyrillic_tse, Cyrillic_TSE ] }; + key <AC10> { [ Cyrillic_che, Cyrillic_CHE, semicolon, colon ] }; + key <AD11> { [ Cyrillic_sha, Cyrillic_SHA, bracketleft, braceleft] }; + key <AD12> { [ Cyrillic_shcha, Cyrillic_SHCHA, bracketright, braceright ] }; + key <AE12> { [ Cyrillic_hardsign, Cyrillic_HARDSIGN, equal, plus ] }; + key <LatY> { [ Cyrillic_yeru, Cyrillic_YERU ] }; + key <LatX> { [ Cyrillic_softsign, Cyrillic_SOFTSIGN ] }; + key <BKSL> { [ Cyrillic_e, Cyrillic_E, backslash, bar ] }; + key <AC11> { [ Cyrillic_yu, Cyrillic_YU, apostrophe, quotedbl ] }; + key <LatQ> { [ Cyrillic_ya, Cyrillic_YA ] }; + + include "level3(ralt_switch)" +}; + +partial alphanumeric_keys +xkb_symbols "mac" { + + include "us(basic)" + name[Group1]= "USA - Macintosh"; + key.type[group1]="FOUR_LEVEL"; + + // Slightly improvised from http://homepage.mac.com/thgewecke/kblayout.jpg + key <LSGT> { [ section, plusminus, section, plusminus ] }; + key <TLDE> { [ grave, asciitilde, dead_grave, dead_horn ] }; + key <AE01> { [ 1, exclam, exclamdown, U2044 ] }; + key <AE02> { [ 2, at, trademark, EuroSign ] }; + key <AE03> { [ 3, numbersign, sterling, U2039 ] }; + key <AE04> { [ 4, dollar, cent, U203A ] }; + key <AE05> { [ 5, percent, infinity, UFB01 ] }; + key <AE06> { [ 6,asciicircum, section, UFB02 ] }; + key <AE07> { [ 7, ampersand, paragraph, doubledagger ] }; + key <AE08> { [ 8, asterisk, enfilledcircbullet, degree ] }; + key <AE09> { [ 9, parenleft, ordfeminine, periodcentered ] }; + key <AE10> { [ 0, parenright, masculine,singlelowquotemark] }; + key <AE11> { [ minus, underscore, endash, emdash ] }; + key <AE12> { [ equal, plus, notequal, plusminus ] }; + + key <AD01> { [ q, Q, oe, OE ] }; + key <AD02> { [ w, W, U2211,doublelowquotemark] }; + key <AD03> { [ e, E, dead_acute, acute ] }; + key <AD04> { [ r, R, registered, U2030 ] }; + key <AD05> { [ t, T, dagger, dead_caron ] }; + key <AD06> { [ y, Y, yen, onequarter ] }; + key <AD07> { [ u, U, dead_diaeresis, diaeresis ] }; + key <AD08> { [ i, I, dead_circumflex, U02C6 ] }; + key <AD09> { [ o, O, oslash, Ooblique ] }; + key <AD10> { [ p, P, Greek_pi, U220F ] }; + key <AD11> { [ bracketleft, braceleft, leftdoublequotemark, rightdoublequotemark ] }; + key <AD12> { [bracketright, braceright, leftsinglequotemark, rightsinglequotemark ] }; + key <BKSL> { [ backslash, bar, guillemotleft, guillemotright ] }; + + key <AC01> { [ a, A, aring, Aring ] }; + key <AC02> { [ s, S, ssharp, dead_stroke ] }; + key <AC03> { [ d, D, partialderivative, eth ] }; + key <AC04> { [ f, F, function, dead_hook ] }; + key <AC05> { [ g, G, copyright, dead_doubleacute ] }; + key <AC06> { [ h, H, dead_abovedot, dead_belowdot ] }; + key <AC07> { [ j, J, U2206, onehalf ] }; + key <AC08> { [ k, K,dead_abovering, UF8FF ] }; + + key <AC09> { [ l, L, notsign, THORN ] }; + key <AC10> { [ semicolon, colon, U2026, thorn ] }; + key <AC11> { [apostrophe, quotedbl, ae, AE ] }; + + key <AB01> { [ z, Z, Greek_OMEGA, dead_cedilla ] }; + key <AB02> { [ x, X, U2248, dead_ogonek ] }; + // unclear whether "approxeq" is 2248 or 2245 + key <AB03> { [ c, C, ccedilla, Ccedilla ] }; + key <AB04> { [ v, V, squareroot, U25CA ] }; + key <AB05> { [ b, B, integral, idotless ] }; + key <AB06> { [ n, N, dead_tilde, U02DC ] }; + key <AB07> { [ m, M, mu, threequarters ] }; + key <AB08> { [ comma, less, lessthanequal, dead_macron ] }; + key <AB09> { [ period, greater, greaterthanequal, dead_breve ] }; + key <AB10> { [ slash, question, division, questiondown ] }; + + include "level3(ralt_switch)" +}; + +// Colemak symbols for xkb on X.Org Server 7.x +// 2006-01-01 Shai Coleman, http://colemak.com/ . Public domain. + +partial alphanumeric_keys +xkb_symbols "colemak" { + include "us" + name[Group1]= "USA - Colemak"; + + // Alphanumeric section + key <TLDE> { [ grave, asciitilde, dead_tilde, asciitilde ] }; + key <AE01> { [ 1, exclam, exclamdown, onesuperior ] }; + key <AE02> { [ 2, at, masculine, twosuperior ] }; + key <AE03> { [ 3, numbersign, ordfeminine, threesuperior ] }; + key <AE04> { [ 4, dollar, cent, sterling ] }; + key <AE05> { [ 5, percent, EuroSign, yen ] }; + key <AE06> { [ 6, asciicircum, hstroke, Hstroke ] }; + key <AE07> { [ 7, ampersand, eth, ETH ] }; + key <AE08> { [ 8, asterisk, thorn, THORN ] }; + key <AE09> { [ 9, parenleft, leftsinglequotemark, leftdoublequotemark ] }; + key <AE10> { [ 0, parenright, rightsinglequotemark, rightdoublequotemark ] }; + key <AE11> { [ minus, underscore, endash, emdash ] }; + key <AE12> { [ equal, plus, multiply, division ] }; + + key <AD01> { [ q, Q, adiaeresis, Adiaeresis ] }; + key <AD02> { [ w, W, aring, Aring ] }; + key <AD03> { [ f, F, atilde, Atilde ] }; + key <AD04> { [ p, P, oslash, Ooblique ] }; + key <AD05> { [ g, G, dead_ogonek, asciitilde ] }; + key <AD06> { [ j, J, dstroke, Dstroke ] }; + key <AD07> { [ l, L, lstroke, Lstroke ] }; + key <AD08> { [ u, U, uacute, Uacute ] }; + key <AD09> { [ y, Y, udiaeresis, Udiaeresis ] }; + key <AD10> { [ semicolon, colon, odiaeresis, Odiaeresis ] }; + key <AD11> { [ bracketleft, braceleft, guillemotleft, 0x1002039 ] }; + key <AD12> { [ bracketright, braceright, guillemotright, 0x100203a ] }; + key <BKSL> { [ backslash, bar, asciitilde, asciitilde ] }; + + key <AC01> { [ a, A, aacute, Aacute ] }; + key <AC02> { [ r, R, dead_grave, asciitilde ] }; + key <AC03> { [ s, S, ssharp, asciitilde ] }; + key <AC04> { [ t, T, dead_acute, dead_doubleacute ] }; + key <AC05> { [ d, D, dead_diaeresis, asciitilde ] }; + key <AC06> { [ h, H, dead_caron, asciitilde ] }; + key <AC07> { [ n, N, ntilde, Ntilde ] }; + key <AC08> { [ e, E, eacute, Eacute ] }; + key <AC09> { [ i, I, iacute, Iacute ] }; + key <AC10> { [ o, O, oacute, Oacute ] }; + key <AC11> { [ apostrophe, quotedbl, otilde, Otilde ] }; + + key <AB01> { [ z, Z, ae, AE ] }; + key <AB02> { [ x, X, dead_circumflex, asciitilde ] }; + key <AB03> { [ c, C, ccedilla, Ccedilla ] }; + key <AB04> { [ v, V, oe, OE ] }; + key <AB05> { [ b, B, dead_breve, asciitilde ] }; + key <AB06> { [ k, K, dead_abovering, asciitilde ] }; + key <AB07> { [ m, M, dead_macron, asciitilde ] }; + key <AB08> { [ comma, less, dead_cedilla, asciitilde ] }; + key <AB09> { [ period, greater, dead_abovedot, asciitilde ] }; + key <AB10> { [ slash, question, questiondown, asciitilde ] }; + + key <CAPS> { [ BackSpace, BackSpace, BackSpace, BackSpace ] }; + key <LSGT> { [ minus, underscore, endash, emdash ] }; + key <SPCE> { [ space, space, space, nobreakspace ] }; + + include "level3(ralt_switch)" +}; + +// I do NOT like dead-keys - the International keyboard as defined by Microsoft +// doesn't fit my needs. Why use two keystrokes for all simple characters (eg ' +// and <space> generates a single ') just to have an é (eacute) in two strokes +// as well? I type ' more often than é (eacute). +// +// This file works just like a regular keyboard, BUT has all dead-keys +// accessible at level3 (through AltGr). An ë (ediaeresis) is now: AltGr+" +// followed by an e. In other words, this keyboard is not international as long +// as you leave the right Alt key alone. +// +// The original MS International keyboard was intended for Latin1 (iso8859-1). +// With the introduction of iso8859-15, the (important) ligature oe (and OE) +// became available. I added them next to ae. Because I write ediaeresis more +// often than registered, I moved registered to be next to copyright and added +// ediaeresis and idiaeresis. - Adriaan + +partial alphanumeric_keys +xkb_symbols "altgr-intl" { + + name[Group1]= "USA - International (AltGr dead keys)"; + + include "us(intl)" + +// five dead keys moved into level3: + + key <TLDE> { [ grave, asciitilde, dead_grave, dead_tilde ] }; + key <AC11> { [apostrophe,quotedbl, dead_acute, dead_diaeresis ] }; + +// diversions from the MS Intl keyboard: + + key <AE01> { [ 1, exclam, onesuperior, exclamdown ] }; + key <AD04> { [ r, R, ediaeresis, Ediaeresis ] }; + key <AC07> { [ j, J, idiaeresis, Idiaeresis ] }; + key <AB02> { [ x, X, oe, OE ] }; + key <AB04> { [ v, V, registered, registered ] }; + +// onequarter etc (not in iso8859-15) moved to get three unshifted deadkeys: + + key <AE06> { [ 6, asciicircum, dead_circumflex, onequarter ] }; + key <AE07> { [ 7, ampersand, dead_horn, onehalf ] }; + key <AE08> { [ 8, asterisk, dead_ogonek, threequarters ] }; + + include "level3(ralt_switch)" +}; + +// Intel ClassmatePC Keyboard Layout +// by Piter PUNK <piterpk@terra.com.br> +// +// The keyboard layouts below maps the us(basic), us(intl) and us(alt-intl) +// to ClassmatePC keyboard. All layouts uses RCTL as level3(switch) since +// the keyboard doesn't have AltGr key. The EuroSign is engraved at 5 key. + +// classmate - us(basic) +partial alphanumeric_keys +xkb_symbols "classmate" { + include "us(basic)" + name[Group1]= "USA - ClassmatePC"; + + key <LSGT> { [ backslash, bar, backslash, bar ] }; + + include "eurosign(5)" + include "level3(switch)" +}; + +// classmate-intl - us(intl) +// RCTL is generated by Fn+Alt, because that, when trying to access +// the level3 symbols at 7,8,9,0,u,i,o,p,j,k,l,;,m,. and / we got +// the keypad keycodes. The keypad is changed to make Fn+Alt+<KP_key> +// generate the same symbol as the original key. +partial alphanumeric_keys +xkb_symbols "classmate-intl" { + include "us(intl)" + name[Group1]= "USA - ClassmatePC (International)"; + key.type[Group1]="FOUR_LEVEL"; + + key <LSGT> { [ backslash, bar, backslash, bar ] }; + + key <KP7> { [ KP_Home, KP_7, + onehalf, dead_horn ] }; + key <KP8> { [ KP_Up, KP_8, + threequarters, dead_ogonek ] }; + key <KP9> { [ KP_Prior, KP_9, + leftsinglequotemark, dead_breve ] }; + key <KPMU> { [ KP_Multiply, KP_Multiply, + rightsinglequotemark, dead_abovering ] }; + + key <KP4> { [ KP_Left, KP_4, + uacute, Uacute ] }; + key <KP5> { [ KP_Begin, KP_5, + iacute, Iacute ] }; + key <KP6> { [ KP_Right, KP_6, + oacute, Oacute ] }; + key <KPSU> { [ KP_Subtract, KP_Subtract, + odiaeresis, Odiaeresis ] }; + + key <KP2> { [ KP_Down, KP_2, + oe, OE ] }; + key <KP3> { [ KP_Next, KP_3, + oslash, Ooblique ] }; + key <KPAD> { [ KP_Add, KP_Add, + paragraph, degree ] }; + + key <KP0> { [ KP_Insert, KP_0, + mu, mu ] }; + key <KPDL> { [ KP_Delete, KP_Decimal, + dead_abovedot, dead_caron ] }; + key <KPDV> { [ KP_Divide, KP_Divide, + questiondown, dead_hook ] }; + + include "level3(switch)" +}; + +// classmate-alt-intl - us(alt-intl) +// RCTL is generated by Fn+Alt, because that, when trying to access +// the level3 symbols at 7,8,9,0,u,i,o,p,j,k,l,;,m,. and / we got +// the keypad keycodes. The keypad is changed to make Fn+Alt+<KP_key> +// generate the same symbol as the original key. +partial alphanumeric_keys +xkb_symbols "classmate-alt-intl" { + include "us(alt-intl)" + name[Group1]= "USA - ClassmatePC (Alternative international)"; + key.type[Group1]="FOUR_LEVEL"; + + key <LSGT> { [ backslash, bar, backslash, bar ] }; + + key <KPSU> { [ KP_Subtract, KP_Subtract ] }; + + key <KP9> { [ KP_Prior, KP_9, + leftsinglequotemark, dead_breve ] }; + key <KPMU> { [ KP_Multiply, KP_Multiply, + rightsinglequotemark, dead_abovering ] }; + + key <KPAD> { [ KP_Add, KP_Add, + dead_ogonek, dead_diaeresis ] }; + + key <KPDL> { [ KP_Delete, KP_Decimal, + dead_abovedot, dead_circumflex ] }; + key <KPDV> { [ KP_Divide, KP_Divide, + dead_hook, dead_hook ] }; + + include "level3(switch)" +}; + +// classmate-altgr-intl - us(altgr-intl) +// RCTL is generated by Fn+Alt, because that, when trying to access +// the level3 symbols at 7,8,9,0,u,i,o,p,j,k,l,;,m,. and / we got +// the keypad keycodes. The keypad is changed to make Fn+Alt+<KP_key> +// generate the same symbol as the original key. +partial alphanumeric_keys +xkb_symbols "classmate-altgr-intl" { + include "us(altgr-intl)" + name[Group1]= "USA - ClassmatePC (International Fn+Alt dead-keys)"; + key.type[Group1]="FOUR_LEVEL"; + + key <LSGT> { [ backslash, bar, backslash, bar ] }; + + key <KP7> { [ KP_Home, KP_7, + dead_horn, dead_horn ] }; + key <KP8> { [ KP_Up, KP_8, + dead_ogonek, dead_ogonek ] }; + key <KP9> { [ KP_Prior, KP_9, + leftsinglequotemark, dead_breve ] }; + key <KPMU> { [ KP_Multiply, KP_Multiply, + rightsinglequotemark, dead_abovering ] }; + + key <KP4> { [ KP_Left, KP_4, + uacute, Uacute ] }; + key <KP5> { [ KP_Begin, KP_5, + iacute, Iacute ] }; + key <KP6> { [ KP_Right, KP_6, + oacute, Oacute ] }; + key <KPSU> { [ KP_Subtract, KP_Subtract, + odiaeresis, Odiaeresis ] }; + + key <KP1> { [ KP_End, KP_1, + idiaeresis, Idiaeresis ] }; + key <KP2> { [ KP_Down, KP_2, + oe, OE ] }; + key <KP3> { [ KP_Next, KP_3, + oslash, Ooblique ] }; + key <KPAD> { [ KP_Add, KP_Add, + paragraph, degree ] }; + + key <KP0> { [ KP_Insert, KP_0, + mu, mu ] }; + key <KPDL> { [ KP_Delete, KP_Decimal, + dead_abovedot, dead_caron ] }; + key <KPDV> { [ KP_Divide, KP_Divide, + questiondown, dead_hook ] }; + + include "level3(switch)" +}; + +partial alphanumeric_keys +xkb_symbols "olpc" { + + include "us(basic)" + name[Group1]= "USA"; + + // OLPC international US English keyboard layout. + // It's a little different from the usual international layout. + // See: http://wiki.laptop.org/go/Image:Keyboard_english.png + + key <TLDE> { [ grave, asciitilde, dead_grave, dead_tilde ] }; + key <AE01> { [ 1, exclam, exclamdown, exclamdown ] }; + key <AE02> { [ 2, at, notsign, notsign ] }; + key <AE03> { [ 3, numbersign, 0x1000300, 0x1000300 ] }; // combining grave + key <AE04> { [ 4, dollar, 0x1000301, 0x1000301 ] }; // combining acute + key <AE05> { [ 5, percent, 0x1000306, 0x1000306 ] }; // combining breve above + key <AE06> { [ 6,asciicircum, 0x100030A, 0x100030A ] }; // combining ring above + key <AE07> { [ 7, ampersand, 0x1000302, 0x1000302 ] }; // combining circumflex above + key <AE08> { [ 8, asterisk, 0x100030C, 0x100030C ] }; // combining caron above + key <AE09> { [ 9, parenleft, 0x1000307, 0x1000307 ] }; // combining dot above + key <AE10> { [ 0, parenright, 0x1000308, 0x1000308 ] }; // combining diaeresis above + key <AE11> { [ minus, underscore, 0x1000304, 0x1000304 ] }; // combining macron above + key <AE12> { [ equal, plus, 0x1000303, 0x1000303 ] }; // combining tilde above + + key <AD01> { [ q, Q, Greek_omega, Greek_OMEGA ] }; + key <AD02> { [ w, W, oslash, Oslash ] }; + key <AD03> { [ e, E, oe, OE ] }; + key <AD04> { [ r, R, 0x1000327, 0x1000327 ] }; // combining cedilla + key <AD05> { [ t, T, 0x100032E, 0x100032E ] }; // combining breve below + key <AD06> { [ y, Y, 0x1000325, 0x1000325 ] }; // combining ring below + key <AD07> { [ u, U, 0x100032D, 0x100032D ] }; // combining circumflex below + key <AD08> { [ i, I, 0x100032C, 0x100032C ] }; // combining caron below + key <AD09> { [ o, O, 0x1000323, 0x1000323 ] }; // combining dot below + key <AD10> { [ p, P, 0x1000324, 0x1000324 ] }; // combining diaeresis below + key <AD11> { [ bracketleft, braceleft, 0x1000331, 0x1000331 ] }; // combining macron below + key <AD12> { [bracketright, braceright, 0x1000330, 0x1000330 ] }; // combining tilde below + + key <AC01> { [ a, A, ae, AE ] }; + key <AC02> { [ s, S, ssharp, 0x1001E9C ] }; // uppercase S sharp + key <AC03> { [ d, D, eth, ETH ] }; + key <AC04> { [ f, F, thorn, THORN ] }; + key <AC06> { [ h, H, sterling, sterling ] }; + key <AC07> { [ j, J, EuroSign, EuroSign ] }; + key <AC10> { [ semicolon, colon, masculine, ordfeminine ] }; + key <AC11> { [ apostrophe, quotedbl, currency, currency ] }; + key <BKSL> { [ backslash, bar, section, section ] }; + + key <AB03> { [ c, C, ccedilla, Ccedilla ] }; + key <AB06> { [ n, N, ntilde, Ntilde ] }; + key <AB07> { [ m, M, mu, mu ] }; + key <AB08> { [ comma, less, guillemotleft, guillemotleft ] }; + key <AB09> { [ period, greater, guillemotright, guillemotright ] }; + key <AB10> { [ slash, question, questiondown, questiondown ] }; + + key <I219> { [ multiply, division, ISO_Next_Group, ISO_Prev_Group ] }; + + include "level3(ralt_switch)" +}; + +partial alphanumeric_keys +xkb_symbols "olpc2" { + include "us(olpc)" + name[Group1]= "USA - Layout toggle on multiply/divide key"; + include "group(olpc)" +}; + +// Based on Cherokee Nation Official Layout +// http://www.cherokee.org/extras/downloads/font/Keyboard.htm + +partial alphanumeric_keys modifier_keys +xkb_symbols "chr" { + + name[Group1]= "USA - Cherokee"; + key.type[group1]="ALPHABETIC"; + + // Alphanumeric section + key <TLDE> { [ grave, U13CA ] }; + key <AE01> { [ 1, U13B1 ] }; + key <AE02> { [ 2, U13C7 ] }; + key <AE03> { [ 3, U13E7 ] }; + key <AE04> { [ U13D9, U13B0 ] }; + key <AE05> { [ U13E6, U13B9 ] }; + key <AE06> { [ U13DC, U13DD ] }; + key <AE07> { [ U13CB, U13E1 ] }; + key <AE08> { [ U13D6, U13BA ] }; + key <AE09> { [ U13D2, parenleft ] }; + key <AE10> { [ U13C4, parenright ] }; + key <AE11> { [ U13BF, U13BC ] }; + key <AE12> { [ U13F3, U13BD ] }; + + key <AD01> { [ U13AA, U13C6 ] }; + key <AD02> { [ U13B3, U13EB ] }; + key <AD03> { [ U13A1, U13E3 ] }; + key <AD04> { [ U13DB, U13CF ] }; + key <AD05> { [ U13D4, U13D8 ] }; + key <AD06> { [ U13EF, U13F2 ] }; + key <AD07> { [ U13A4, U13AD ] }; + key <AD08> { [ U13A2, U13F1 ] }; + key <AD09> { [ U13A3, U13EC ] }; + key <AD10> { [ U13C1, U13EA ] }; + key <AD11> { [ U13D5, U13D1 ] }; + key <AD12> { [ U13B6, U13E4 ] }; + key <BKSL> { [ U13E9, U13EE ] }; + + key <AC01> { [ U13A0, U13CC ] }; + key <AC02> { [ U13CD, U13CE ] }; + key <AC03> { [ U13D7, U13D0 ] }; + key <AC04> { [ U13A9, U13C8 ] }; + key <AC05> { [ U13A6, U13E5 ] }; + key <AC06> { [ U13AF, U13B2 ] }; + key <AC07> { [ U13DA, U13AB ] }; + key <AC08> { [ U13B8, U13A7 ] }; + key <AC09> { [ U13B5, U13AE ] }; + key <AC10> { [ U13E8, U13E0 ] }; + key <AC11> { [ apostrophe, quotedbl ] }; + + key <AB01> { [ U13AC, U13C3 ] }; + key <AB02> { [ U13F4, U13ED ] }; + key <AB03> { [ U13D3, U13DF ] }; + key <AB04> { [ U13A5, U13DE ] }; + key <AB05> { [ U13A8, U13F0 ] }; + key <AB06> { [ U13BE, U13BB ] }; + key <AB07> { [ U13C5, U13B7 ] }; + key <AB08> { [ comma, U13E2 ] }; + key <AB09> { [ period, U13B4 ] }; + key <AB10> { [ U13C2, U13C9 ] }; + + // End alphanumeric section +}; + +// Serbian charecters added as third level symbols to US keyboard layout. + +partial alphanumeric_keys +xkb_symbols "hbs" { + + name[Group1]= "USA - Serbo-Croatian"; + + include "us" + + key <TLDE> { [ grave, asciitilde ] }; + key <AE06> { [ 6, dead_caron, asciicircum, asciicircum ] }; + key <AC09> { [ l, L, U1C9, U1C8 ] }; + key <AB06> { [ n, N, U1CC, U1CB ] }; + key <AB01> { [ z, Z, U1C6, U1C5 ] }; + key <AD03> { [ e, E, EuroSign, cent ] }; + key <AC03> { [ d, D, dstroke, Dstroke ] }; + key <AC11> { [ dead_acute, quotedbl, apostrophe, apostrophe ] }; + key <SPCE> { [ space, space, nobreakspace, nobreakspace ] }; + key <AB08> { [ comma, less, NoSymbol, guillemotright ] }; + key <AB09> { [ period, greater, NoSymbol, guillemotleft ] }; + + include "level3(ralt_switch)" +}; + +//based on http://upload.wikimedia.org/wikipedia/commons/1/18/T-Mobile_G1_launch_event_2.jpg +partial alphanumeric_keys +xkb_symbols "htcdream" { + include "inet(htcdream)" + name[Group1]= "USA - htcdream"; + + //second row + key <AD01> { [ q, Q, Tab, Tab ] }; + key <AD02> { [ w, W, grave, grave ] }; + key <AD03> { [ e, E, underscore, underscore ] }; + key <AD04> { [ r, R, sterling, sterling ] }; + key <AD05> { [ t, T, EuroSign, EuroSign ] }; + key <AD06> { [ y, Y, division, division ] }; + key <AD07> { [ u, U, multiply, multiply ] }; + key <AD08> { [ i, I, minus, minus ] }; + key <AD09> { [ o, O, plus, plus ] }; + key <AD10> { [ p, P, equal, equal ] }; + + //third row + key <AC01> { [ a, A, NoSymbol, NoSymbol ] }; + key <AC02> { [ s, S, bar, bar ] }; + key <AC03> { [ d ,D, backslash, backslash ] }; + key <AC04> { [ f, F, braceleft, braceleft ] }; + key <AC05> { [ g, G, braceright, braceright ] }; + key <AC06> { [ h, H, colon, colon ] }; + key <AC07> { [ j, J, semicolon, semicolon ] }; + key <AC08> { [ k, K, quotedbl, quotedbl ] }; + key <AC09> { [ l, L, apostrophe, apostrophe ] }; + + //forth row + key <AB01> { [ z, Z, NoSymbol, NoSymbol ] }; + key <AB02> { [ x, X, NoSymbol, NoSymbol ] }; + key <AB03> { [ c, C, NoSymbol, NoSymbol ] }; + key <AB04> { [ v, V, bracketleft, bracketleft ] }; + key <AB05> { [ b, B, bracketright, bracketright ] }; + key <AB06> { [ n, N, less, less ] }; + key <AB07> { [ m, M, greater, greater ] }; + key <AB08> { [ comma, comma, question, question ] }; + + //fifth row + key <FK15> { [ at, at, asciitilde, asciitilde ] }; + + include "level3(alt_switch)" +}; + +// EXTRAS: + +// XCompose is out! Unicode combining is in! For those of us who live +// on the edge: A keymap using Unicode combining characters instead of +// deadkeys. This variation does not deviate from the lame MS-style +// US-intl layout; but it uses AltGr for combining, like altgr-intl. +// +// This might break your font layout layout systems (because they +// suck), caveat emptor. Also, most of today's software will count +// individual combining marks for selection, deletion, character +// counting &c., and won't be smart enough to do canonical equivalence +// when searching, &c. +// +// With Unicode combining you use "handwriting order", not +// "typewriting order" as with deadkeys. That is, you first type the +// base character, then the diacritics/accents/modifiers. This has +// the advantage of avoiding hidden states --- each keypress changes +// something on screen. +// +// TODO: as of now, this duplicates all us(intl) functionality with +// combining. With care, perhaps we could add more combining marks +// not present in intl, and support all major languages. +partial alphanumeric_keys +xkb_symbols "intl-unicode" { + + name[Group1]= "USA - International (AltGr Unicode combining)"; + + include "us(intl)" + include "level3(ralt_switch)" + + // grave, tilde + key <TLDE> { [grave, asciitilde, U0300, U0303 ] }; + // double acute + key <AE02> { [ 2, at, twosuperior, U030B ] }; + // macron + key <AE03> { [ 3, numbersign, threesuperior, U0304 ] }; + // circumflex + key <AE06> { [ 6, asciicircum, onequarter, U0302 ] }; + // horn + key <AE07> { [ 7, ampersand, onehalf, U031B ] }; + // ogonek + key <AE08> { [ 8, asterisk, threequarters, U0328 ] }; + // breve + key <AE09> { [ 9, parenleft, leftsinglequotemark, U0306 ] }; + // abovering + key <AE10> { [ 0, parenright, rightsinglequotemark, U030A ] }; + + // belowdot + key <AE11> { [ minus, underscore, yen, U0323 ] }; + // acute, diaeresis + key <AC11> { [apostrophe, quotedbl, U0301, U0308 ] }; + // abovedot, caron + key <AB09> { [ period, greater, U0307, U030C ] }; + // hook + key <AB10> { [ slash, question, questiondown, 0309 ] }; + + // alt-intl compatibility + // cedilla, caron + key <AB08> { [ comma, less, U0327, U030C ] }; + // ogonek, diaeresis + key <AC10> { [ semicolon, colon, U0328, U0308 ] }; + // doubleacute, horn + key <AE12> { [ equal, plus, U030B, U031B ] }; + + // we don't do combining latin letters and combining enclosures + // because support for those is very rare. +}; + +// XCompose is out! Unicode combining is in! For those of us who live +// on the edge: A keymap using Unicode combining characters instead of +// deadkeys. This variation does break compatibility with us-intl, +// whenever I thought it would be more mnemonic or Unicodeish. +partial alphanumeric_keys +xkb_symbols "alt-intl-unicode" { + + name[Group1]= "USA - International (AltGr Unicode combining, alternative)"; + + include "extras/us(intl-unicode)" + include "level3(ralt_switch)" + + // easier macron; em-dash. + // em-dash is available via compose, but I added here since it's such + // an important typographic character. + key <AE11> { [ minus, underscore, U0304, U2014 ] }; + + // belowdot, abovedot (caron at coma/less key, per above) + key <AB09> { [ period, greater, U0323, U0307 ] }; + +}; + +partial alphanumeric_keys +xkb_symbols "ats" { + + include "us" + + name[Group1]= "USA - Atsina"; + + //Using Dead key to get COMBINING COMMA ABOVE for ejectives on + //q, l, t, s, m, g, k, p, w, y, r + //XCompose key is used for the other accute and grave. + + key <AD03> { [ e, E, eacute, Eacute ] }; + key <AD07> { [ u, U, uacute, Uacute ] }; + key <AD08> { [ i, I, iacute, Iacute ] }; + key <AD09> { [ o, O, oacute, Oacute ] }; + key <AD11> { [ bracketleft, braceleft, U03B8 ] }; + key <AD12> { [ bracketright, braceright, U010D, U010C ] }; + //U+010C (uppercase Č) and U+010D (lowercase č). + + key <AC01> { [ a, A, aacute, Aacute ] }; + + + //Small letter Open use compose to key get acute accent + key <AB03> { [ c, C, U0254, U0186 ] }; + key <AB08> { [ comma, less, U0313 ] }; + key <AB10> { [ slash, question, U0294 ] }; + + include "level3(ralt_switch)" + include "compose(rctrl)" +}; + +partial alphanumeric_keys +xkb_symbols "crd" { + + include "us" + + name[Group1]= "USA - Couer D'alene Salish"; + + // Alphanumeric section + key <AD02> { [ w, W, U02B7, U02B7 ] }; + key <AE07> { [ 7, ampersand, U0294 ] }; + key <AD01> { [ q, Q, U221A ] }; + key <AB04> { [ v, V, U0259 ] }; + key <BKSL> { [ backslash, bar, U026B ] }; + key <AD03> { [ e, E, U025B ] }; + key <AD08> { [ i, I, U026A ] }; + key <AC07> { [ j, J, U01F0 ] }; + key <AE06> { [ 6, asciicircum, U0295 ] }; + key <AC02> { [ s, S, U0161 ] }; + key <AB03> { [ c, C, U010D ] }; + key <AD09> { [ o, O, U0254 ] }; + key <AB09> { [ period, greater, U0323 ] }; + + include "level3(ralt_switch)" + include "compose(rctrl)" + + // End alphanumeric section +}; |