diff options
Diffstat (limited to 'xorg-server/dix')
30 files changed, 7038 insertions, 3743 deletions
diff --git a/xorg-server/dix/CHANGES b/xorg-server/dix/CHANGES deleted file mode 100644 index d8fb7c31a..000000000 --- a/xorg-server/dix/CHANGES +++ /dev/null @@ -1,17 +0,0 @@ -The following changes have been made to this directory since R3 (for -a full description, see doc/Server/r4.tbl.ms): - - o Windows restructured (memory reduction, devPrivates and speedups) - o GCs restructured (memory reduction, devPrivates and wrappers) - o Screens restructured (window ops merged in, devPrivates) - o Pixmaps restructured (drawable changes mostly) - o Cursors restructured (shares glyph bits now) - o Visuals restructured (screen index removed, fields rearranged) - o Devices restructured (input extension changes) - o Out of memory changes. Many interfaces now return OutOfMemory - status. - o Synchronous grab code rewritten. Should conform to our - understanding of the protocol now. Be careful when time - stamping events (don't allow time to run backwards). - o Resource types redesigned and rewritten. - o Internal fake color allocation routine for software cursors. diff --git a/xorg-server/dix/Makefile.am b/xorg-server/dix/Makefile.am index eb5e77946..4c2395d82 100644 --- a/xorg-server/dix/Makefile.am +++ b/xorg-server/dix/Makefile.am @@ -1,10 +1,4 @@ -standard_dix_libs = libdix.la libxpstubs.la - -if XPRINT -noinst_LTLIBRARIES = $(standard_dix_libs) libXpdix.la -else -noinst_LTLIBRARIES = $(standard_dix_libs) -endif +noinst_LTLIBRARIES = libdix.la AM_CFLAGS = $(DIX_CFLAGS) \ -DVENDOR_NAME=\""@VENDOR_NAME@"\" \ @@ -20,6 +14,8 @@ libdix_la_SOURCES = \ dispatch.h \ dixfonts.c \ dixutils.c \ + enterleave.c \ + enterleave.h \ events.c \ extension.c \ ffs.c \ @@ -33,26 +29,16 @@ libdix_la_SOURCES = \ pixmap.c \ privates.c \ property.c \ + ptrveloc.c \ registry.c \ resource.c \ selection.c \ swaprep.c \ swapreq.c \ tables.c \ - window.c \ - strcasecmp.c \ - strcasestr.c - -libxpstubs_la_SOURCES = \ - xpstubs.c - -if XPRINT -libXpdix_la_SOURCES = $(libdix_la_SOURCES) -libXpdix_la_CPPFLAGS = -I$(top_srcdir)/hw/xprint -libXpdix_la_CFLAGS = $(AM_CFLAGS) $(XPRINT_CFLAGS) -endif + window.c -EXTRA_DIST = buildatoms BuiltInAtoms CHANGES Xserver.d Xserver-dtrace.h.in +EXTRA_DIST = buildatoms BuiltInAtoms Xserver.d Xserver-dtrace.h.in # Install list of protocol names miscconfigdir = $(SERVER_MISC_CONFIG_PATH) diff --git a/xorg-server/dix/Makefile.in b/xorg-server/dix/Makefile.in index c1a07a163..28de940f1 100644 --- a/xorg-server/dix/Makefile.in +++ b/xorg-server/dix/Makefile.in @@ -1,4 +1,4 @@ -# Makefile.in generated by automake 1.10.1 from Makefile.am. +# Makefile.in generated by automake 1.10.2 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, @@ -47,56 +47,20 @@ mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/include/do-not-use-config.h \ $(top_builddir)/include/xorg-server.h \ $(top_builddir)/include/dix-config.h \ - $(top_builddir)/include/xgl-config.h \ $(top_builddir)/include/xorg-config.h \ $(top_builddir)/include/xkb-config.h \ $(top_builddir)/include/xwin-config.h \ $(top_builddir)/include/kdrive-config.h CONFIG_CLEAN_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) -libXpdix_la_LIBADD = -am__libXpdix_la_SOURCES_DIST = atom.c colormap.c cursor.c deprecated.c \ - devices.c dispatch.c dispatch.h dixfonts.c dixutils.c events.c \ - extension.c ffs.c gc.c getevents.c globals.c glyphcurs.c \ - grabs.c initatoms.c main.c pixmap.c privates.c property.c \ - registry.c resource.c selection.c swaprep.c swapreq.c tables.c \ - window.c strcasecmp.c strcasestr.c -am__objects_1 = libXpdix_la-atom.lo libXpdix_la-colormap.lo \ - libXpdix_la-cursor.lo libXpdix_la-deprecated.lo \ - libXpdix_la-devices.lo libXpdix_la-dispatch.lo \ - libXpdix_la-dixfonts.lo libXpdix_la-dixutils.lo \ - libXpdix_la-events.lo libXpdix_la-extension.lo \ - libXpdix_la-ffs.lo libXpdix_la-gc.lo libXpdix_la-getevents.lo \ - libXpdix_la-globals.lo libXpdix_la-glyphcurs.lo \ - libXpdix_la-grabs.lo libXpdix_la-initatoms.lo \ - libXpdix_la-main.lo libXpdix_la-pixmap.lo \ - libXpdix_la-privates.lo libXpdix_la-property.lo \ - libXpdix_la-registry.lo libXpdix_la-resource.lo \ - libXpdix_la-selection.lo libXpdix_la-swaprep.lo \ - libXpdix_la-swapreq.lo libXpdix_la-tables.lo \ - libXpdix_la-window.lo libXpdix_la-strcasecmp.lo \ - libXpdix_la-strcasestr.lo -@XPRINT_TRUE@am_libXpdix_la_OBJECTS = $(am__objects_1) -libXpdix_la_OBJECTS = $(am_libXpdix_la_OBJECTS) -libXpdix_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ - $(LIBTOOLFLAGS) --mode=link $(CCLD) $(libXpdix_la_CFLAGS) \ - $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ -@XPRINT_TRUE@am_libXpdix_la_rpath = libdix_la_LIBADD = am_libdix_la_OBJECTS = atom.lo colormap.lo cursor.lo deprecated.lo \ - devices.lo dispatch.lo dixfonts.lo dixutils.lo events.lo \ - extension.lo ffs.lo gc.lo getevents.lo globals.lo glyphcurs.lo \ - grabs.lo initatoms.lo main.lo pixmap.lo privates.lo \ - property.lo registry.lo resource.lo selection.lo swaprep.lo \ - swapreq.lo tables.lo window.lo strcasecmp.lo strcasestr.lo + devices.lo dispatch.lo dixfonts.lo dixutils.lo enterleave.lo \ + events.lo extension.lo ffs.lo gc.lo getevents.lo globals.lo \ + glyphcurs.lo grabs.lo initatoms.lo main.lo pixmap.lo \ + privates.lo property.lo ptrveloc.lo registry.lo resource.lo \ + selection.lo swaprep.lo swapreq.lo tables.lo window.lo libdix_la_OBJECTS = $(am_libdix_la_OBJECTS) -@XPRINT_FALSE@am_libdix_la_rpath = -@XPRINT_TRUE@am_libdix_la_rpath = -libxpstubs_la_LIBADD = -am_libxpstubs_la_OBJECTS = xpstubs.lo -libxpstubs_la_OBJECTS = $(am_libxpstubs_la_OBJECTS) -@XPRINT_FALSE@am_libxpstubs_la_rpath = -@XPRINT_TRUE@am_libxpstubs_la_rpath = PROGRAMS = $(noinst_PROGRAMS) dix_O_SOURCES = dix.c dix_O_OBJECTS = dix.$(OBJEXT) @@ -106,17 +70,12 @@ depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ - --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ - $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ -SOURCES = $(libXpdix_la_SOURCES) $(libdix_la_SOURCES) \ - $(libxpstubs_la_SOURCES) dix.c -DIST_SOURCES = $(am__libXpdix_la_SOURCES_DIST) $(libdix_la_SOURCES) \ - $(libxpstubs_la_SOURCES) dix.c +SOURCES = $(libdix_la_SOURCES) dix.c +DIST_SOURCES = $(libdix_la_SOURCES) dix.c am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ @@ -134,8 +93,9 @@ ADMIN_MAN_DIR = @ADMIN_MAN_DIR@ ADMIN_MAN_SUFFIX = @ADMIN_MAN_SUFFIX@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ -APPDEFAULTDIR = @APPDEFAULTDIR@ APPLE_APPLICATIONS_DIR = @APPLE_APPLICATIONS_DIR@ +APPLE_APPLICATION_ID = @APPLE_APPLICATION_ID@ +APPLE_APPLICATION_NAME = @APPLE_APPLICATION_NAME@ APP_MAN_DIR = @APP_MAN_DIR@ APP_MAN_SUFFIX = @APP_MAN_SUFFIX@ AR = @AR@ @@ -156,10 +116,6 @@ CFLAGS = @CFLAGS@ COMPILEDDEFAULTFONTPATH = @COMPILEDDEFAULTFONTPATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ -CXX = @CXX@ -CXXCPP = @CXXCPP@ -CXXDEPMODE = @CXXDEPMODE@ -CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DARWIN_LIBS = @DARWIN_LIBS@ DBUS_CFLAGS = @DBUS_CFLAGS@ @@ -181,6 +137,7 @@ DMXXIEXAMPLES_DEP_CFLAGS = @DMXXIEXAMPLES_DEP_CFLAGS@ DMXXIEXAMPLES_DEP_LIBS = @DMXXIEXAMPLES_DEP_LIBS@ DMXXMUEXAMPLES_DEP_CFLAGS = @DMXXMUEXAMPLES_DEP_CFLAGS@ DMXXMUEXAMPLES_DEP_LIBS = @DMXXMUEXAMPLES_DEP_LIBS@ +DOLT_BASH = @DOLT_BASH@ DRI2PROTO_CFLAGS = @DRI2PROTO_CFLAGS@ DRI2PROTO_LIBS = @DRI2PROTO_LIBS@ DRIPROTO_CFLAGS = @DRIPROTO_CFLAGS@ @@ -190,18 +147,15 @@ DRIVER_MAN_SUFFIX = @DRIVER_MAN_SUFFIX@ DRI_DRIVER_PATH = @DRI_DRIVER_PATH@ DSYMUTIL = @DSYMUTIL@ DTRACE = @DTRACE@ -ECHO = @ECHO@ +DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ -F77 = @F77@ -FFLAGS = @FFLAGS@ +FGREP = @FGREP@ FILE_MAN_DIR = @FILE_MAN_DIR@ FILE_MAN_SUFFIX = @FILE_MAN_SUFFIX@ -FREETYPE_CFLAGS = @FREETYPE_CFLAGS@ -FREETYPE_LIBS = @FREETYPE_LIBS@ GLX_ARCH_DEFINES = @GLX_ARCH_DEFINES@ GLX_DEFINES = @GLX_DEFINES@ GL_CFLAGS = @GL_CFLAGS@ @@ -220,7 +174,7 @@ KDRIVE_LIBS = @KDRIVE_LIBS@ KDRIVE_LOCAL_LIBS = @KDRIVE_LOCAL_LIBS@ KDRIVE_PURE_INCS = @KDRIVE_PURE_INCS@ KDRIVE_PURE_LIBS = @KDRIVE_PURE_LIBS@ -LAUNCHD = @LAUNCHD@ +LD = @LD@ LDFLAGS = @LDFLAGS@ LD_EXPORT_SYMBOLS_FLAG = @LD_EXPORT_SYMBOLS_FLAG@ LEX = @LEX@ @@ -234,7 +188,10 @@ LIBTOOL = @LIBTOOL@ LIB_MAN_DIR = @LIB_MAN_DIR@ LIB_MAN_SUFFIX = @LIB_MAN_SUFFIX@ LINUXDOC = @LINUXDOC@ +LIPO = @LIPO@ LN_S = @LN_S@ +LTCOMPILE = @LTCOMPILE@ +LTCXXCOMPILE = @LTCXXCOMPILE@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ @@ -246,8 +203,7 @@ MESA_SOURCE = @MESA_SOURCE@ MISC_MAN_DIR = @MISC_MAN_DIR@ MISC_MAN_SUFFIX = @MISC_MAN_SUFFIX@ MKDIR_P = @MKDIR_P@ -MKFONTDIR = @MKFONTDIR@ -MKFONTSCALE = @MKFONTSCALE@ +NM = @NM@ NMEDIT = @NMEDIT@ OBJC = @OBJC@ OBJCCLD = @OBJCCLD@ @@ -256,8 +212,8 @@ OBJCFLAGS = @OBJCFLAGS@ OBJCLINK = @OBJCLINK@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ -OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ -OPENSSL_LIBS = @OPENSSL_LIBS@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ @@ -290,7 +246,6 @@ VENDOR_NAME = @VENDOR_NAME@ VENDOR_NAME_SHORT = @VENDOR_NAME_SHORT@ VENDOR_RELEASE = @VENDOR_RELEASE@ VERSION = @VERSION@ -X11APP_ARCHS = @X11APP_ARCHS@ X11EXAMPLES_DEP_CFLAGS = @X11EXAMPLES_DEP_CFLAGS@ X11EXAMPLES_DEP_LIBS = @X11EXAMPLES_DEP_LIBS@ XDMCP_CFLAGS = @XDMCP_CFLAGS@ @@ -300,27 +255,12 @@ XDMXCONFIG_DEP_LIBS = @XDMXCONFIG_DEP_LIBS@ XDMX_CFLAGS = @XDMX_CFLAGS@ XDMX_LIBS = @XDMX_LIBS@ XDMX_SYS_LIBS = @XDMX_SYS_LIBS@ -XEGLMODULES_CFLAGS = @XEGLMODULES_CFLAGS@ -XEGL_LIBS = @XEGL_LIBS@ -XEGL_SYS_LIBS = @XEGL_SYS_LIBS@ XEPHYR_CFLAGS = @XEPHYR_CFLAGS@ -XEPHYR_DRI_LIBS = @XEPHYR_DRI_LIBS@ XEPHYR_INCS = @XEPHYR_INCS@ XEPHYR_LIBS = @XEPHYR_LIBS@ XF86CONFIGFILE = @XF86CONFIGFILE@ -XF86MISC_CFLAGS = @XF86MISC_CFLAGS@ -XF86MISC_LIBS = @XF86MISC_LIBS@ XF86VIDMODE_CFLAGS = @XF86VIDMODE_CFLAGS@ XF86VIDMODE_LIBS = @XF86VIDMODE_LIBS@ -XGLMODULES_CFLAGS = @XGLMODULES_CFLAGS@ -XGLMODULES_LIBS = @XGLMODULES_LIBS@ -XGLXMODULES_CFLAGS = @XGLXMODULES_CFLAGS@ -XGLXMODULES_LIBS = @XGLXMODULES_LIBS@ -XGLX_LIBS = @XGLX_LIBS@ -XGLX_SYS_LIBS = @XGLX_SYS_LIBS@ -XGL_LIBS = @XGL_LIBS@ -XGL_MODULE_PATH = @XGL_MODULE_PATH@ -XGL_SYS_LIBS = @XGL_SYS_LIBS@ XKB_BASE_DIRECTORY = @XKB_BASE_DIRECTORY@ XKB_BIN_DIRECTORY = @XKB_BIN_DIRECTORY@ XKB_COMPILED_DIR = @XKB_COMPILED_DIR@ @@ -331,10 +271,6 @@ XNESTMODULES_CFLAGS = @XNESTMODULES_CFLAGS@ XNESTMODULES_LIBS = @XNESTMODULES_LIBS@ XNEST_LIBS = @XNEST_LIBS@ XNEST_SYS_LIBS = @XNEST_SYS_LIBS@ -XORGCFG_DEP_CFLAGS = @XORGCFG_DEP_CFLAGS@ -XORGCFG_DEP_LIBS = @XORGCFG_DEP_LIBS@ -XORGCONFIG_DEP_CFLAGS = @XORGCONFIG_DEP_CFLAGS@ -XORGCONFIG_DEP_LIBS = @XORGCONFIG_DEP_LIBS@ XORG_CFLAGS = @XORG_CFLAGS@ XORG_INCS = @XORG_INCS@ XORG_LIBS = @XORG_LIBS@ @@ -343,13 +279,8 @@ XORG_MODULES_LIBS = @XORG_MODULES_LIBS@ XORG_OS = @XORG_OS@ XORG_OS_SUBDIR = @XORG_OS_SUBDIR@ XORG_SYS_LIBS = @XORG_SYS_LIBS@ -XPRINTMODULES_CFLAGS = @XPRINTMODULES_CFLAGS@ -XPRINTMODULES_LIBS = @XPRINTMODULES_LIBS@ -XPRINTPROTO_CFLAGS = @XPRINTPROTO_CFLAGS@ -XPRINTPROTO_LIBS = @XPRINTPROTO_LIBS@ -XPRINT_CFLAGS = @XPRINT_CFLAGS@ -XPRINT_LIBS = @XPRINT_LIBS@ -XPRINT_SYS_LIBS = @XPRINT_SYS_LIBS@ +XPBPROXY_CFLAGS = @XPBPROXY_CFLAGS@ +XPBPROXY_LIBS = @XPBPROXY_LIBS@ XRESEXAMPLES_DEP_CFLAGS = @XRESEXAMPLES_DEP_CFLAGS@ XRESEXAMPLES_DEP_LIBS = @XRESEXAMPLES_DEP_LIBS@ XSDL_INCS = @XSDL_INCS@ @@ -382,8 +313,7 @@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_CC = @ac_ct_CC@ -ac_ct_CXX = @ac_ct_CXX@ -ac_ct_F77 = @ac_ct_F77@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ @@ -403,7 +333,6 @@ driverdir = @driverdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ extdir = @extdir@ -ft_config = @ft_config@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ @@ -413,12 +342,12 @@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ -launchagentsdir = @launchagentsdir@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ logdir = @logdir@ +lt_ECHO = @lt_ECHO@ mandir = @mandir@ mkdir_p = @mkdir_p@ moduledir = @moduledir@ @@ -436,11 +365,7 @@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ -xglmoduledir = @xglmoduledir@ -xpconfigdir = @xpconfigdir@ -standard_dix_libs = libdix.la libxpstubs.la -@XPRINT_FALSE@noinst_LTLIBRARIES = $(standard_dix_libs) -@XPRINT_TRUE@noinst_LTLIBRARIES = $(standard_dix_libs) libXpdix.la +noinst_LTLIBRARIES = libdix.la AM_CFLAGS = $(DIX_CFLAGS) \ -DVENDOR_NAME=\""@VENDOR_NAME@"\" \ -DVENDOR_RELEASE="@VENDOR_RELEASE@" @@ -455,6 +380,8 @@ libdix_la_SOURCES = \ dispatch.h \ dixfonts.c \ dixutils.c \ + enterleave.c \ + enterleave.h \ events.c \ extension.c \ ffs.c \ @@ -468,23 +395,16 @@ libdix_la_SOURCES = \ pixmap.c \ privates.c \ property.c \ + ptrveloc.c \ registry.c \ resource.c \ selection.c \ swaprep.c \ swapreq.c \ tables.c \ - window.c \ - strcasecmp.c \ - strcasestr.c + window.c -libxpstubs_la_SOURCES = \ - xpstubs.c - -@XPRINT_TRUE@libXpdix_la_SOURCES = $(libdix_la_SOURCES) -@XPRINT_TRUE@libXpdix_la_CPPFLAGS = -I$(top_srcdir)/hw/xprint -@XPRINT_TRUE@libXpdix_la_CFLAGS = $(AM_CFLAGS) $(XPRINT_CFLAGS) -EXTRA_DIST = buildatoms BuiltInAtoms CHANGES Xserver.d Xserver-dtrace.h.in +EXTRA_DIST = buildatoms BuiltInAtoms Xserver.d Xserver-dtrace.h.in # Install list of protocol names miscconfigdir = $(SERVER_MISC_CONFIG_PATH) @@ -502,8 +422,8 @@ $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__confi @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ - && exit 0; \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ @@ -536,12 +456,8 @@ clean-noinstLTLIBRARIES: echo "rm -f \"$${dir}/so_locations\""; \ rm -f "$${dir}/so_locations"; \ done -libXpdix.la: $(libXpdix_la_OBJECTS) $(libXpdix_la_DEPENDENCIES) - $(libXpdix_la_LINK) $(am_libXpdix_la_rpath) $(libXpdix_la_OBJECTS) $(libXpdix_la_LIBADD) $(LIBS) libdix.la: $(libdix_la_OBJECTS) $(libdix_la_DEPENDENCIES) - $(LINK) $(am_libdix_la_rpath) $(libdix_la_OBJECTS) $(libdix_la_LIBADD) $(LIBS) -libxpstubs.la: $(libxpstubs_la_OBJECTS) $(libxpstubs_la_DEPENDENCIES) - $(LINK) $(am_libxpstubs_la_rpath) $(libxpstubs_la_OBJECTS) $(libxpstubs_la_LIBADD) $(LIBS) + $(LINK) $(libdix_la_OBJECTS) $(libdix_la_LIBADD) $(LIBS) clean-noinstPROGRAMS: @list='$(noinst_PROGRAMS)'; for p in $$list; do \ @@ -568,6 +484,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dix.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dixfonts.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dixutils.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/enterleave.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/events.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/extension.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ffs.Plo@am__quote@ @@ -577,50 +494,18 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/glyphcurs.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/grabs.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/initatoms.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXpdix_la-atom.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXpdix_la-colormap.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXpdix_la-cursor.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXpdix_la-deprecated.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXpdix_la-devices.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXpdix_la-dispatch.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXpdix_la-dixfonts.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXpdix_la-dixutils.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXpdix_la-events.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXpdix_la-extension.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXpdix_la-ffs.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXpdix_la-gc.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXpdix_la-getevents.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXpdix_la-globals.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXpdix_la-glyphcurs.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXpdix_la-grabs.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXpdix_la-initatoms.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXpdix_la-main.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXpdix_la-pixmap.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXpdix_la-privates.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXpdix_la-property.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXpdix_la-registry.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXpdix_la-resource.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXpdix_la-selection.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXpdix_la-strcasecmp.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXpdix_la-strcasestr.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXpdix_la-swaprep.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXpdix_la-swapreq.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXpdix_la-tables.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libXpdix_la-window.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pixmap.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/privates.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/property.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ptrveloc.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/registry.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/resource.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/selection.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/strcasecmp.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/strcasestr.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/swaprep.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/swapreq.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tables.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/window.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xpstubs.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @@ -643,216 +528,6 @@ distclean-compile: @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< -libXpdix_la-atom.lo: atom.c -@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libXpdix_la_CPPFLAGS) $(CPPFLAGS) $(libXpdix_la_CFLAGS) $(CFLAGS) -MT libXpdix_la-atom.lo -MD -MP -MF $(DEPDIR)/libXpdix_la-atom.Tpo -c -o libXpdix_la-atom.lo `test -f 'atom.c' || echo '$(srcdir)/'`atom.c -@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libXpdix_la-atom.Tpo $(DEPDIR)/libXpdix_la-atom.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='atom.c' object='libXpdix_la-atom.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libXpdix_la_CPPFLAGS) $(CPPFLAGS) $(libXpdix_la_CFLAGS) $(CFLAGS) -c -o libXpdix_la-atom.lo `test -f 'atom.c' || echo '$(srcdir)/'`atom.c - -libXpdix_la-colormap.lo: colormap.c -@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libXpdix_la_CPPFLAGS) $(CPPFLAGS) $(libXpdix_la_CFLAGS) $(CFLAGS) -MT libXpdix_la-colormap.lo -MD -MP -MF $(DEPDIR)/libXpdix_la-colormap.Tpo -c -o libXpdix_la-colormap.lo `test -f 'colormap.c' || echo '$(srcdir)/'`colormap.c -@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libXpdix_la-colormap.Tpo $(DEPDIR)/libXpdix_la-colormap.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='colormap.c' object='libXpdix_la-colormap.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libXpdix_la_CPPFLAGS) $(CPPFLAGS) $(libXpdix_la_CFLAGS) $(CFLAGS) -c -o libXpdix_la-colormap.lo `test -f 'colormap.c' || echo '$(srcdir)/'`colormap.c - -libXpdix_la-cursor.lo: cursor.c -@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libXpdix_la_CPPFLAGS) $(CPPFLAGS) $(libXpdix_la_CFLAGS) $(CFLAGS) -MT libXpdix_la-cursor.lo -MD -MP -MF $(DEPDIR)/libXpdix_la-cursor.Tpo -c -o libXpdix_la-cursor.lo `test -f 'cursor.c' || echo '$(srcdir)/'`cursor.c -@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libXpdix_la-cursor.Tpo $(DEPDIR)/libXpdix_la-cursor.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='cursor.c' object='libXpdix_la-cursor.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libXpdix_la_CPPFLAGS) $(CPPFLAGS) $(libXpdix_la_CFLAGS) $(CFLAGS) -c -o libXpdix_la-cursor.lo `test -f 'cursor.c' || echo '$(srcdir)/'`cursor.c - -libXpdix_la-deprecated.lo: deprecated.c -@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libXpdix_la_CPPFLAGS) $(CPPFLAGS) $(libXpdix_la_CFLAGS) $(CFLAGS) -MT libXpdix_la-deprecated.lo -MD -MP -MF $(DEPDIR)/libXpdix_la-deprecated.Tpo -c -o libXpdix_la-deprecated.lo `test -f 'deprecated.c' || echo '$(srcdir)/'`deprecated.c -@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libXpdix_la-deprecated.Tpo $(DEPDIR)/libXpdix_la-deprecated.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='deprecated.c' object='libXpdix_la-deprecated.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libXpdix_la_CPPFLAGS) $(CPPFLAGS) $(libXpdix_la_CFLAGS) $(CFLAGS) -c -o libXpdix_la-deprecated.lo `test -f 'deprecated.c' || echo '$(srcdir)/'`deprecated.c - -libXpdix_la-devices.lo: devices.c -@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libXpdix_la_CPPFLAGS) $(CPPFLAGS) $(libXpdix_la_CFLAGS) $(CFLAGS) -MT libXpdix_la-devices.lo -MD -MP -MF $(DEPDIR)/libXpdix_la-devices.Tpo -c -o libXpdix_la-devices.lo `test -f 'devices.c' || echo '$(srcdir)/'`devices.c -@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libXpdix_la-devices.Tpo $(DEPDIR)/libXpdix_la-devices.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='devices.c' object='libXpdix_la-devices.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libXpdix_la_CPPFLAGS) $(CPPFLAGS) $(libXpdix_la_CFLAGS) $(CFLAGS) -c -o libXpdix_la-devices.lo `test -f 'devices.c' || echo '$(srcdir)/'`devices.c - -libXpdix_la-dispatch.lo: dispatch.c -@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libXpdix_la_CPPFLAGS) $(CPPFLAGS) $(libXpdix_la_CFLAGS) $(CFLAGS) -MT libXpdix_la-dispatch.lo -MD -MP -MF $(DEPDIR)/libXpdix_la-dispatch.Tpo -c -o libXpdix_la-dispatch.lo `test -f 'dispatch.c' || echo '$(srcdir)/'`dispatch.c -@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libXpdix_la-dispatch.Tpo $(DEPDIR)/libXpdix_la-dispatch.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='dispatch.c' object='libXpdix_la-dispatch.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libXpdix_la_CPPFLAGS) $(CPPFLAGS) $(libXpdix_la_CFLAGS) $(CFLAGS) -c -o libXpdix_la-dispatch.lo `test -f 'dispatch.c' || echo '$(srcdir)/'`dispatch.c - -libXpdix_la-dixfonts.lo: dixfonts.c -@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libXpdix_la_CPPFLAGS) $(CPPFLAGS) $(libXpdix_la_CFLAGS) $(CFLAGS) -MT libXpdix_la-dixfonts.lo -MD -MP -MF $(DEPDIR)/libXpdix_la-dixfonts.Tpo -c -o libXpdix_la-dixfonts.lo `test -f 'dixfonts.c' || echo '$(srcdir)/'`dixfonts.c -@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libXpdix_la-dixfonts.Tpo $(DEPDIR)/libXpdix_la-dixfonts.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='dixfonts.c' object='libXpdix_la-dixfonts.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libXpdix_la_CPPFLAGS) $(CPPFLAGS) $(libXpdix_la_CFLAGS) $(CFLAGS) -c -o libXpdix_la-dixfonts.lo `test -f 'dixfonts.c' || echo '$(srcdir)/'`dixfonts.c - -libXpdix_la-dixutils.lo: dixutils.c -@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libXpdix_la_CPPFLAGS) $(CPPFLAGS) $(libXpdix_la_CFLAGS) $(CFLAGS) -MT libXpdix_la-dixutils.lo -MD -MP -MF $(DEPDIR)/libXpdix_la-dixutils.Tpo -c -o libXpdix_la-dixutils.lo `test -f 'dixutils.c' || echo '$(srcdir)/'`dixutils.c -@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libXpdix_la-dixutils.Tpo $(DEPDIR)/libXpdix_la-dixutils.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='dixutils.c' object='libXpdix_la-dixutils.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libXpdix_la_CPPFLAGS) $(CPPFLAGS) $(libXpdix_la_CFLAGS) $(CFLAGS) -c -o libXpdix_la-dixutils.lo `test -f 'dixutils.c' || echo '$(srcdir)/'`dixutils.c - -libXpdix_la-events.lo: events.c -@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libXpdix_la_CPPFLAGS) $(CPPFLAGS) $(libXpdix_la_CFLAGS) $(CFLAGS) -MT libXpdix_la-events.lo -MD -MP -MF $(DEPDIR)/libXpdix_la-events.Tpo -c -o libXpdix_la-events.lo `test -f 'events.c' || echo '$(srcdir)/'`events.c -@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libXpdix_la-events.Tpo $(DEPDIR)/libXpdix_la-events.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='events.c' object='libXpdix_la-events.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libXpdix_la_CPPFLAGS) $(CPPFLAGS) $(libXpdix_la_CFLAGS) $(CFLAGS) -c -o libXpdix_la-events.lo `test -f 'events.c' || echo '$(srcdir)/'`events.c - -libXpdix_la-extension.lo: extension.c -@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libXpdix_la_CPPFLAGS) $(CPPFLAGS) $(libXpdix_la_CFLAGS) $(CFLAGS) -MT libXpdix_la-extension.lo -MD -MP -MF $(DEPDIR)/libXpdix_la-extension.Tpo -c -o libXpdix_la-extension.lo `test -f 'extension.c' || echo '$(srcdir)/'`extension.c -@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libXpdix_la-extension.Tpo $(DEPDIR)/libXpdix_la-extension.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='extension.c' object='libXpdix_la-extension.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libXpdix_la_CPPFLAGS) $(CPPFLAGS) $(libXpdix_la_CFLAGS) $(CFLAGS) -c -o libXpdix_la-extension.lo `test -f 'extension.c' || echo '$(srcdir)/'`extension.c - -libXpdix_la-ffs.lo: ffs.c -@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libXpdix_la_CPPFLAGS) $(CPPFLAGS) $(libXpdix_la_CFLAGS) $(CFLAGS) -MT libXpdix_la-ffs.lo -MD -MP -MF $(DEPDIR)/libXpdix_la-ffs.Tpo -c -o libXpdix_la-ffs.lo `test -f 'ffs.c' || echo '$(srcdir)/'`ffs.c -@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libXpdix_la-ffs.Tpo $(DEPDIR)/libXpdix_la-ffs.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='ffs.c' object='libXpdix_la-ffs.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libXpdix_la_CPPFLAGS) $(CPPFLAGS) $(libXpdix_la_CFLAGS) $(CFLAGS) -c -o libXpdix_la-ffs.lo `test -f 'ffs.c' || echo '$(srcdir)/'`ffs.c - -libXpdix_la-gc.lo: gc.c -@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libXpdix_la_CPPFLAGS) $(CPPFLAGS) $(libXpdix_la_CFLAGS) $(CFLAGS) -MT libXpdix_la-gc.lo -MD -MP -MF $(DEPDIR)/libXpdix_la-gc.Tpo -c -o libXpdix_la-gc.lo `test -f 'gc.c' || echo '$(srcdir)/'`gc.c -@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libXpdix_la-gc.Tpo $(DEPDIR)/libXpdix_la-gc.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='gc.c' object='libXpdix_la-gc.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libXpdix_la_CPPFLAGS) $(CPPFLAGS) $(libXpdix_la_CFLAGS) $(CFLAGS) -c -o libXpdix_la-gc.lo `test -f 'gc.c' || echo '$(srcdir)/'`gc.c - -libXpdix_la-getevents.lo: getevents.c -@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libXpdix_la_CPPFLAGS) $(CPPFLAGS) $(libXpdix_la_CFLAGS) $(CFLAGS) -MT libXpdix_la-getevents.lo -MD -MP -MF $(DEPDIR)/libXpdix_la-getevents.Tpo -c -o libXpdix_la-getevents.lo `test -f 'getevents.c' || echo '$(srcdir)/'`getevents.c -@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libXpdix_la-getevents.Tpo $(DEPDIR)/libXpdix_la-getevents.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='getevents.c' object='libXpdix_la-getevents.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libXpdix_la_CPPFLAGS) $(CPPFLAGS) $(libXpdix_la_CFLAGS) $(CFLAGS) -c -o libXpdix_la-getevents.lo `test -f 'getevents.c' || echo '$(srcdir)/'`getevents.c - -libXpdix_la-globals.lo: globals.c -@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libXpdix_la_CPPFLAGS) $(CPPFLAGS) $(libXpdix_la_CFLAGS) $(CFLAGS) -MT libXpdix_la-globals.lo -MD -MP -MF $(DEPDIR)/libXpdix_la-globals.Tpo -c -o libXpdix_la-globals.lo `test -f 'globals.c' || echo '$(srcdir)/'`globals.c -@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libXpdix_la-globals.Tpo $(DEPDIR)/libXpdix_la-globals.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='globals.c' object='libXpdix_la-globals.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libXpdix_la_CPPFLAGS) $(CPPFLAGS) $(libXpdix_la_CFLAGS) $(CFLAGS) -c -o libXpdix_la-globals.lo `test -f 'globals.c' || echo '$(srcdir)/'`globals.c - -libXpdix_la-glyphcurs.lo: glyphcurs.c -@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libXpdix_la_CPPFLAGS) $(CPPFLAGS) $(libXpdix_la_CFLAGS) $(CFLAGS) -MT libXpdix_la-glyphcurs.lo -MD -MP -MF $(DEPDIR)/libXpdix_la-glyphcurs.Tpo -c -o libXpdix_la-glyphcurs.lo `test -f 'glyphcurs.c' || echo '$(srcdir)/'`glyphcurs.c -@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libXpdix_la-glyphcurs.Tpo $(DEPDIR)/libXpdix_la-glyphcurs.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glyphcurs.c' object='libXpdix_la-glyphcurs.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libXpdix_la_CPPFLAGS) $(CPPFLAGS) $(libXpdix_la_CFLAGS) $(CFLAGS) -c -o libXpdix_la-glyphcurs.lo `test -f 'glyphcurs.c' || echo '$(srcdir)/'`glyphcurs.c - -libXpdix_la-grabs.lo: grabs.c -@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libXpdix_la_CPPFLAGS) $(CPPFLAGS) $(libXpdix_la_CFLAGS) $(CFLAGS) -MT libXpdix_la-grabs.lo -MD -MP -MF $(DEPDIR)/libXpdix_la-grabs.Tpo -c -o libXpdix_la-grabs.lo `test -f 'grabs.c' || echo '$(srcdir)/'`grabs.c -@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libXpdix_la-grabs.Tpo $(DEPDIR)/libXpdix_la-grabs.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='grabs.c' object='libXpdix_la-grabs.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libXpdix_la_CPPFLAGS) $(CPPFLAGS) $(libXpdix_la_CFLAGS) $(CFLAGS) -c -o libXpdix_la-grabs.lo `test -f 'grabs.c' || echo '$(srcdir)/'`grabs.c - -libXpdix_la-initatoms.lo: initatoms.c -@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libXpdix_la_CPPFLAGS) $(CPPFLAGS) $(libXpdix_la_CFLAGS) $(CFLAGS) -MT libXpdix_la-initatoms.lo -MD -MP -MF $(DEPDIR)/libXpdix_la-initatoms.Tpo -c -o libXpdix_la-initatoms.lo `test -f 'initatoms.c' || echo '$(srcdir)/'`initatoms.c -@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libXpdix_la-initatoms.Tpo $(DEPDIR)/libXpdix_la-initatoms.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='initatoms.c' object='libXpdix_la-initatoms.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libXpdix_la_CPPFLAGS) $(CPPFLAGS) $(libXpdix_la_CFLAGS) $(CFLAGS) -c -o libXpdix_la-initatoms.lo `test -f 'initatoms.c' || echo '$(srcdir)/'`initatoms.c - -libXpdix_la-main.lo: main.c -@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libXpdix_la_CPPFLAGS) $(CPPFLAGS) $(libXpdix_la_CFLAGS) $(CFLAGS) -MT libXpdix_la-main.lo -MD -MP -MF $(DEPDIR)/libXpdix_la-main.Tpo -c -o libXpdix_la-main.lo `test -f 'main.c' || echo '$(srcdir)/'`main.c -@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libXpdix_la-main.Tpo $(DEPDIR)/libXpdix_la-main.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='main.c' object='libXpdix_la-main.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libXpdix_la_CPPFLAGS) $(CPPFLAGS) $(libXpdix_la_CFLAGS) $(CFLAGS) -c -o libXpdix_la-main.lo `test -f 'main.c' || echo '$(srcdir)/'`main.c - -libXpdix_la-pixmap.lo: pixmap.c -@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libXpdix_la_CPPFLAGS) $(CPPFLAGS) $(libXpdix_la_CFLAGS) $(CFLAGS) -MT libXpdix_la-pixmap.lo -MD -MP -MF $(DEPDIR)/libXpdix_la-pixmap.Tpo -c -o libXpdix_la-pixmap.lo `test -f 'pixmap.c' || echo '$(srcdir)/'`pixmap.c -@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libXpdix_la-pixmap.Tpo $(DEPDIR)/libXpdix_la-pixmap.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='pixmap.c' object='libXpdix_la-pixmap.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libXpdix_la_CPPFLAGS) $(CPPFLAGS) $(libXpdix_la_CFLAGS) $(CFLAGS) -c -o libXpdix_la-pixmap.lo `test -f 'pixmap.c' || echo '$(srcdir)/'`pixmap.c - -libXpdix_la-privates.lo: privates.c -@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libXpdix_la_CPPFLAGS) $(CPPFLAGS) $(libXpdix_la_CFLAGS) $(CFLAGS) -MT libXpdix_la-privates.lo -MD -MP -MF $(DEPDIR)/libXpdix_la-privates.Tpo -c -o libXpdix_la-privates.lo `test -f 'privates.c' || echo '$(srcdir)/'`privates.c -@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libXpdix_la-privates.Tpo $(DEPDIR)/libXpdix_la-privates.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='privates.c' object='libXpdix_la-privates.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libXpdix_la_CPPFLAGS) $(CPPFLAGS) $(libXpdix_la_CFLAGS) $(CFLAGS) -c -o libXpdix_la-privates.lo `test -f 'privates.c' || echo '$(srcdir)/'`privates.c - -libXpdix_la-property.lo: property.c -@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libXpdix_la_CPPFLAGS) $(CPPFLAGS) $(libXpdix_la_CFLAGS) $(CFLAGS) -MT libXpdix_la-property.lo -MD -MP -MF $(DEPDIR)/libXpdix_la-property.Tpo -c -o libXpdix_la-property.lo `test -f 'property.c' || echo '$(srcdir)/'`property.c -@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libXpdix_la-property.Tpo $(DEPDIR)/libXpdix_la-property.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='property.c' object='libXpdix_la-property.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libXpdix_la_CPPFLAGS) $(CPPFLAGS) $(libXpdix_la_CFLAGS) $(CFLAGS) -c -o libXpdix_la-property.lo `test -f 'property.c' || echo '$(srcdir)/'`property.c - -libXpdix_la-registry.lo: registry.c -@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libXpdix_la_CPPFLAGS) $(CPPFLAGS) $(libXpdix_la_CFLAGS) $(CFLAGS) -MT libXpdix_la-registry.lo -MD -MP -MF $(DEPDIR)/libXpdix_la-registry.Tpo -c -o libXpdix_la-registry.lo `test -f 'registry.c' || echo '$(srcdir)/'`registry.c -@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libXpdix_la-registry.Tpo $(DEPDIR)/libXpdix_la-registry.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='registry.c' object='libXpdix_la-registry.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libXpdix_la_CPPFLAGS) $(CPPFLAGS) $(libXpdix_la_CFLAGS) $(CFLAGS) -c -o libXpdix_la-registry.lo `test -f 'registry.c' || echo '$(srcdir)/'`registry.c - -libXpdix_la-resource.lo: resource.c -@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libXpdix_la_CPPFLAGS) $(CPPFLAGS) $(libXpdix_la_CFLAGS) $(CFLAGS) -MT libXpdix_la-resource.lo -MD -MP -MF $(DEPDIR)/libXpdix_la-resource.Tpo -c -o libXpdix_la-resource.lo `test -f 'resource.c' || echo '$(srcdir)/'`resource.c -@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libXpdix_la-resource.Tpo $(DEPDIR)/libXpdix_la-resource.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='resource.c' object='libXpdix_la-resource.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libXpdix_la_CPPFLAGS) $(CPPFLAGS) $(libXpdix_la_CFLAGS) $(CFLAGS) -c -o libXpdix_la-resource.lo `test -f 'resource.c' || echo '$(srcdir)/'`resource.c - -libXpdix_la-selection.lo: selection.c -@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libXpdix_la_CPPFLAGS) $(CPPFLAGS) $(libXpdix_la_CFLAGS) $(CFLAGS) -MT libXpdix_la-selection.lo -MD -MP -MF $(DEPDIR)/libXpdix_la-selection.Tpo -c -o libXpdix_la-selection.lo `test -f 'selection.c' || echo '$(srcdir)/'`selection.c -@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libXpdix_la-selection.Tpo $(DEPDIR)/libXpdix_la-selection.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='selection.c' object='libXpdix_la-selection.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libXpdix_la_CPPFLAGS) $(CPPFLAGS) $(libXpdix_la_CFLAGS) $(CFLAGS) -c -o libXpdix_la-selection.lo `test -f 'selection.c' || echo '$(srcdir)/'`selection.c - -libXpdix_la-swaprep.lo: swaprep.c -@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libXpdix_la_CPPFLAGS) $(CPPFLAGS) $(libXpdix_la_CFLAGS) $(CFLAGS) -MT libXpdix_la-swaprep.lo -MD -MP -MF $(DEPDIR)/libXpdix_la-swaprep.Tpo -c -o libXpdix_la-swaprep.lo `test -f 'swaprep.c' || echo '$(srcdir)/'`swaprep.c -@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libXpdix_la-swaprep.Tpo $(DEPDIR)/libXpdix_la-swaprep.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='swaprep.c' object='libXpdix_la-swaprep.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libXpdix_la_CPPFLAGS) $(CPPFLAGS) $(libXpdix_la_CFLAGS) $(CFLAGS) -c -o libXpdix_la-swaprep.lo `test -f 'swaprep.c' || echo '$(srcdir)/'`swaprep.c - -libXpdix_la-swapreq.lo: swapreq.c -@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libXpdix_la_CPPFLAGS) $(CPPFLAGS) $(libXpdix_la_CFLAGS) $(CFLAGS) -MT libXpdix_la-swapreq.lo -MD -MP -MF $(DEPDIR)/libXpdix_la-swapreq.Tpo -c -o libXpdix_la-swapreq.lo `test -f 'swapreq.c' || echo '$(srcdir)/'`swapreq.c -@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libXpdix_la-swapreq.Tpo $(DEPDIR)/libXpdix_la-swapreq.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='swapreq.c' object='libXpdix_la-swapreq.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libXpdix_la_CPPFLAGS) $(CPPFLAGS) $(libXpdix_la_CFLAGS) $(CFLAGS) -c -o libXpdix_la-swapreq.lo `test -f 'swapreq.c' || echo '$(srcdir)/'`swapreq.c - -libXpdix_la-tables.lo: tables.c -@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libXpdix_la_CPPFLAGS) $(CPPFLAGS) $(libXpdix_la_CFLAGS) $(CFLAGS) -MT libXpdix_la-tables.lo -MD -MP -MF $(DEPDIR)/libXpdix_la-tables.Tpo -c -o libXpdix_la-tables.lo `test -f 'tables.c' || echo '$(srcdir)/'`tables.c -@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libXpdix_la-tables.Tpo $(DEPDIR)/libXpdix_la-tables.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tables.c' object='libXpdix_la-tables.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libXpdix_la_CPPFLAGS) $(CPPFLAGS) $(libXpdix_la_CFLAGS) $(CFLAGS) -c -o libXpdix_la-tables.lo `test -f 'tables.c' || echo '$(srcdir)/'`tables.c - -libXpdix_la-window.lo: window.c -@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libXpdix_la_CPPFLAGS) $(CPPFLAGS) $(libXpdix_la_CFLAGS) $(CFLAGS) -MT libXpdix_la-window.lo -MD -MP -MF $(DEPDIR)/libXpdix_la-window.Tpo -c -o libXpdix_la-window.lo `test -f 'window.c' || echo '$(srcdir)/'`window.c -@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libXpdix_la-window.Tpo $(DEPDIR)/libXpdix_la-window.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='window.c' object='libXpdix_la-window.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libXpdix_la_CPPFLAGS) $(CPPFLAGS) $(libXpdix_la_CFLAGS) $(CFLAGS) -c -o libXpdix_la-window.lo `test -f 'window.c' || echo '$(srcdir)/'`window.c - -libXpdix_la-strcasecmp.lo: strcasecmp.c -@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libXpdix_la_CPPFLAGS) $(CPPFLAGS) $(libXpdix_la_CFLAGS) $(CFLAGS) -MT libXpdix_la-strcasecmp.lo -MD -MP -MF $(DEPDIR)/libXpdix_la-strcasecmp.Tpo -c -o libXpdix_la-strcasecmp.lo `test -f 'strcasecmp.c' || echo '$(srcdir)/'`strcasecmp.c -@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libXpdix_la-strcasecmp.Tpo $(DEPDIR)/libXpdix_la-strcasecmp.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='strcasecmp.c' object='libXpdix_la-strcasecmp.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libXpdix_la_CPPFLAGS) $(CPPFLAGS) $(libXpdix_la_CFLAGS) $(CFLAGS) -c -o libXpdix_la-strcasecmp.lo `test -f 'strcasecmp.c' || echo '$(srcdir)/'`strcasecmp.c - -libXpdix_la-strcasestr.lo: strcasestr.c -@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libXpdix_la_CPPFLAGS) $(CPPFLAGS) $(libXpdix_la_CFLAGS) $(CFLAGS) -MT libXpdix_la-strcasestr.lo -MD -MP -MF $(DEPDIR)/libXpdix_la-strcasestr.Tpo -c -o libXpdix_la-strcasestr.lo `test -f 'strcasestr.c' || echo '$(srcdir)/'`strcasestr.c -@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libXpdix_la-strcasestr.Tpo $(DEPDIR)/libXpdix_la-strcasestr.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='strcasestr.c' object='libXpdix_la-strcasestr.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libXpdix_la_CPPFLAGS) $(CPPFLAGS) $(libXpdix_la_CFLAGS) $(CFLAGS) -c -o libXpdix_la-strcasestr.lo `test -f 'strcasestr.c' || echo '$(srcdir)/'`strcasestr.c - mostlyclean-libtool: -rm -f *.lo @@ -881,7 +556,7 @@ ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ - $(AWK) '{ files[$$0] = 1; nonemtpy = 1; } \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ mkid -fID $$unique tags: TAGS diff --git a/xorg-server/dix/cursor.c b/xorg-server/dix/cursor.c index 0ddf9d791..81540fd89 100644 --- a/xorg-server/dix/cursor.c +++ b/xorg-server/dix/cursor.c @@ -59,6 +59,7 @@ SOFTWARE. #include "cursorstr.h" #include "dixfontstr.h" #include "opaque.h" +#include "inputstr.h" #include "xace.h" typedef struct _GlyphShare { @@ -116,14 +117,15 @@ FreeCursor(pointer value, XID cid) CursorPtr pCurs = (CursorPtr)value; ScreenPtr pscr; + DeviceIntPtr pDev = NULL; /* unused anyway */ - if ( --pCurs->refcnt > 0) + if ( --pCurs->refcnt != 0) return(Success); for (nscr = 0; nscr < screenInfo.numScreens; nscr++) { pscr = screenInfo.screens[nscr]; - (void)( *pscr->UnrealizeCursor)( pscr, pCurs); + (void)( *pscr->UnrealizeCursor)(pDev, pscr, pCurs); } dixFreePrivates(pCurs->devPrivates); FreeCursorBits(pCurs->bits); @@ -175,9 +177,10 @@ AllocARGBCursor(unsigned char *psrcbits, unsigned char *pmaskbits, CursorPtr pCurs; int rc, nscr; ScreenPtr pscr; + DeviceIntPtr pDev; *ppCurs = NULL; - pCurs = (CursorPtr)xalloc(sizeof(CursorRec) + sizeof(CursorBits)); + pCurs = (CursorPtr)xcalloc(sizeof(CursorRec) + sizeof(CursorBits), 1); if (!pCurs) { xfree(psrcbits); @@ -194,11 +197,11 @@ AllocARGBCursor(unsigned char *psrcbits, unsigned char *pmaskbits, bits->height = cm->height; bits->xhot = cm->xhot; bits->yhot = cm->yhot; + pCurs->refcnt = 1; bits->devPrivates = NULL; bits->refcnt = -1; CheckForEmptyMask(bits); pCurs->bits = bits; - pCurs->refcnt = 1; #ifdef XFIXES pCurs->serialNumber = ++cursorSerial; pCurs->name = None; @@ -227,22 +230,51 @@ AllocARGBCursor(unsigned char *psrcbits, unsigned char *pmaskbits, /* * realize the cursor for every screen + * Do not change the refcnt, this will be changed when ChangeToCursor + * actually changes the sprite. */ for (nscr = 0; nscr < screenInfo.numScreens; nscr++) { - pscr = screenInfo.screens[nscr]; - if (!( *pscr->RealizeCursor)( pscr, pCurs)) - { - while (--nscr >= 0) - { - pscr = screenInfo.screens[nscr]; - ( *pscr->UnrealizeCursor)( pscr, pCurs); - } - dixFreePrivates(pCurs->devPrivates); - FreeCursorBits(bits); - xfree(pCurs); - return BadAlloc; - } + pscr = screenInfo.screens[nscr]; + for (pDev = inputInfo.devices; pDev; pDev = pDev->next) + { + if (DevHasCursor(pDev)) + { + if (!( *pscr->RealizeCursor)(pDev, pscr, pCurs)) + { + /* Realize failed for device pDev on screen pscr. + * We have to assume that for all devices before, realize + * worked. We need to rollback all devices so far on the + * current screen and then all devices on previous + * screens. + */ + DeviceIntPtr pDevIt = inputInfo.devices; /*dev iterator*/ + while(pDevIt && pDevIt != pDev) + { + if (DevHasCursor(pDevIt)) + ( *pscr->UnrealizeCursor)(pDevIt, pscr, pCurs); + pDevIt = pDevIt->next; + } + while (--nscr >= 0) + { + pscr = screenInfo.screens[nscr]; + /* now unrealize all devices on previous screens */ + pDevIt = inputInfo.devices; + while (pDevIt) + { + if (DevHasCursor(pDevIt)) + ( *pscr->UnrealizeCursor)(pDevIt, pscr, pCurs); + pDevIt = pDevIt->next; + } + ( *pscr->UnrealizeCursor)(pDev, pscr, pCurs); + } + dixFreePrivates(pCurs->devPrivates); + FreeCursorBits(bits); + xfree(pCurs); + return BadAlloc; + } + } + } } *ppCurs = pCurs; return rc; @@ -264,6 +296,7 @@ AllocGlyphCursor(Font source, unsigned sourceChar, Font mask, unsigned maskChar, int nscr; ScreenPtr pscr; GlyphSharePtr pShare; + DeviceIntPtr pDev; rc = dixLookupResource((pointer *)&sourcefont, source, RT_FONT, client, DixUseAccess); @@ -293,7 +326,7 @@ AllocGlyphCursor(Font source, unsigned sourceChar, Font mask, unsigned maskChar, } if (pShare) { - pCurs = (CursorPtr)xalloc(sizeof(CursorRec)); + pCurs = (CursorPtr)xcalloc(sizeof(CursorRec), 1); if (!pCurs) return BadAlloc; bits = pShare->bits; @@ -335,7 +368,8 @@ AllocGlyphCursor(Font source, unsigned sourceChar, Font mask, unsigned maskChar, } if (sourcefont != maskfont) { - pCurs = (CursorPtr)xalloc(sizeof(CursorRec) + sizeof(CursorBits)); + pCurs = + (CursorPtr)xcalloc(sizeof(CursorRec) + sizeof(CursorBits), 1); if (pCurs) bits = (CursorBitsPtr)((char *)pCurs + sizeof(CursorRec)); else @@ -343,9 +377,9 @@ AllocGlyphCursor(Font source, unsigned sourceChar, Font mask, unsigned maskChar, } else { - pCurs = (CursorPtr)xalloc(sizeof(CursorRec)); + pCurs = (CursorPtr)xcalloc(sizeof(CursorRec), 1); if (pCurs) - bits = (CursorBitsPtr)xalloc(sizeof(CursorBits)); + bits = (CursorBitsPtr)xcalloc(sizeof(CursorBits), 1); else bits = (CursorBitsPtr)NULL; } @@ -386,6 +420,7 @@ AllocGlyphCursor(Font source, unsigned sourceChar, Font mask, unsigned maskChar, sharedGlyphs = pShare; } } + CheckForEmptyMask(bits); pCurs->bits = bits; pCurs->refcnt = 1; @@ -420,19 +455,52 @@ AllocGlyphCursor(Font source, unsigned sourceChar, Font mask, unsigned maskChar, */ for (nscr = 0; nscr < screenInfo.numScreens; nscr++) { - pscr = screenInfo.screens[nscr]; - if (!( *pscr->RealizeCursor)( pscr, pCurs)) - { - while (--nscr >= 0) - { - pscr = screenInfo.screens[nscr]; - ( *pscr->UnrealizeCursor)( pscr, pCurs); - } - dixFreePrivates(pCurs->devPrivates); - FreeCursorBits(pCurs->bits); - xfree(pCurs); - return BadAlloc; - } + pscr = screenInfo.screens[nscr]; + + for (pDev = inputInfo.devices; pDev; pDev = pDev->next) + { + if (DevHasCursor(pDev)) + { + if (!( *pscr->RealizeCursor)(pDev, pscr, pCurs)) + { + /* Realize failed for device pDev on screen pscr. + * We have to assume that for all devices before, realize + * worked. We need to rollback all devices so far on the + * current screen and then all devices on previous + * screens. + */ + DeviceIntPtr pDevIt = inputInfo.devices; /*dev iterator*/ + while(pDevIt && pDevIt != pDev) + { + if (DevHasCursor(pDevIt)) + ( *pscr->UnrealizeCursor)(pDevIt, pscr, pCurs); + pDevIt = pDevIt->next; + } + + (*pscr->UnrealizeCursor)(inputInfo.pointer, pscr, pCurs); + + while (--nscr >= 0) + { + pscr = screenInfo.screens[nscr]; + /* now unrealize all devices on previous screens */ + ( *pscr->UnrealizeCursor)(inputInfo.pointer, pscr, pCurs); + + pDevIt = inputInfo.devices; + while (pDevIt) + { + if (DevHasCursor(pDevIt)) + ( *pscr->UnrealizeCursor)(pDevIt, pscr, pCurs); + pDevIt = pDevIt->next; + } + ( *pscr->UnrealizeCursor)(pDev, pscr, pCurs); + } + dixFreePrivates(pCurs->devPrivates); + FreeCursorBits(bits); + xfree(pCurs); + return BadAlloc; + } + } + } } *ppCurs = pCurs; return Success; diff --git a/xorg-server/dix/devices.c b/xorg-server/dix/devices.c index 5a726afe8..3b8d544da 100644 --- a/xorg-server/dix/devices.c +++ b/xorg-server/dix/devices.c @@ -27,13 +27,13 @@ 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, +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 +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. +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 @@ -57,11 +57,13 @@ SOFTWARE. #define NEED_EVENTS #define NEED_REPLIES #include <X11/Xproto.h> +#include <X11/Xatom.h> #include "windowstr.h" #include "inputstr.h" #include "scrnintstr.h" #include "cursorstr.h" #include "dixstruct.h" +#include "ptrveloc.h" #include "site.h" #ifndef XKB_IN_SERVER #define XKB_IN_SERVER @@ -71,21 +73,109 @@ SOFTWARE. #endif #include "privates.h" #include "xace.h" +#include "mi.h" #include "dispatch.h" #include "swaprep.h" #include "dixevents.h" +#include "mipointer.h" #include <X11/extensions/XI.h> #include <X11/extensions/XIproto.h> #include "exglobals.h" #include "exevents.h" +#include "listdev.h" /* for CopySwapXXXClass */ +#include "xiproperty.h" +#include "enterleave.h" /* for EnterWindow() */ +#include "xserver-properties.h" /** @file * This file handles input device-related stuff. */ -DevPrivateKey CoreDevicePrivateKey = &CoreDevicePrivateKey; +static int CoreDevicePrivateKeyIndex; +DevPrivateKey CoreDevicePrivateKey = &CoreDevicePrivateKeyIndex; +/* Used to sture classes currently not in use by an MD */ +static int UnusedClassesPrivateKeyIndex; +DevPrivateKey UnusedClassesPrivateKey = &UnusedClassesPrivateKeyIndex; + + +/** + * DIX property handler. + */ +static int +DeviceSetProperty(DeviceIntPtr dev, Atom property, XIPropertyValuePtr prop, + BOOL checkonly) +{ + if (property == XIGetKnownProperty(XI_PROP_ENABLED)) + { + if (prop->format != 8 || prop->type != XA_INTEGER || prop->size != 1) + return BadValue; + + /* Don't allow disabling of VCP/VCK */ + if ((dev == inputInfo.pointer || dev == inputInfo.keyboard) && + !(*(CARD8*)prop->data)) + return BadAccess; + + if (!checkonly) + { + if ((*((CARD8*)prop->data)) && !dev->enabled) + EnableDevice(dev); + else if (!(*((CARD8*)prop->data)) && dev->enabled) + DisableDevice(dev); + } + } + + return Success; +} + +/* Pair the keyboard to the pointer device. Keyboard events will follow the + * pointer sprite. Only applicable for master devices. + * If the client is set, the request to pair comes from some client. In this + * case, we need to check for access. If the client is NULL, it's from an + * internal automatic pairing, we must always permit this. + */ +static int +PairDevices(ClientPtr client, DeviceIntPtr ptr, DeviceIntPtr kbd) +{ + if (!ptr) + return BadDevice; + + /* Don't allow pairing for slave devices */ + if (!ptr->isMaster || !kbd->isMaster) + return BadDevice; + + if (ptr->spriteInfo->paired) + return BadDevice; + + if (kbd->spriteInfo->spriteOwner) + { + xfree(kbd->spriteInfo->sprite); + kbd->spriteInfo->sprite = NULL; + kbd->spriteInfo->spriteOwner = FALSE; + } + + kbd->spriteInfo->sprite = ptr->spriteInfo->sprite; + kbd->spriteInfo->paired = ptr; + ptr->spriteInfo->paired = kbd; + return Success; +} + + +/** + * Find and return the next unpaired MD pointer device. + */ +static DeviceIntPtr +NextFreePointerDevice(void) +{ + DeviceIntPtr dev; + for (dev = inputInfo.devices; dev; dev = dev->next) + if (dev->isMaster && + dev->spriteInfo->spriteOwner && + !dev->spriteInfo->paired) + return dev; + return NULL; +} /** * Create a new input device and init it to sane values. The device is added @@ -95,69 +185,48 @@ DevPrivateKey CoreDevicePrivateKey = &CoreDevicePrivateKey; * @return The newly created device. */ DeviceIntPtr -AddInputDevice(DeviceProc deviceProc, Bool autoStart) +AddInputDevice(ClientPtr client, DeviceProc deviceProc, Bool autoStart) { DeviceIntPtr dev, *prev; /* not a typo */ DeviceIntPtr devtmp; int devid; - char devind[MAX_DEVICES]; + char devind[MAXDEVICES]; + BOOL enabled; /* Find next available id */ - memset(devind, 0, sizeof(char)*MAX_DEVICES); + memset(devind, 0, sizeof(char)*MAXDEVICES); for (devtmp = inputInfo.devices; devtmp; devtmp = devtmp->next) devind[devtmp->id]++; for (devtmp = inputInfo.off_devices; devtmp; devtmp = devtmp->next) devind[devtmp->id]++; - for (devid = 0; devid < MAX_DEVICES && devind[devid]; devid++) + for (devid = 0; devid < MAXDEVICES && devind[devid]; devid++) ; - if (devid >= MAX_DEVICES) + if (devid >= MAXDEVICES) return (DeviceIntPtr)NULL; - dev = (DeviceIntPtr) xcalloc(sizeof(DeviceIntRec), 1); + dev = xcalloc(sizeof(DeviceIntRec) + sizeof(SpriteInfoRec), 1); if (!dev) return (DeviceIntPtr)NULL; - dev->name = (char *)NULL; - dev->type = 0; dev->id = devid; - dev->public.on = FALSE; dev->public.processInputProc = (ProcessInputProc)NoopDDA; dev->public.realInputProc = (ProcessInputProc)NoopDDA; dev->public.enqueueInputProc = EnqueueEvent; dev->deviceProc = deviceProc; dev->startup = autoStart; - dev->sync.frozen = FALSE; - dev->sync.other = NullGrab; - dev->sync.state = NOT_GRABBED; - dev->sync.event = (xEvent *) NULL; - dev->sync.evcount = 0; - dev->grab = NullGrab; - dev->grabTime = currentTime; - dev->fromPassiveGrab = FALSE; - dev->key = (KeyClassPtr)NULL; - dev->valuator = (ValuatorClassPtr)NULL; - dev->button = (ButtonClassPtr)NULL; - dev->focus = (FocusClassPtr)NULL; - dev->proximity = (ProximityClassPtr)NULL; - dev->absolute = (AbsoluteClassPtr)NULL; - dev->kbdfeed = (KbdFeedbackPtr)NULL; - dev->ptrfeed = (PtrFeedbackPtr)NULL; - dev->intfeed = (IntegerFeedbackPtr)NULL; - dev->stringfeed = (StringFeedbackPtr)NULL; - dev->bell = (BellFeedbackPtr)NULL; - dev->leds = (LedFeedbackPtr)NULL; -#ifdef XKB - dev->xkb_interest = NULL; -#endif - dev->config_info = NULL; - dev->devPrivates = NULL; - dev->unwrapProc = NULL; + + /* device grab defaults */ + dev->deviceGrab.grabTime = currentTime; + dev->deviceGrab.ActivateGrab = ActivateKeyboardGrab; + dev->deviceGrab.DeactivateGrab = DeactivateKeyboardGrab; + dev->coreEvents = TRUE; - dev->inited = FALSE; - dev->enabled = FALSE; + + /* sprite defaults */ + dev->spriteInfo = (SpriteInfoPtr)&dev[1]; /* security creation/labeling check */ - if (XaceHook(XACE_DEVICE_ACCESS, serverClient, dev, DixCreateAccess)) { + if (XaceHook(XACE_DEVICE_ACCESS, client, dev, DixCreateAccess)) { xfree(dev); return NULL; } @@ -169,14 +238,24 @@ AddInputDevice(DeviceProc deviceProc, Bool autoStart) *prev = dev; dev->next = NULL; + enabled = FALSE; + XIChangeDeviceProperty(dev, XIGetKnownProperty(XI_PROP_ENABLED), + XA_INTEGER, 8, PropModeReplace, 1, &enabled, + FALSE); + XISetDevicePropertyDeletable(dev, XIGetKnownProperty(XI_PROP_ENABLED), FALSE); + XIRegisterPropertyHandler(dev, DeviceSetProperty, NULL, NULL); + return dev; } /** + * Enable the device through the driver, add the device to the device list. * Switch device ON through the driver and push it onto the global device - * list. All clients are notified about the device being enabled. + * list. Initialize the DIX sprite or pair the device. All clients are + * notified about the device being enabled. * - * A device will send events once enabled. + * A master pointer device needs to be enabled before a master keyboard + * device. * * @param The device to be enabled. * @return TRUE on success or FALSE otherwise. @@ -187,15 +266,62 @@ EnableDevice(DeviceIntPtr dev) DeviceIntPtr *prev; int ret; DeviceIntRec dummyDev; + DeviceIntPtr other; devicePresenceNotify ev; + int namelen = 0; /* dummy */ + int evsize = sizeof(xEvent); + int listlen; + EventListPtr evlist; + BOOL enabled; for (prev = &inputInfo.off_devices; *prev && (*prev != dev); prev = &(*prev)->next) ; + + if (!dev->spriteInfo->sprite) + { + if (dev->isMaster) + { + /* Sprites appear on first root window, so we can hardcode it */ + if (dev->spriteInfo->spriteOwner) + { + InitializeSprite(dev, WindowTable[0]); + /* mode doesn't matter */ + EnterWindow(dev, WindowTable[0], NotifyAncestor); + } + else if ((other = NextFreePointerDevice()) == NULL) + { + ErrorF("[dix] cannot find pointer to pair with. " + "This is a bug.\n"); + return FALSE; + } else + PairDevices(NULL, other, dev); + } else + { + other = (IsPointerDevice(dev)) ? inputInfo.pointer : + inputInfo.keyboard; + AttachDevice(NULL, dev, other); + } + } + + /* Before actually enabling the device, we need to make sure the event + * list's events have enough memory for a ClassesChangedEvent from the + * device + */ + + SizeDeviceInfo(dev, &namelen, &evsize); + + listlen = GetEventList(&evlist); + OsBlockSignals(); + SetMinimumEventSize(evlist, listlen, evsize); + mieqResizeEvents(evsize); + OsReleaseSignals(); + + if ((*prev != dev) || !dev->inited || ((ret = (*dev->deviceProc)(dev, DEVICE_ON)) != Success)) { - ErrorF("couldn't enable device %d\n", dev->id); + ErrorF("[dix] couldn't enable device %d\n", dev->id); return FALSE; } dev->enabled = TRUE; @@ -206,11 +332,16 @@ EnableDevice(DeviceIntPtr dev) *prev = dev; dev->next = NULL; + enabled = TRUE; + XIChangeDeviceProperty(dev, XIGetKnownProperty(XI_PROP_ENABLED), + XA_INTEGER, 8, PropModeReplace, 1, &enabled, + TRUE); + ev.type = DevicePresenceNotify; ev.time = currentTime.milliseconds; ev.devchange = DeviceEnabled; ev.deviceid = dev->id; - dummyDev.id = 0; + dummyDev.id = MAXDEVICES; SendEventToAllWindows(&dummyDev, DevicePresenceNotifyMask, (xEvent *) &ev, 1); @@ -222,14 +353,18 @@ EnableDevice(DeviceIntPtr dev) * list. A device will not send events while disabled. All clients are * notified about the device being disabled. * + * Master keyboard devices have to be disabled before master pointer devices + * otherwise things turn bad. + * * @return TRUE on success or FALSE otherwise. */ Bool DisableDevice(DeviceIntPtr dev) { - DeviceIntPtr *prev; + DeviceIntPtr *prev, other; DeviceIntRec dummyDev; devicePresenceNotify ev; + BOOL enabled; for (prev = &inputInfo.devices; *prev && (*prev != dev); @@ -237,17 +372,54 @@ DisableDevice(DeviceIntPtr dev) ; if (*prev != dev) return FALSE; + + /* float attached devices */ + if (dev->isMaster) + { + for (other = inputInfo.devices; other; other = other->next) + { + if (other->u.master == dev) + AttachDevice(NULL, other, NULL); + } + } + else + { + for (other = inputInfo.devices; other; other = other->next) + { + if (other->isMaster && other->u.lastSlave == dev) + other->u.lastSlave = NULL; + } + } + + if (dev->isMaster && dev->spriteInfo->sprite) + { + for (other = inputInfo.devices; other; other = other->next) + { + if (other->spriteInfo->paired == dev) + { + ErrorF("[dix] cannot disable device, still paired. " + "This is a bug. \n"); + return FALSE; + } + } + } + (void)(*dev->deviceProc)(dev, DEVICE_OFF); dev->enabled = FALSE; *prev = dev->next; dev->next = inputInfo.off_devices; inputInfo.off_devices = dev; + enabled = FALSE; + XIChangeDeviceProperty(dev, XIGetKnownProperty(XI_PROP_ENABLED), + XA_INTEGER, 8, PropModeReplace, 1, &enabled, + TRUE); + ev.type = DevicePresenceNotify; ev.time = currentTime.milliseconds; ev.devchange = DeviceDisabled; ev.deviceid = dev->id; - dummyDev.id = 0; + dummyDev.id = MAXDEVICES; SendEventToAllWindows(&dummyDev, DevicePresenceNotifyMask, (xEvent *) &ev, 1); @@ -257,7 +429,8 @@ DisableDevice(DeviceIntPtr dev) /** * Initialise a new device through the driver and tell all clients about the * new device. - * + * + * Must be called before EnableDevice. * The device will NOT send events until it is enabled! * * @return Success or an error code on failure. @@ -268,18 +441,27 @@ ActivateDevice(DeviceIntPtr dev) int ret = Success; devicePresenceNotify ev; DeviceIntRec dummyDev; + ScreenPtr pScreen = screenInfo.screens[0]; if (!dev || !dev->deviceProc) return BadImplementation; ret = (*dev->deviceProc) (dev, DEVICE_INIT); dev->inited = (ret == Success); - + if (!dev->inited) + return ret; + + /* Initialize memory for sprites. */ + if (dev->isMaster && dev->spriteInfo->spriteOwner) + pScreen->DeviceCursorInitialize(dev, pScreen); + ev.type = DevicePresenceNotify; ev.time = currentTime.milliseconds; ev.devchange = DeviceAdded; ev.deviceid = dev->id; - dummyDev.id = 0; + + memset(&dummyDev, 0, sizeof(DeviceIntRec)); + dummyDev.id = MAXDEVICES; SendEventToAllWindows(&dummyDev, DevicePresenceNotifyMask, (xEvent *) &ev, 1); @@ -305,7 +487,7 @@ CoreKeyboardCtl(DeviceIntPtr pDev, KeybdCtrl *ctrl) } /** - * Device control function for the Virtual Core Keyboard. + * Device control function for the Virtual Core Keyboard. */ static int CoreKeyboardProc(DeviceIntPtr pDev, int what) @@ -315,9 +497,16 @@ CoreKeyboardProc(DeviceIntPtr pDev, int what) #ifdef XKB XkbComponentNamesRec names; #endif + ClassesPtr classes; switch (what) { case DEVICE_INIT: + if (!(classes = xcalloc(1, sizeof(ClassesRec)))) + { + ErrorF("[dix] Could not allocate device classes.\n"); + return BadAlloc; + } + keySyms.minKeyCode = 8; keySyms.maxKeyCode = 255; keySyms.mapWidth = 4; @@ -326,21 +515,21 @@ CoreKeyboardProc(DeviceIntPtr pDev, int what) keySyms.minKeyCode + 1) * keySyms.mapWidth); if (!keySyms.map) { - ErrorF("Couldn't allocate core keymap\n"); + ErrorF("[dix] Couldn't allocate core keymap\n"); + xfree(classes); return BadAlloc; } - modMap = (CARD8 *)xalloc(MAP_LENGTH); + modMap = xcalloc(1, MAP_LENGTH); if (!modMap) { - ErrorF("Couldn't allocate core modifier map\n"); + ErrorF("[dix] Couldn't allocate core modifier map\n"); + xfree(classes); return BadAlloc; } - bzero((char *)modMap, MAP_LENGTH); #ifdef XKB if (!noXkbExtension) { bzero(&names, sizeof(names)); - XkbSetRulesDflts("base", "pc105", "us", NULL, NULL); XkbInitKeyboardDeviceStruct(pDev, &names, &keySyms, modMap, CoreKeyboardBell, CoreKeyboardCtl); } @@ -354,11 +543,9 @@ CoreKeyboardProc(DeviceIntPtr pDev, int what) xfree(keySyms.map); xfree(modMap); - break; case DEVICE_CLOSE: - dixSetPrivate(&pDev->devPrivates, CoreDevicePrivateKey, NULL); break; default: @@ -369,28 +556,34 @@ CoreKeyboardProc(DeviceIntPtr pDev, int what) /** * Device control function for the Virtual Core Pointer. + * + * Aside from initialisation, it backs up the original device classes into the + * devicePrivates. This only needs to be done for master devices. */ static int CorePointerProc(DeviceIntPtr pDev, int what) { BYTE map[33]; int i = 0; + ClassesPtr classes; switch (what) { case DEVICE_INIT: + if (!(classes = xcalloc(1, sizeof(ClassesRec)))) + return BadAlloc; + for (i = 1; i <= 32; i++) map[i] = i; InitPointerDeviceStruct((DevicePtr)pDev, map, 32, - GetMotionHistory, (PtrCtrlProcPtr)NoopDDA, + (PtrCtrlProcPtr)NoopDDA, GetMotionHistorySize(), 2); pDev->valuator->axisVal[0] = screenInfo.screens[0]->width / 2; - pDev->valuator->lastx = pDev->valuator->axisVal[0]; + pDev->last.valuators[0] = pDev->valuator->axisVal[0]; pDev->valuator->axisVal[1] = screenInfo.screens[0]->height / 2; - pDev->valuator->lasty = pDev->valuator->axisVal[1]; + pDev->last.valuators[1] = pDev->valuator->axisVal[1]; break; case DEVICE_CLOSE: - dixSetPrivate(&pDev->devPrivates, CoreDevicePrivateKey, NULL); break; default: @@ -402,68 +595,41 @@ CorePointerProc(DeviceIntPtr pDev, int what) /** * Initialise the two core devices, VCP and VCK (see events.c). - * The devices are activated but not enabled. + * Both devices are not tied to physical devices, but guarantee that there is + * always a keyboard and a pointer present and keep the protocol semantics. + * * Note that the server MUST have two core devices at all times, even if there * is no physical device connected. */ void InitCoreDevices(void) { - DeviceIntPtr dev; + if (AllocMasterDevice(serverClient, "Virtual core", + &inputInfo.pointer, + &inputInfo.keyboard) != Success) + FatalError("Failed to allocate core devices"); + + ActivateDevice(inputInfo.pointer); + ActivateDevice(inputInfo.keyboard); + EnableDevice(inputInfo.pointer); + EnableDevice(inputInfo.keyboard); - if (!inputInfo.keyboard) { - dev = AddInputDevice(CoreKeyboardProc, TRUE); - if (!dev) - FatalError("Failed to allocate core keyboard"); - dev->name = strdup("Virtual core keyboard"); -#ifdef XKB - dev->public.processInputProc = CoreProcessKeyboardEvent; - dev->public.realInputProc = CoreProcessKeyboardEvent; - if (!noXkbExtension) - XkbSetExtension(dev, ProcessKeyboardEvent); -#else - dev->public.processInputProc = ProcessKeyboardEvent; - dev->public.realInputProc = ProcessKeyboardEvent; -#endif - dev->ActivateGrab = ActivateKeyboardGrab; - dev->DeactivateGrab = DeactivateKeyboardGrab; - dev->coreEvents = FALSE; - (void)ActivateDevice(dev); - inputInfo.keyboard = dev; - } - - if (!inputInfo.pointer) { - dev = AddInputDevice(CorePointerProc, TRUE); - if (!dev) - FatalError("Failed to allocate core pointer"); - dev->name = strdup("Virtual core pointer"); -#ifdef XKB - dev->public.processInputProc = CoreProcessPointerEvent; - dev->public.realInputProc = CoreProcessPointerEvent; - if (!noXkbExtension) - XkbSetExtension(dev, ProcessPointerEvent); -#else - dev->public.processInputProc = ProcessPointerEvent; - dev->public.realInputProc = ProcessPointerEvent; -#endif - dev->ActivateGrab = ActivatePointerGrab; - dev->DeactivateGrab = DeactivatePointerGrab; - dev->coreEvents = FALSE; - (void)ActivateDevice(dev); - inputInfo.pointer = dev; - } } /** * Activate all switched-off devices and then enable all those devices. - * + * * Will return an error if no core keyboard or core pointer is present. * In theory this should never happen if you call InitCoreDevices() first. - * + * + * InitAndStartDevices needs to be called AFTER the windows are initialized. + * Devices will start sending events after InitAndStartDevices() has + * completed. + * * @return Success or error code on failure. */ int -InitAndStartDevices(void) +InitAndStartDevices() { DeviceIntPtr dev, next; @@ -472,6 +638,8 @@ InitAndStartDevices(void) if (!dev->inited) ActivateDevice(dev); } + + /* enable real devices */ for (dev = inputInfo.off_devices; dev; dev = next) { DebugF("(dix) enabling device %d\n", dev->id); @@ -479,27 +647,183 @@ InitAndStartDevices(void) if (dev->inited && dev->startup) (void)EnableDevice(dev); } - for (dev = inputInfo.devices; - dev && (dev != inputInfo.keyboard); - dev = dev->next) - ; - if (!dev || (dev != inputInfo.keyboard)) { - ErrorF("No core keyboard\n"); - return BadImplementation; + + return Success; +} + +/** + * Free the given device class and reset the pointer to NULL. + */ +static void +FreeDeviceClass(int type, pointer *class) +{ + if (!(*class)) + return; + + switch(type) + { + case KeyClass: + { + KeyClassPtr* k = (KeyClassPtr*)class; +#ifdef XKB + if ((*k)->xkbInfo) + { + XkbFreeInfo((*k)->xkbInfo); + (*k)->xkbInfo = NULL; + } +#endif + xfree((*k)->curKeySyms.map); + xfree((*k)->modifierKeyMap); + xfree((*k)); + break; + } + case ButtonClass: + { + ButtonClassPtr *b = (ButtonClassPtr*)class; +#ifdef XKB + if ((*b)->xkb_acts) + xfree((*b)->xkb_acts); +#endif + xfree((*b)); + break; + } + case ValuatorClass: + { + ValuatorClassPtr *v = (ValuatorClassPtr*)class; + + /* Counterpart to 'biggest hack ever' in init. */ + if ((*v)->motion) + xfree((*v)->motion); + xfree((*v)); + break; + } + case FocusClass: + { + FocusClassPtr *f = (FocusClassPtr*)class; + xfree((*f)->trace); + xfree((*f)); + break; + } + case ProximityClass: + { + ProximityClassPtr *p = (ProximityClassPtr*)class; + xfree((*p)); + break; + } } - for (dev = inputInfo.devices; - dev && (dev != inputInfo.pointer); - dev = dev->next) - ; - if (!dev || (dev != inputInfo.pointer)) { - ErrorF("No core pointer\n"); - return BadImplementation; + *class = NULL; +} + +static void +FreeFeedbackClass(int type, pointer *class) +{ + if (!(*class)) + return; + + switch(type) + { + case KbdFeedbackClass: + { + KbdFeedbackPtr *kbdfeed = (KbdFeedbackPtr*)class; + KbdFeedbackPtr k, knext; + for (k = (*kbdfeed); k; k = knext) { + knext = k->next; +#ifdef XKB + if (k->xkb_sli) + XkbFreeSrvLedInfo(k->xkb_sli); +#endif + xfree(k); + } + break; + } + case PtrFeedbackClass: + { + PtrFeedbackPtr *ptrfeed = (PtrFeedbackPtr*)class; + PtrFeedbackPtr p, pnext; + + for (p = (*ptrfeed); p; p = pnext) { + pnext = p->next; + xfree(p); + } + break; + } + case IntegerFeedbackClass: + { + IntegerFeedbackPtr *intfeed = (IntegerFeedbackPtr*)class; + IntegerFeedbackPtr i, inext; + + for (i = (*intfeed); i; i = inext) { + inext = i->next; + xfree(i); + } + break; + } + case StringFeedbackClass: + { + StringFeedbackPtr *stringfeed = (StringFeedbackPtr*)class; + StringFeedbackPtr s, snext; + + for (s = (*stringfeed); s; s = snext) { + snext = s->next; + xfree(s->ctrl.symbols_supported); + xfree(s->ctrl.symbols_displayed); + xfree(s); + } + break; + } + case BellFeedbackClass: + { + BellFeedbackPtr *bell = (BellFeedbackPtr*)class; + BellFeedbackPtr b, bnext; + + for (b = (*bell); b; b = bnext) { + bnext = b->next; + xfree(b); + } + break; + } + case LedFeedbackClass: + { + LedFeedbackPtr *leds = (LedFeedbackPtr*)class; + LedFeedbackPtr l, lnext; + + for (l = (*leds); l; l = lnext) { + lnext = l->next; +#ifdef XKB + if (l->xkb_sli) + XkbFreeSrvLedInfo(l->xkb_sli); +#endif + xfree(l); + } + break; + } } - return Success; + *class = NULL; +} + +static void +FreeAllDeviceClasses(ClassesPtr classes) +{ + if (!classes) + return; + + FreeDeviceClass(KeyClass, (pointer)&classes->key); + FreeDeviceClass(ValuatorClass, (pointer)&classes->valuator); + FreeDeviceClass(ButtonClass, (pointer)&classes->button); + FreeDeviceClass(FocusClass, (pointer)&classes->focus); + FreeDeviceClass(ProximityClass, (pointer)&classes->proximity); + + FreeFeedbackClass(KbdFeedbackClass, (pointer)&classes->kbdfeed); + FreeFeedbackClass(PtrFeedbackClass, (pointer)&classes->ptrfeed); + FreeFeedbackClass(IntegerFeedbackClass, (pointer)&classes->intfeed); + FreeFeedbackClass(StringFeedbackClass, (pointer)&classes->stringfeed); + FreeFeedbackClass(BellFeedbackClass, (pointer)&classes->bell); + FreeFeedbackClass(LedFeedbackClass, (pointer)&classes->leds); + } /** - * Close down a device and free all resources. + * Close down a device and free all resources. * Once closed down, the driver will probably not expect you that you'll ever * enable it again and free associated structs. If you want the device to just * be disabled, DisableDevice(). @@ -508,106 +832,65 @@ InitAndStartDevices(void) static void CloseDevice(DeviceIntPtr dev) { - KbdFeedbackPtr k, knext; - PtrFeedbackPtr p, pnext; - IntegerFeedbackPtr i, inext; - StringFeedbackPtr s, snext; - BellFeedbackPtr b, bnext; - LedFeedbackPtr l, lnext; + ScreenPtr screen = screenInfo.screens[0]; + ClassesPtr classes; + int j; + + if (!dev) + return; + + XIDeleteAllDeviceProperties(dev); if (dev->inited) (void)(*dev->deviceProc)(dev, DEVICE_CLOSE); - xfree(dev->name); + /* free sprite memory */ + if (dev->isMaster && dev->spriteInfo->sprite) + screen->DeviceCursorCleanup(dev, screen); - if (dev->key) { -#ifdef XKB - if (dev->key->xkbInfo) - XkbFreeInfo(dev->key->xkbInfo); -#endif - dev->key->xkbInfo = NULL; - xfree(dev->key->curKeySyms.map); - xfree(dev->key->modifierKeyMap); - xfree(dev->key); - dev->key = NULL; - } + /* free acceleration info */ + if(dev->valuator && dev->valuator->accelScheme.AccelCleanupProc) + dev->valuator->accelScheme.AccelCleanupProc(dev); - if (dev->valuator) { - /* Counterpart to 'biggest hack ever' in init. */ - if (dev->valuator->motion && - dev->valuator->GetMotionProc == GetMotionHistory) - xfree(dev->valuator->motion); - xfree(dev->valuator); - } + xfree(dev->name); - if (dev->button) { -#ifdef XKB - if (dev->button->xkb_acts) - xfree(dev->button->xkb_acts); -#endif - xfree(dev->button); - } + classes = (ClassesPtr)&dev->key; + FreeAllDeviceClasses(classes); - if (dev->focus) { - xfree(dev->focus->trace); - xfree(dev->focus); + if (dev->isMaster) + { + classes = dixLookupPrivate(&dev->devPrivates, UnusedClassesPrivateKey); + FreeAllDeviceClasses(classes); } - if (dev->proximity) - xfree(dev->proximity); - for (k = dev->kbdfeed; k; k = knext) { - knext = k->next; #ifdef XKB - if (k->xkb_sli) - XkbFreeSrvLedInfo(k->xkb_sli); + while (dev->xkb_interest) + XkbRemoveResourceClient((DevicePtr)dev,dev->xkb_interest->resource); #endif - xfree(k); - } - for (p = dev->ptrfeed; p; p = pnext) { - pnext = p->next; - xfree(p); - } - - for (i = dev->intfeed; i; i = inext) { - inext = i->next; - xfree(i); + if (DevHasCursor(dev) && dev->spriteInfo->sprite) { + xfree(dev->spriteInfo->sprite->spriteTrace); + xfree(dev->spriteInfo->sprite); } - for (s = dev->stringfeed; s; s = snext) { - snext = s->next; - xfree(s->ctrl.symbols_supported); - xfree(s->ctrl.symbols_displayed); - xfree(s); - } - - for (b = dev->bell; b; b = bnext) { - bnext = b->next; - xfree(b); - } - - for (l = dev->leds; l; l = lnext) { - lnext = l->next; -#ifdef XKB - if (l->xkb_sli) - XkbFreeSrvLedInfo(l->xkb_sli); -#endif - xfree(l); + /* a client may have the device set as client pointer */ + for (j = 0; j < currentMaxClients; j++) + { + if (clients[j] && clients[j]->clientPtr == dev) + { + clients[j]->clientPtr = NULL; + clients[j]->clientPtr = PickPointer(clients[j]); + } } -#ifdef XKB - while (dev->xkb_interest) - XkbRemoveResourceClient((DevicePtr)dev,dev->xkb_interest->resource); -#endif - - xfree(dev->sync.event); + xfree(dev->deviceGrab.sync.event); dixFreePrivates(dev->devPrivates); xfree(dev); } /** - * Shut down all devices, free all resources, etc. + * Shut down all devices, free all resources, etc. * Only useful if you're shutting down the server! */ void @@ -615,6 +898,17 @@ CloseDownDevices(void) { DeviceIntPtr dev, next; + /* Float all SDs before closing them. Note that at this point resources + * (e.g. cursors) have been freed already, so we can't just call + * AttachDevice(NULL, dev, NULL). Instead, we have to forcibly set master + * to NULL and pretend nothing happened. + */ + for (dev = inputInfo.devices; dev; dev = dev->next) + { + if (!dev->isMaster && dev->u.master) + dev->u.master = NULL; + } + for (dev = inputInfo.devices; dev; dev = next) { next = dev->next; @@ -625,17 +919,40 @@ CloseDownDevices(void) next = dev->next; DeleteInputDeviceRequest(dev); } + inputInfo.devices = NULL; inputInfo.off_devices = NULL; inputInfo.keyboard = NULL; inputInfo.pointer = NULL; +#ifdef XKB + XkbDeleteRulesDflts(); +#endif +} + +/** + * Remove the cursor sprite for all devices. This needs to be done before any + * resources are freed or any device is deleted. + */ +void +UndisplayDevices() +{ + DeviceIntPtr dev; + ScreenPtr screen = screenInfo.screens[0]; + + for (dev = inputInfo.devices; dev; dev = dev->next) + screen->DisplayCursor(dev, screen, NullCursor); } /** * Remove a device from the device list, closes it and thus frees all - * resources. + * resources. * Removes both enabled and disabled devices and notifies all devices about * the removal of the device. + * + * No PresenceNotify is sent for device that the client never saw. This can + * happen if a malloc fails during the addition of master devices. If + * dev->init is FALSE it means the client never received a DeviceAdded event, + * so let's not send a DeviceRemoved event either. */ int RemoveDevice(DeviceIntPtr dev) @@ -644,13 +961,19 @@ RemoveDevice(DeviceIntPtr dev) int ret = BadMatch; devicePresenceNotify ev; DeviceIntRec dummyDev; + ScreenPtr screen = screenInfo.screens[0]; int deviceid; + int initialized; DebugF("(dix) removing device %d\n", dev->id); if (!dev || dev == inputInfo.keyboard || dev == inputInfo.pointer) return BadImplementation; + initialized = dev->inited; + if (DevHasCursor(dev)) + screen->DisplayCursor(dev, screen, NullCursor); + deviceid = dev->id; DisableDevice(dev); @@ -658,13 +981,13 @@ RemoveDevice(DeviceIntPtr dev) for (tmp = inputInfo.devices; tmp; (prev = tmp), (tmp = next)) { next = tmp->next; if (tmp == dev) { - CloseDevice(tmp); if (prev==NULL) inputInfo.devices = next; else prev->next = next; + CloseDevice(tmp); ret = Success; } } @@ -683,14 +1006,14 @@ RemoveDevice(DeviceIntPtr dev) ret = Success; } } - - if (ret == Success) { + + if (ret == Success && initialized) { inputInfo.numDevices--; ev.type = DevicePresenceNotify; ev.time = currentTime.milliseconds; ev.devchange = DeviceRemoved; ev.deviceid = deviceid; - dummyDev.id = 0; + dummyDev.id = MAXDEVICES; SendEventToAllWindows(&dummyDev, DevicePresenceNotifyMask, (xEvent *) &ev, 1); } @@ -701,6 +1024,8 @@ RemoveDevice(DeviceIntPtr dev) int NumMotionEvents(void) { + /* only called to fill data in initial connection reply. + * VCP is ok here, it is the only fixed device we have. */ return inputInfo.pointer->valuator->numMotionEvents; } @@ -776,10 +1101,9 @@ SetKeySymsMap(KeySymsPtr dst, KeySymsPtr src) KeySym *map; int bytes = sizeof(KeySym) * src->mapWidth * (dst->maxKeyCode - dst->minKeyCode + 1); - map = (KeySym *)xalloc(bytes); + map = (KeySym *)xcalloc(1, bytes); if (!map) return FALSE; - bzero((char *)map, bytes); if (dst->map) { for (i = 0; i <= dst->maxKeyCode-dst->minKeyCode; i++) @@ -790,6 +1114,16 @@ SetKeySymsMap(KeySymsPtr dst, KeySymsPtr src) } dst->mapWidth = src->mapWidth; dst->map = map; + } else if (!dst->map) + { + KeySym *map; + int bytes = sizeof(KeySym) * src->mapWidth * + (dst->maxKeyCode - dst->minKeyCode + 1); + map = (KeySym *)xcalloc(1, bytes); + if (!map) + return FALSE; + dst->map = map; + dst->mapWidth = src->mapWidth; } memmove((char *)&dst->map[rowDif * dst->mapWidth], (char *)src->map, @@ -819,10 +1153,9 @@ InitModMap(KeyClassPtr keyc) } } } - keyc->modifierKeyMap = (KeyCode *)xalloc(8*keyc->maxKeysPerModifier); + keyc->modifierKeyMap = xcalloc(8, keyc->maxKeysPerModifier); if (!keyc->modifierKeyMap && keyc->maxKeysPerModifier) return (FALSE); - bzero((char *)keyc->modifierKeyMap, 8*(int)keyc->maxKeysPerModifier); for (i = 0; i < 8; i++) keysPerModifier[i] = 0; for (i = 8; i < MAP_LENGTH; i++) @@ -843,27 +1176,15 @@ InitModMap(KeyClassPtr keyc) _X_EXPORT Bool InitKeyClassDeviceStruct(DeviceIntPtr dev, KeySymsPtr pKeySyms, CARD8 pModifiers[]) { - int i; KeyClassPtr keyc; - - keyc = (KeyClassPtr)xalloc(sizeof(KeyClassRec)); + + keyc = xcalloc(1, sizeof(KeyClassRec)); if (!keyc) return FALSE; - keyc->curKeySyms.map = (KeySym *)NULL; - keyc->curKeySyms.mapWidth = 0; keyc->curKeySyms.minKeyCode = pKeySyms->minKeyCode; keyc->curKeySyms.maxKeyCode = pKeySyms->maxKeyCode; - keyc->modifierKeyMap = (KeyCode *)NULL; - keyc->state = 0; - keyc->prev_state = 0; if (pModifiers) memmove((char *)keyc->modifierMap, (char *)pModifiers, MAP_LENGTH); - else - bzero((char *)keyc->modifierMap, MAP_LENGTH); - bzero((char *)keyc->down, DOWN_LENGTH); - bzero((char *)keyc->postdown, DOWN_LENGTH); - for (i = 0; i < 8; i++) - keyc->modifierKeyCount[i] = 0; if (!SetKeySymsMap(&keyc->curKeySyms, pKeySyms) || !InitModMap(keyc)) { xfree(keyc->curKeySyms.map); @@ -880,32 +1201,24 @@ InitKeyClassDeviceStruct(DeviceIntPtr dev, KeySymsPtr pKeySyms, CARD8 pModifiers } _X_EXPORT Bool -InitButtonClassDeviceStruct(DeviceIntPtr dev, int numButtons, +InitButtonClassDeviceStruct(DeviceIntPtr dev, int numButtons, CARD8 *map) { ButtonClassPtr butc; int i; - butc = (ButtonClassPtr)xalloc(sizeof(ButtonClassRec)); + butc = xcalloc(1, sizeof(ButtonClassRec)); if (!butc) return FALSE; butc->numButtons = numButtons; for (i = 1; i <= numButtons; i++) butc->map[i] = map[i]; - butc->buttonsDown = 0; - butc->state = 0; - butc->motionMask = 0; - bzero((char *)butc->down, DOWN_LENGTH); -#ifdef XKB - butc->xkb_acts= NULL; -#endif dev->button = butc; return TRUE; } _X_EXPORT Bool -InitValuatorClassDeviceStruct(DeviceIntPtr dev, int numAxes, - ValuatorMotionProcPtr motionProc, +InitValuatorClassDeviceStruct(DeviceIntPtr dev, int numAxes, int numMotionEvents, int mode) { int i; @@ -914,7 +1227,7 @@ InitValuatorClassDeviceStruct(DeviceIntPtr dev, int numAxes, if (!dev) return FALSE; - valc = (ValuatorClassPtr)xalloc(sizeof(ValuatorClassRec) + + valc = (ValuatorClassPtr)xcalloc(1, sizeof(ValuatorClassRec) + numAxes * sizeof(AxisInfo) + numAxes * sizeof(unsigned int)); if (!valc) @@ -923,7 +1236,6 @@ InitValuatorClassDeviceStruct(DeviceIntPtr dev, int numAxes, valc->motion = NULL; valc->first_motion = 0; valc->last_motion = 0; - valc->GetMotionProc = motionProc; valc->numMotionEvents = numMotionEvents; valc->motionHintWindow = NullWindow; @@ -931,20 +1243,82 @@ InitValuatorClassDeviceStruct(DeviceIntPtr dev, int numAxes, valc->mode = mode; valc->axes = (AxisInfoPtr)(valc + 1); valc->axisVal = (int *)(valc->axes + numAxes); - valc->lastx = 0; - valc->lasty = 0; - valc->dxremaind = 0; - valc->dyremaind = 0; dev->valuator = valc; - /* biggest hack ever. */ - if (motionProc == GetMotionHistory) - AllocateMotionHistory(dev); + AllocateMotionHistory(dev); for (i=0; i<numAxes; i++) { - InitValuatorAxisStruct(dev, i, 0, -1, 0, 0, 0); + InitValuatorAxisStruct(dev, i, NO_AXIS_LIMITS, NO_AXIS_LIMITS, + 0, 0, 0); valc->axisVal[i]=0; } + + dev->last.numValuators = numAxes; + if(dev->isMaster) /* master devs do not accelerate */ + InitPointerAccelerationScheme(dev, PtrAccelNoOp); + else + InitPointerAccelerationScheme(dev, PtrAccelDefault); + return TRUE; +} + +/* global list of acceleration schemes */ +ValuatorAccelerationRec pointerAccelerationScheme[] = { + {PtrAccelNoOp, NULL, NULL, NULL}, + {PtrAccelPredictable, acceleratePointerPredictable, NULL, AccelerationDefaultCleanup}, + {PtrAccelLightweight, acceleratePointerLightweight, NULL, NULL}, + {-1, NULL, NULL, NULL} /* terminator */ +}; + +/** + * install an acceleration scheme. returns TRUE on success, and should not + * change anything if unsuccessful. + */ +_X_EXPORT Bool +InitPointerAccelerationScheme(DeviceIntPtr dev, + int scheme) +{ + int x, i = -1; + void* data = NULL; + ValuatorClassPtr val; + + val = dev->valuator; + + if(!val) + return FALSE; + + if(dev->isMaster && (scheme != PtrAccelNoOp)) + scheme = PtrAccelNoOp; /* no accel for master devices */ + + for(x = 0; pointerAccelerationScheme[x].number >= 0; x++) { + if(pointerAccelerationScheme[x].number == scheme){ + i = x; + break; + } + } + + if(-1 == i) + return FALSE; + + + /* init scheme-specific data */ + switch(scheme){ + case PtrAccelPredictable: + { + DeviceVelocityPtr s; + s = (DeviceVelocityPtr)xalloc(sizeof(DeviceVelocityRec)); + if(!s) + return FALSE; + InitVelocityData(s); + data = s; + break; + } + default: + break; + } + + val->accelScheme = pointerAccelerationScheme[i]; + val->accelScheme.accelData = data; + return TRUE; } @@ -958,10 +1332,10 @@ InitAbsoluteClassDeviceStruct(DeviceIntPtr dev) return FALSE; /* we don't do anything sensible with these, but should */ - abs->min_x = -1; - abs->min_y = -1; - abs->max_x = -1; - abs->max_y = -1; + abs->min_x = NO_AXIS_LIMITS; + abs->min_y = NO_AXIS_LIMITS; + abs->max_x = NO_AXIS_LIMITS; + abs->max_y = NO_AXIS_LIMITS; abs->flip_x = 0; abs->flip_y = 0; abs->rotation = 0; @@ -969,8 +1343,8 @@ InitAbsoluteClassDeviceStruct(DeviceIntPtr dev) abs->offset_x = 0; abs->offset_y = 0; - abs->width = -1; - abs->height = -1; + abs->width = NO_AXIS_LIMITS; + abs->height = NO_AXIS_LIMITS; abs->following = 0; abs->screen = 0; @@ -998,7 +1372,7 @@ InitFocusClassDeviceStruct(DeviceIntPtr dev) } _X_EXPORT Bool -InitKbdFeedbackClassDeviceStruct(DeviceIntPtr dev, BellProcPtr bellProc, +InitKbdFeedbackClassDeviceStruct(DeviceIntPtr dev, BellProcPtr bellProc, KbdCtrlProcPtr controlProc) { KbdFeedbackPtr feedc; @@ -1062,7 +1436,7 @@ static IntegerCtrl defaultIntegerControl = { _X_EXPORT Bool InitStringFeedbackClassDeviceStruct ( - DeviceIntPtr dev, StringCtrlProcPtr controlProc, + DeviceIntPtr dev, StringCtrlProcPtr controlProc, int max_symbols, int num_symbols_supported, KeySym *symbols) { int i; @@ -1075,9 +1449,9 @@ InitStringFeedbackClassDeviceStruct ( feedc->ctrl.num_symbols_supported = num_symbols_supported; feedc->ctrl.num_symbols_displayed = 0; feedc->ctrl.max_symbols = max_symbols; - feedc->ctrl.symbols_supported = (KeySym *) + feedc->ctrl.symbols_supported = (KeySym *) xalloc (sizeof (KeySym) * num_symbols_supported); - feedc->ctrl.symbols_displayed = (KeySym *) + feedc->ctrl.symbols_displayed = (KeySym *) xalloc (sizeof (KeySym) * max_symbols); if (!feedc->ctrl.symbols_supported || !feedc->ctrl.symbols_displayed) { @@ -1101,7 +1475,7 @@ InitStringFeedbackClassDeviceStruct ( } _X_EXPORT Bool -InitBellFeedbackClassDeviceStruct (DeviceIntPtr dev, BellProcPtr bellProc, +InitBellFeedbackClassDeviceStruct (DeviceIntPtr dev, BellProcPtr bellProc, BellCtrlProcPtr controlProc) { BellFeedbackPtr feedc; @@ -1160,23 +1534,22 @@ InitIntegerFeedbackClassDeviceStruct (DeviceIntPtr dev, IntegerCtrlProcPtr contr } _X_EXPORT Bool -InitPointerDeviceStruct(DevicePtr device, CARD8 *map, int numButtons, - ValuatorMotionProcPtr motionProc, +InitPointerDeviceStruct(DevicePtr device, CARD8 *map, int numButtons, PtrCtrlProcPtr controlProc, int numMotionEvents, int numAxes) { DeviceIntPtr dev = (DeviceIntPtr)device; return(InitButtonClassDeviceStruct(dev, numButtons, map) && - InitValuatorClassDeviceStruct(dev, numAxes, motionProc, + InitValuatorClassDeviceStruct(dev, numAxes, numMotionEvents, 0) && InitPtrFeedbackClassDeviceStruct(dev, controlProc)); } _X_EXPORT Bool -InitKeyboardDeviceStruct(DevicePtr device, KeySymsPtr pKeySyms, - CARD8 pModifiers[], BellProcPtr bellProc, - KbdCtrlProcPtr controlProc) +InitKeyboardDeviceStruct(DevicePtr device, KeySymsPtr pKeySyms, + CARD8 pModifiers[], BellProcPtr bellProc, + KbdCtrlProcPtr controlProc) { DeviceIntPtr dev = (DeviceIntPtr)device; @@ -1186,8 +1559,8 @@ InitKeyboardDeviceStruct(DevicePtr device, KeySymsPtr pKeySyms, } _X_EXPORT void -SendMappingNotify(unsigned request, unsigned firstKeyCode, unsigned count, - ClientPtr client) +SendMappingNotify(DeviceIntPtr pDev, unsigned request, unsigned firstKeyCode, + unsigned count, ClientPtr client) { int i; xEvent event; @@ -1201,9 +1574,9 @@ SendMappingNotify(unsigned request, unsigned firstKeyCode, unsigned count, } #ifdef XKB if (!noXkbExtension && - ((request == MappingKeyboard) || (request == MappingModifier))) - XkbApplyMappingChange(inputInfo.keyboard, request, firstKeyCode, count, - client); + ((request == MappingKeyboard) || (request == MappingModifier))) { + XkbApplyMappingChange(pDev,request,firstKeyCode,count, client); + } #endif /* 0 is the server client */ @@ -1225,13 +1598,15 @@ SendMappingNotify(unsigned request, unsigned firstKeyCode, unsigned count, } /* - * n-squared algorithm. n < 255 and don't want to copy the whole thing and - * sort it to do the checking. How often is it called? Just being lazy? + * Check if the given buffer contains elements between low (inclusive) and + * high (inclusive) only. + * + * @return TRUE if the device map is invalid, FALSE otherwise. */ Bool BadDeviceMap(BYTE *buff, int length, unsigned low, unsigned high, XID *errval) { - int i, j; + int i; for (i = 0; i < length; i++) if (buff[i]) /* only check non-zero elements */ @@ -1241,12 +1616,6 @@ BadDeviceMap(BYTE *buff, int length, unsigned low, unsigned high, XID *errval) *errval = buff[i]; return TRUE; } - for (j = i + 1; j < length; j++) - if (buff[i] == buff[j]) - { - *errval = buff[i]; - return TRUE; - } } return FALSE; } @@ -1281,10 +1650,11 @@ DoSetModifierMapping(ClientPtr client, KeyCode *inputMap, int numKeyPerModifier, xSetModifierMappingReply *rep) { DeviceIntPtr pDev = NULL; + DeviceIntPtr cp = PickKeyboard(client); /* ClientPointer keyboard */ int rc, i = 0, inputMapLen = numKeyPerModifier * 8; for (pDev = inputInfo.devices; pDev; pDev = pDev->next) { - if ((pDev->coreEvents || pDev == inputInfo.keyboard) && pDev->key) { + if (pDev == cp || (!pDev->isMaster && (pDev->u.master == cp) && pDev->key)) { for (i = 0; i < inputMapLen; i++) { /* Check that all the new modifiers fall within the advertised * keycode range, and are okay with the DDX. */ @@ -1350,7 +1720,7 @@ DoSetModifierMapping(ClientPtr client, KeyCode *inputMap, return Success; } -int +int ProcSetModifierMapping(ClientPtr client) { xSetModifierMappingReply rep; @@ -1372,7 +1742,6 @@ ProcSetModifierMapping(ClientPtr client) if (rc != Success) return rc; - SendMappingNotify(MappingModifier, 0, 0, client); for (dev = inputInfo.devices; dev; dev = dev->next) if (dev->key && dev->coreEvents) SendDeviceMappingNotify(client, MappingModifier, 0, 0, dev); @@ -1384,12 +1753,12 @@ int ProcGetModifierMapping(ClientPtr client) { xGetModifierMappingReply rep; - KeyClassPtr keyc = inputInfo.keyboard->key; + DeviceIntPtr dev = PickKeyboard(client); + KeyClassPtr keyc = dev->key; int rc; REQUEST_SIZE_MATCH(xReq); - rc = XaceHook(XACE_DEVICE_ACCESS, client, inputInfo.keyboard, - DixGetAttrAccess); + rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixGetAttrAccess); if (rc != Success) return rc; @@ -1413,12 +1782,12 @@ ProcChangeKeyboardMapping(ClientPtr client) REQUEST(xChangeKeyboardMappingReq); unsigned len; KeySymsRec keysyms; - KeySymsPtr curKeySyms = &inputInfo.keyboard->key->curKeySyms; + KeySymsPtr curKeySyms = &PickKeyboard(client)->key->curKeySyms; DeviceIntPtr pDev = NULL; int rc; REQUEST_AT_LEAST_SIZE(xChangeKeyboardMappingReq); - len = client->req_len - (sizeof(xChangeKeyboardMappingReq) >> 2); + len = client->req_len - (sizeof(xChangeKeyboardMappingReq) >> 2); if (len != (stuff->keyCodes * stuff->keySymsPerKeyCode)) return BadLength; @@ -1451,8 +1820,6 @@ ProcChangeKeyboardMapping(ClientPtr client) if (!SetKeySymsMap(&pDev->key->curKeySyms, &keysyms)) return BadAlloc; - SendMappingNotify(MappingKeyboard, stuff->firstKeyCode, stuff->keyCodes, - client); for (pDev = inputInfo.devices; pDev; pDev = pDev->next) if (pDev->key && pDev->coreEvents) SendDeviceMappingNotify(client, MappingKeyboard, @@ -1466,36 +1833,23 @@ static int DoSetPointerMapping(ClientPtr client, DeviceIntPtr device, BYTE *map, int n) { int rc, i = 0; - DeviceIntPtr dev = NULL; if (!device || !device->button) return BadDevice; - for (dev = inputInfo.devices; dev; dev = dev->next) { - if ((dev->coreEvents || dev == inputInfo.pointer) && dev->button) { - rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixManageAccess); - if (rc != Success) - return rc; - } - } + rc = XaceHook(XACE_DEVICE_ACCESS, client, device, DixManageAccess); + if (rc != Success) + return rc; - for (dev = inputInfo.devices; dev; dev = dev->next) { - if ((dev->coreEvents || dev == inputInfo.pointer) && dev->button) { - for (i = 0; i < n; i++) { - if ((device->button->map[i + 1] != map[i]) && - BitIsOn(device->button->down, i + 1)) { - return MappingBusy; - } - } + for (i = 0; i < n; i++) { + if ((device->button->map[i + 1] != map[i]) && + BitIsOn(device->button->down, i + 1)) { + return MappingBusy; } } - for (dev = inputInfo.devices; dev; dev = dev->next) { - if ((dev->coreEvents || dev == inputInfo.pointer) && dev->button) { - for (i = 0; i < n; i++) - dev->button->map[i + 1] = map[i]; - } - } + for (i = 0; i < n; i++) + device->button->map[i + 1] = map[i]; return Success; } @@ -1505,6 +1859,8 @@ ProcSetPointerMapping(ClientPtr client) { BYTE *map; int ret; + int i, j; + DeviceIntPtr ptr = PickPointer(client); xSetPointerMappingReply rep; REQUEST(xSetPointerMappingReq); REQUEST_AT_LEAST_SIZE(xSetPointerMappingReq); @@ -1516,25 +1872,41 @@ ProcSetPointerMapping(ClientPtr client) rep.sequenceNumber = client->sequence; rep.success = MappingSuccess; map = (BYTE *)&stuff[1]; - + /* So we're bounded here by the number of core buttons. This check * probably wants disabling through XFixes. */ - if (stuff->nElts != inputInfo.pointer->button->numButtons) { + /* MPX: With ClientPointer, we can return the right number of buttons. + * Let's just hope nobody changed ClientPointer between GetPointerMapping + * and SetPointerMapping + */ + if (stuff->nElts != ptr->button->numButtons) { client->errorValue = stuff->nElts; return BadValue; } if (BadDeviceMap(&map[0], (int)stuff->nElts, 1, 255, &client->errorValue)) return BadValue; - ret = DoSetPointerMapping(client, inputInfo.pointer, map, stuff->nElts); + /* core protocol specs don't allow for duplicate mappings. */ + for (i = 0; i < stuff->nElts; i++) + { + for (j = i + 1; j < stuff->nElts; j++) + { + if (map[i] && map[i] == map[j]) + { + client->errorValue = map[i]; + return BadValue; + } + } + } + + ret = DoSetPointerMapping(client, ptr, map, stuff->nElts); if (ret != Success) { rep.success = ret; WriteReplyToClient(client, sizeof(xSetPointerMappingReply), &rep); return Success; } - /* FIXME: Send mapping notifies for all the extended devices as well. */ - SendMappingNotify(MappingPointer, 0, 0, client); + SendMappingNotify(ptr, MappingPointer, 0, 0, client); WriteReplyToClient(client, sizeof(xSetPointerMappingReply), &rep); return Success; } @@ -1543,13 +1915,13 @@ int ProcGetKeyboardMapping(ClientPtr client) { xGetKeyboardMappingReply rep; - KeySymsPtr curKeySyms = &inputInfo.keyboard->key->curKeySyms; + DeviceIntPtr kbd = PickKeyboard(client); + KeySymsPtr curKeySyms = &kbd->key->curKeySyms; int rc; REQUEST(xGetKeyboardMappingReq); REQUEST_SIZE_MATCH(xGetKeyboardMappingReq); - rc = XaceHook(XACE_DEVICE_ACCESS, client, inputInfo.keyboard, - DixGetAttrAccess); + rc = XaceHook(XACE_DEVICE_ACCESS, client, kbd, DixGetAttrAccess); if (rc != Success) return rc; @@ -1584,12 +1956,14 @@ int ProcGetPointerMapping(ClientPtr client) { xGetPointerMappingReply rep; - ButtonClassPtr butc = inputInfo.pointer->button; + /* Apps may get different values each time they call GetPointerMapping as + * the ClientPointer could change. */ + DeviceIntPtr ptr = PickPointer(client); + ButtonClassPtr butc = ptr->button; int rc; REQUEST_SIZE_MATCH(xReq); - rc = XaceHook(XACE_DEVICE_ACCESS, client, inputInfo.pointer, - DixGetAttrAccess); + rc = XaceHook(XACE_DEVICE_ACCESS, client, ptr, DixGetAttrAccess); if (rc != Success) return rc; @@ -1599,7 +1973,7 @@ ProcGetPointerMapping(ClientPtr client) rep.length = ((unsigned)rep.nElts + (4-1))/4; WriteReplyToClient(client, sizeof(xGetPointerMappingReply), &rep); (void)WriteToClient(client, (int)rep.nElts, (char *)&butc->map[1]); - return Success; + return Success; } void @@ -1639,7 +2013,7 @@ DoChangeKeyboardControl (ClientPtr client, DeviceIntPtr keybd, XID *vlist, index2 = (BITS32) lowbit (vmask); vmask &= ~index2; switch (index2) { - case KBKeyClickPercent: + case KBKeyClickPercent: t = (INT8)*vlist; vlist++; if (t == -1) { @@ -1728,8 +2102,8 @@ DoChangeKeyboardControl (ClientPtr client, DeviceIntPtr keybd, XID *vlist, case KBKey: key = (KeyCode)*vlist; vlist++; - if ((KeyCode)key < inputInfo.keyboard->key->curKeySyms.minKeyCode || - (KeyCode)key > inputInfo.keyboard->key->curKeySyms.maxKeyCode) { + if ((KeyCode)key < keybd->key->curKeySyms.minKeyCode || + (KeyCode)key > keybd->key->curKeySyms.maxKeyCode) { client->errorValue = key; return BadValue; } @@ -1789,7 +2163,7 @@ DoChangeKeyboardControl (ClientPtr client, DeviceIntPtr keybd, XID *vlist, return Success; #undef DO_ALL -} +} int ProcChangeKeyboardControl (ClientPtr client) @@ -1833,12 +2207,12 @@ int ProcGetKeyboardControl (ClientPtr client) { int rc, i; - KeybdCtrl *ctrl = &inputInfo.keyboard->kbdfeed->ctrl; + DeviceIntPtr kbd = PickKeyboard(client); + KeybdCtrl *ctrl = &kbd->kbdfeed->ctrl; xGetKeyboardControlReply rep; REQUEST_SIZE_MATCH(xReq); - rc = XaceHook(XACE_DEVICE_ACCESS, client, inputInfo.keyboard, - DixGetAttrAccess); + rc = XaceHook(XACE_DEVICE_ACCESS, client, kbd, DixGetAttrAccess); if (rc != Success) return rc; @@ -1855,21 +2229,26 @@ ProcGetKeyboardControl (ClientPtr client) rep.map[i] = ctrl->autoRepeats[i]; WriteReplyToClient(client, sizeof(xGetKeyboardControlReply), &rep); return Success; -} +} int ProcBell(ClientPtr client) { - DeviceIntPtr keybd = inputInfo.keyboard; + DeviceIntPtr keybd = PickKeyboard(client); int base = keybd->kbdfeed->ctrl.bell; int newpercent; int rc; REQUEST(xBellReq); REQUEST_SIZE_MATCH(xBellReq); + /* Seems like no keyboard actually has the BellProc set. Returning + * BadDevice (previous code) will make apps crash badly. The man pages + * doesn't say anything about a BadDevice being returned either. + * So just quietly do nothing and pretend everything has worked. + */ if (!keybd->kbdfeed->BellProc) - return BadDevice; - + return Success; + if (stuff->percent < -100 || stuff->percent > 100) { client->errorValue = stuff->percent; return BadValue; @@ -1879,7 +2258,7 @@ ProcBell(ClientPtr client) if (stuff->percent < 0) newpercent = base + newpercent; else - newpercent = base - newpercent + stuff->percent; + newpercent = base - newpercent + stuff->percent; for (keybd = inputInfo.devices; keybd; keybd = keybd->next) { if ((keybd->coreEvents || keybd == inputInfo.keyboard) && @@ -1900,20 +2279,20 @@ ProcBell(ClientPtr client) } return Success; -} +} int ProcChangePointerControl(ClientPtr client) { - DeviceIntPtr mouse = inputInfo.pointer; + DeviceIntPtr mouse = PickPointer(client); PtrCtrl ctrl; /* might get BadValue part way through */ int rc; REQUEST(xChangePointerControlReq); REQUEST_SIZE_MATCH(xChangePointerControlReq); - + if (!mouse->ptrfeed->CtrlProc) return BadDevice; - + ctrl = mouse->ptrfeed->ctrl; if ((stuff->doAccel != xTrue) && (stuff->doAccel != xFalse)) { client->errorValue = stuff->doAccel; @@ -1969,7 +2348,7 @@ ProcChangePointerControl(ClientPtr client) } for (mouse = inputInfo.devices; mouse; mouse = mouse->next) { - if ((mouse->coreEvents || mouse == inputInfo.pointer) && + if ((mouse->coreEvents || mouse == PickPointer(client)) && mouse->ptrfeed && mouse->ptrfeed->CtrlProc) { mouse->ptrfeed->ctrl = ctrl; (*mouse->ptrfeed->CtrlProc)(mouse, &mouse->ptrfeed->ctrl); @@ -1977,18 +2356,18 @@ ProcChangePointerControl(ClientPtr client) } return Success; -} +} int ProcGetPointerControl(ClientPtr client) { - PtrCtrl *ctrl = &inputInfo.pointer->ptrfeed->ctrl; + DeviceIntPtr ptr = PickPointer(client); + PtrCtrl *ctrl = &ptr->ptrfeed->ctrl; xGetPointerControlReply rep; int rc; REQUEST_SIZE_MATCH(xReq); - rc = XaceHook(XACE_DEVICE_ACCESS, client, inputInfo.pointer, - DixGetAttrAccess); + rc = XaceHook(XACE_DEVICE_ACCESS, client, ptr, DixGetAttrAccess); if (rc != Success) return rc; @@ -2005,7 +2384,7 @@ ProcGetPointerControl(ClientPtr client) void MaybeStopHint(DeviceIntPtr dev, ClientPtr client) { - GrabPtr grab = dev->grab; + GrabPtr grab = dev->deviceGrab.grab; if ((grab && SameClient(grab, client) && ((grab->eventMask & PointerMotionHintMask) || @@ -2026,7 +2405,7 @@ ProcGetMotionEvents(ClientPtr client) xGetMotionEventsReply rep; int i, count, xmin, xmax, ymin, ymax, rc; unsigned long nEvents; - DeviceIntPtr mouse = inputInfo.pointer; + DeviceIntPtr mouse = PickPointer(client); TimeStamp start, stop; REQUEST(xGetMotionEventsReq); REQUEST_SIZE_MATCH(xGetMotionEventsReq); @@ -2051,14 +2430,9 @@ ProcGetMotionEvents(ClientPtr client) { if (CompareTimeStamps(stop, currentTime) == LATER) stop = currentTime; - coords = (xTimecoord *)xalloc(mouse->valuator->numMotionEvents - * sizeof(xTimecoord)); - if (!coords) - return BadAlloc; - count = (*mouse->valuator->GetMotionProc) (mouse, coords, - start.milliseconds, - stop.milliseconds, - pWin->drawable.pScreen); + count = GetMotionHistory(mouse, &coords, start.milliseconds, + stop.milliseconds, pWin->drawable.pScreen, + TRUE); xmin = pWin->drawable.x - wBorderWidth (pWin); xmax = pWin->drawable.x + (int)pWin->drawable.width + wBorderWidth (pWin); @@ -2094,15 +2468,15 @@ ProcQueryKeymap(ClientPtr client) { xQueryKeymapReply rep; int rc, i; - CARD8 *down = inputInfo.keyboard->key->down; + DeviceIntPtr keybd = PickKeyboard(client); + CARD8 *down = keybd->key->down; REQUEST_SIZE_MATCH(xReq); rep.type = X_Reply; rep.sequenceNumber = client->sequence; rep.length = 2; - rc = XaceHook(XACE_DEVICE_ACCESS, client, inputInfo.keyboard, - DixReadAccess); + rc = XaceHook(XACE_DEVICE_ACCESS, client, keybd, DixReadAccess); if (rc != Success) return rc; @@ -2110,5 +2484,174 @@ ProcQueryKeymap(ClientPtr client) rep.map[i] = down[i]; WriteReplyToClient(client, sizeof(xQueryKeymapReply), &rep); + + return Success; +} + +/** + * 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. + * + * Master may be NULL to set the device floating. + * + * We don't allow multi-layer hierarchies right now. You can't attach a slave + * to another slave. + */ +int +AttachDevice(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr master) +{ + ScreenPtr screen; + DeviceIntPtr oldmaster; + if (!dev || dev->isMaster) + return BadDevice; + + if (master && !master->isMaster) /* can't attach to slaves */ + return BadDevice; + + /* set from floating to floating? */ + if (!dev->u.master && !master) + return Success; + + /* free the existing sprite. */ + if (!dev->u.master && dev->spriteInfo->paired == dev) + { + screen = miPointerGetScreen(dev); + screen->DeviceCursorCleanup(dev, screen); + xfree(dev->spriteInfo->sprite); + } + + oldmaster = dev->u.master; + dev->u.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, + * so we reset spriteOwner. + * Sprite has to be forced to NULL first, otherwise InitializeSprite won't + * alloc new memory but overwrite the previous one. + */ + if (!master) + { + WindowPtr currentRoot = dev->spriteInfo->sprite->spriteTrace[0]; + /* we need to init a fake sprite */ + screen = currentRoot->drawable.pScreen; + screen->DeviceCursorInitialize(dev, screen); + dev->spriteInfo->sprite = NULL; + InitializeSprite(dev, currentRoot); + dev->spriteInfo->spriteOwner = FALSE; + dev->spriteInfo->paired = dev; + + } else + { + dev->spriteInfo->sprite = master->spriteInfo->sprite; + dev->spriteInfo->paired = master; + dev->spriteInfo->spriteOwner = FALSE; + } + + /* If we were connected to master device before, this MD may need to + * change back to it's original classes. + */ + if (oldmaster) + { + DeviceIntPtr it; + for (it = inputInfo.devices; it; it = it->next) + if (!it->isMaster && it->u.master == oldmaster) + break; + } + + return Success; +} + +/** + * Return the device paired with the given device or NULL. + * Returns the device paired with the parent master if the given device is a + * slave device. + */ +_X_EXPORT DeviceIntPtr +GetPairedDevice(DeviceIntPtr dev) +{ + if (!dev->isMaster && dev->u.master) + dev = dev->u.master; + + return dev->spriteInfo->paired; +} + + +/** + * Create a new master device (== one pointer, one keyboard device). + * Only allocates the devices, you will need to call ActivateDevice() and + * EnableDevice() manually. + */ +int +AllocMasterDevice(ClientPtr client, char* name, DeviceIntPtr* ptr, DeviceIntPtr* keybd) +{ + DeviceIntPtr pointer; + DeviceIntPtr keyboard; + ClassesPtr classes; + *ptr = *keybd = NULL; + + pointer = AddInputDevice(client, CorePointerProc, TRUE); + if (!pointer) + return BadAlloc; + + pointer->name = xcalloc(strlen(name) + strlen(" pointer") + 1, sizeof(char)); + strcpy(pointer->name, name); + strcat(pointer->name, " pointer"); + +#ifdef XKB + pointer->public.processInputProc = ProcessOtherEvent; + pointer->public.realInputProc = ProcessOtherEvent; + if (!noXkbExtension) + XkbSetExtension(pointer, ProcessPointerEvent); +#else + pointer->public.processInputProc = ProcessPointerEvent; + pointer->public.realInputProc = ProcessPointerEvent; +#endif + pointer->deviceGrab.ActivateGrab = ActivatePointerGrab; + pointer->deviceGrab.DeactivateGrab = DeactivatePointerGrab; + pointer->coreEvents = TRUE; + pointer->spriteInfo->spriteOwner = TRUE; + + pointer->u.lastSlave = NULL; + pointer->isMaster = TRUE; + + keyboard = AddInputDevice(client, CoreKeyboardProc, TRUE); + if (!keyboard) + { + RemoveDevice(pointer); + return BadAlloc; + } + + keyboard->name = xcalloc(strlen(name) + strlen(" keyboard") + 1, sizeof(char)); + strcpy(keyboard->name, name); + strcat(keyboard->name, " keyboard"); + +#ifdef XKB + keyboard->public.processInputProc = ProcessOtherEvent; + keyboard->public.realInputProc = ProcessOtherEvent; + if (!noXkbExtension) + XkbSetExtension(keyboard, ProcessKeyboardEvent); +#else + keyboard->public.processInputProc = ProcessKeyboardEvent; + keyboard->public.realInputProc = ProcessKeyboardEvent; +#endif + keyboard->deviceGrab.ActivateGrab = ActivateKeyboardGrab; + keyboard->deviceGrab.DeactivateGrab = DeactivateKeyboardGrab; + keyboard->coreEvents = TRUE; + keyboard->spriteInfo->spriteOwner = FALSE; + + keyboard->u.lastSlave = NULL; + keyboard->isMaster = TRUE; + + + /* The ClassesRec stores the device classes currently not used. */ + classes = xcalloc(1, sizeof(ClassesRec)); + dixSetPrivate(&pointer->devPrivates, UnusedClassesPrivateKey, classes); + classes = xcalloc(1, sizeof(ClassesRec)); + dixSetPrivate(&keyboard->devPrivates, UnusedClassesPrivateKey, classes); + + *ptr = pointer; + *keybd = keyboard; + return Success; } diff --git a/xorg-server/dix/dispatch.c b/xorg-server/dix/dispatch.c index b91385596..66f8f79ff 100644 --- a/xorg-server/dix/dispatch.c +++ b/xorg-server/dix/dispatch.c @@ -136,9 +136,6 @@ int ProcInitialConnection(); #endif #include "privates.h" #include "xace.h" -#ifdef XAPPGROUP -#include "appgroup.h" -#endif #ifdef XKB #ifndef XKB_IN_SERVER #define XKB_IN_SERVER @@ -163,7 +160,6 @@ typedef const char *string; #define GETBIT(buf, i) (MASKWORD(buf, i) & BITMASK(i)) extern xConnSetupPrefix connSetupPrefix; -extern char *ConnectionInfo; static ClientPtr grabClient; #define GrabNone 0 @@ -201,7 +197,7 @@ XID clientErrorValue; /* XXX this is a kludge */ #define SAME_SCREENS(a, b) (\ (a.pScreen == b.pScreen)) -_X_EXPORT void +void SetInputCheck(HWEventQueuePtr c0, HWEventQueuePtr c1) { checkForInput[0] = c0; @@ -240,7 +236,6 @@ UpdateCurrentTimeIf(void) currentTime = systime; } -#ifdef SMART_SCHEDULE #undef SMART_DEBUG @@ -341,7 +336,6 @@ SmartScheduleClient (int *clientReady, int nready) } return best; } -#endif #define MAJOROP ((xReq *)client->requestBuffer)->reqType @@ -353,9 +347,7 @@ Dispatch(void) ClientPtr client; int nready; HWEventQueuePtr* icheck = checkForInput; -#ifdef SMART_SCHEDULE long start_tick; -#endif nextFreeClientID = 1; nClients = 0; @@ -374,13 +366,11 @@ Dispatch(void) nready = WaitForSomething(clientReady); -#ifdef SMART_SCHEDULE if (nready && !SmartScheduleDisable) { clientReady[0] = SmartScheduleClient (clientReady, nready); nready = 1; } -#endif /***************** * Handle events in round robin fashion, doing input between * each round @@ -402,19 +392,13 @@ Dispatch(void) } isItTimeToYield = FALSE; -#ifdef XPRINT - requestingClient = client; -#endif -#ifdef SMART_SCHEDULE start_tick = SmartScheduleTime; -#endif while (!isItTimeToYield) { if (*icheck[0] != *icheck[1]) ProcessInputEvents(); FlushIfCriticalOutputPending(); -#ifdef SMART_SCHEDULE if (!SmartScheduleDisable && (SmartScheduleTime - start_tick) >= SmartScheduleSlice) { @@ -423,7 +407,6 @@ Dispatch(void) client->smart_priority--; break; } -#endif /* now, finally, deal with client requests */ result = ReadRequestFromClient(client); @@ -471,14 +454,9 @@ Dispatch(void) } } FlushAllOutput(); -#ifdef SMART_SCHEDULE client = clients[clientReady[nready]]; if (client) client->smart_stop_tick = SmartScheduleTime; -#endif -#ifdef XPRINT - requestingClient = NULL; -#endif } dispatchException &= ~DE_PRIORITYCHANGE; } @@ -1053,9 +1031,7 @@ ProcTranslateCoords(ClientPtr client) pWin = pDst->firstChild; while (pWin) { -#ifdef SHAPE BoxRec box; -#endif if ((pWin->mapped) && (x >= pWin->drawable.x - wBorderWidth (pWin)) && (x < pWin->drawable.x + (int)pWin->drawable.width + @@ -1063,7 +1039,6 @@ ProcTranslateCoords(ClientPtr client) (y >= pWin->drawable.y - wBorderWidth (pWin)) && (y < pWin->drawable.y + (int)pWin->drawable.height + wBorderWidth (pWin)) -#ifdef SHAPE /* When a window is shaped, a further check * is made to see if the point is inside * borderSize @@ -1077,7 +1052,6 @@ ProcTranslateCoords(ClientPtr client) wInputShape(pWin), x - pWin->drawable.x, y - pWin->drawable.y, &box)) -#endif ) { rep.child = pWin->drawable.id; @@ -2901,18 +2875,16 @@ ProcCreateCursor (ClientPtr client) return (BadMatch); n = BitmapBytePad(width)*height; - srcbits = (unsigned char *)xalloc(n); + srcbits = xcalloc(1, n); if (!srcbits) return (BadAlloc); - mskbits = (unsigned char *)xalloc(n); + mskbits = xalloc(n); if (!mskbits) { xfree(srcbits); return (BadAlloc); } - /* zeroing the (pad) bits helps some ddx cursor handling */ - bzero((char *)srcbits, n); (* src->drawable.pScreen->GetImage)( (DrawablePtr)src, 0, 0, width, height, XYPixmap, 1, (pointer)srcbits); if ( msk == (PixmapPtr)NULL) @@ -3465,9 +3437,7 @@ CloseDownClient(ClientPtr client) if (client->index < nextFreeClientID) nextFreeClientID = client->index; clients[client->index] = NullClient; -#ifdef SMART_SCHEDULE SmartLastClient = NullClient; -#endif dixFreePrivates(client->devPrivates); xfree(client); @@ -3512,20 +3482,19 @@ void InitClient(ClientPtr client, int i, pointer ospriv) if (!noXkbExtension) { client->xkbClientFlags = 0; client->mapNotifyMask = 0; + client->newKeyboardNotifyMask = 0; + client->vMinor = client->vMajor = 0; QueryMinMaxKeyCodes(&client->minKC,&client->maxKC); } #endif client->replyBytesRemaining = 0; -#ifdef XAPPGROUP - client->appgroup = NULL; -#endif client->fontResFunc = NULL; -#ifdef SMART_SCHEDULE client->smart_priority = 0; client->smart_start_tick = SmartScheduleTime; client->smart_stop_tick = SmartScheduleTime; client->smart_check_tick = SmartScheduleTime; -#endif + + client->clientPtr = NULL; } /************************ @@ -3643,9 +3612,6 @@ SendConnSetup(ClientPtr client, char *reason) client->requestVector = client->swapped ? SwappedProcVector : ProcVector; client->sequence = 0; -#ifdef XAPPGROUP - XagConnectionInfo (client, &lconnSetupPrefix, &lConnectionInfo, &numScreens); -#endif ((xConnSetup *)lConnectionInfo)->ridBase = client->clientAsMask; ((xConnSetup *)lConnectionInfo)->ridMask = RESOURCE_ID_MASK; #ifdef MATCH_CLIENT_ENDIAN diff --git a/xorg-server/dix/dixfonts.c b/xorg-server/dix/dixfonts.c index 8ed494c09..02f9d6de8 100644 --- a/xorg-server/dix/dixfonts.c +++ b/xorg-server/dix/dixfonts.c @@ -87,7 +87,7 @@ extern FontPtr defaultFont; static FontPathElementPtr *font_path_elements = (FontPathElementPtr *) 0; static int num_fpes = 0; -_X_EXPORT FPEFunctions *fpe_functions = (FPEFunctions *) 0; +static FPEFunctions *fpe_functions = (FPEFunctions *) 0; static int num_fpe_types = 0; static unsigned char *font_path_string; @@ -97,9 +97,8 @@ static int size_slept_fpes = 0; static FontPathElementPtr *slept_fpes = (FontPathElementPtr *) 0; static FontPatternCachePtr patternCache; -_X_EXPORT int -FontToXError(err) - int err; +static int +FontToXError(int err) { switch (err) { case Successful: @@ -117,6 +116,16 @@ FontToXError(err) } } +static int +LoadGlyphs(ClientPtr client, FontPtr pfont, unsigned nchars, int item_size, + unsigned char *data) +{ + if (fpe_functions[pfont->fpe->type].load_glyphs) + return (*fpe_functions[pfont->fpe->type].load_glyphs) + (client, pfont, 0, nchars, item_size, data); + else + return Successful; +} /* * adding RT_FONT prevents conflict with default cursor font @@ -304,8 +313,14 @@ doOpenFont(ClientPtr client, OFclosurePtr c) c->fontname = newname; c->fnamelen = newlen; c->current_fpe = 0; - if (--aliascount <= 0) + if (--aliascount <= 0) { + /* We've tried resolving this alias 20 times, we're + * probably stuck in an infinite loop of aliases pointing + * to each other - time to take emergency exit! + */ + err = BadImplementation; break; + } continue; } if (err == BadFontName) { @@ -388,7 +403,7 @@ OpenFont(ClientPtr client, XID fid, Mask flags, unsigned lenfname, char *pfontna f = (char *)xalloc(lenfname + 1); memmove(f, pfontname, lenfname); f[lenfname] = '\0'; - ErrorF("OpenFont: fontname is \"%s\"\n", f); + ErrorF("[dix] OpenFont: fontname is \"%s\"\n", f); xfree(f); #endif if (!lenfname || lenfname > XLFDMAXFONTNAMELEN) @@ -466,7 +481,7 @@ OpenFont(ClientPtr client, XID fid, Mask flags, unsigned lenfname, char *pfontna * * \param value must conform to DeleteType */ -_X_EXPORT int +int CloseFont(pointer value, XID fid) { int nscr; @@ -1695,7 +1710,7 @@ SetFontPathElements(int npaths, unsigned char *paths, int *bad, Bool persist) if (len == 0) { if (persist) - ErrorF ("Removing empty element from the valid list of fontpaths\n"); + ErrorF("[dix] Removing empty element from the valid list of fontpaths\n"); err = BadValue; } else @@ -1747,7 +1762,7 @@ SetFontPathElements(int npaths, unsigned char *paths, int *bad, Bool persist) { if (persist) { - ErrorF("Could not init font path element %s, removing from list!\n", + ErrorF("[dix] Could not init font path element %s, removing from list!\n", fpe->name); } xfree (fpe->name); @@ -1875,16 +1890,6 @@ GetFontPath(ClientPtr client, int *count, int *length, unsigned char **result) return Success; } -_X_EXPORT int -LoadGlyphs(ClientPtr client, FontPtr pfont, unsigned nchars, int item_size, unsigned char *data) -{ - if (fpe_functions[pfont->fpe->type].load_glyphs) - return (*fpe_functions[pfont->fpe->type].load_glyphs) - (client, pfont, 0, nchars, item_size, data); - else - return Successful; -} - void DeleteClientFontStuff(ClientPtr client) { @@ -1904,16 +1909,9 @@ InitFonts (void) { patternCache = MakeFontPatternCache(); - if (screenInfo.numScreens > screenInfo.numVideoScreens) { - PrinterFontRegisterFpeFunctions(); - FontFileCheckRegisterFpeFunctions(); - check_fs_register_fpe_functions(); - } else - { - BuiltinRegisterFpeFunctions(); - FontFileRegisterFpeFunctions(); - fs_register_fpe_functions(); - } + BuiltinRegisterFpeFunctions(); + FontFileRegisterFpeFunctions(); + fs_register_fpe_functions(); } int @@ -1926,37 +1924,27 @@ GetDefaultPointSize () FontResolutionPtr GetClientResolutions (int *num) { -#ifdef XPRINT - if (requestingClient && requestingClient->fontResFunc != NULL && - !requestingClient->clientGone) - { - return (*requestingClient->fontResFunc)(requestingClient, num); - } - else -#endif - { - static struct _FontResolution res; - ScreenPtr pScreen; + static struct _FontResolution res; + ScreenPtr pScreen; - pScreen = screenInfo.screens[0]; - res.x_resolution = (pScreen->width * 25.4) / pScreen->mmWidth; - /* - * XXX - we'll want this as long as bitmap instances are prevalent - so that we can match them from scalable fonts - */ - if (res.x_resolution < 88) - res.x_resolution = 75; - else - res.x_resolution = 100; - res.y_resolution = (pScreen->height * 25.4) / pScreen->mmHeight; - if (res.y_resolution < 88) - res.y_resolution = 75; - else - res.y_resolution = 100; - res.point_size = 120; - *num = 1; - return &res; - } + pScreen = screenInfo.screens[0]; + res.x_resolution = (pScreen->width * 25.4) / pScreen->mmWidth; + /* + * XXX - we'll want this as long as bitmap instances are prevalent + so that we can match them from scalable fonts + */ + if (res.x_resolution < 88) + res.x_resolution = 75; + else + res.x_resolution = 100; + res.y_resolution = (pScreen->height * 25.4) / pScreen->mmHeight; + if (res.y_resolution < 88) + res.y_resolution = 75; + else + res.y_resolution = 100; + res.point_size = 120; + *num = 1; + return &res; } /* diff --git a/xorg-server/dix/dixutils.c b/xorg-server/dix/dixutils.c index aaf510623..340564ecd 100644 --- a/xorg-server/dix/dixutils.c +++ b/xorg-server/dix/dixutils.c @@ -270,14 +270,15 @@ dixLookupClient(ClientPtr *pClient, XID rid, ClientPtr client, Mask access) *pClient = clients[clientIndex]; return Success; bad: - client->errorValue = rid; + if(client) + client->errorValue = rid; *pClient = NULL; return rc; } int AlterSaveSetForClient(ClientPtr client, WindowPtr pWin, unsigned mode, - Bool toRoot, Bool remap) + Bool toRoot, Bool map) { int numnow; SaveSetElt *pTmp = NULL; @@ -303,7 +304,7 @@ AlterSaveSetForClient(ClientPtr client, WindowPtr pWin, unsigned mode, client->numSaved = numnow; SaveSetAssignWindow(client->saveSet[numnow - 1], pWin); SaveSetAssignToRoot(client->saveSet[numnow - 1], toRoot); - SaveSetAssignRemap(client->saveSet[numnow - 1], remap); + SaveSetAssignMap(client->saveSet[numnow - 1], map); return(Success); } else if ((mode == SetModeDelete) && (j < numnow)) diff --git a/xorg-server/dix/enterleave.c b/xorg-server/dix/enterleave.c new file mode 100644 index 000000000..8511dea6f --- /dev/null +++ b/xorg-server/dix/enterleave.c @@ -0,0 +1,1377 @@ +/* + * Copyright © 2008 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 + * + */ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include <X11/X.h> +#include "windowstr.h" +#include "scrnintstr.h" +#include "exglobals.h" +#include "enterleave.h" + +/* @file This file describes the model for sending core enter/leave events and + * focus in/out in the case of multiple pointers/keyboard foci + * Since we can't send more than one Enter or Leave/Focus in or out event per + * window to a core client without confusing it, this is a rather complicated + * approach. + * + * For a full description of the enter/leave model from a window's + * perspective, see + * http://lists.freedesktop.org/archives/xorg/2008-August/037606.html + * + * For a full description of the focus in/out model from a window's + * perspective, see + * http://lists.freedesktop.org/archives/xorg/2008-December/041740.html + * + * Additional notes: + * -) The core protocol spec says that "In a LeaveNotify event, if a child of the + * event window contains the initial position of the pointer, then the child + * component is set to that child. Otherwise, it is None. For an EnterNotify + * event, if a child of the event window contains the final pointer position, + * then the child component is set to that child. Otherwise, it is None." + * + * By inference, this means that only NotifyVirtual or NotifyNonlinearVirtual + * events may have a subwindow set to other than None. + * + * -) NotifyPointer events may be sent if the focus changes from window A to + * B. The assumption used in this model is that NotifyPointer events are only + * sent for the pointer paired with the keyboard that is involved in the focus + * events. For example, if F(W) changes because of keyboard 2, then + * NotifyPointer events are only sent for pointer 2. + */ + +static WindowPtr PointerWindows[MAXDEVICES]; +static WindowPtr FocusWindows[MAXDEVICES]; + +/** + * Return TRUE if @win has a pointer within its boundaries, excluding child + * window. + */ +static BOOL +HasPointer(WindowPtr win) +{ + int i; + + for (i = 0; i < MAXDEVICES; i++) + if (PointerWindows[i] == win) + return TRUE; + + return FALSE; +} + +/** + * Return TRUE if at least one keyboard focus is set to @win (excluding + * descendants of win). + */ +static BOOL +HasFocus(WindowPtr win) +{ + int i; + for (i = 0; i < MAXDEVICES; i++) + if (FocusWindows[i] == win) + return TRUE; + + return FALSE; +} + +/** + * Return the window the device @dev is currently on. + */ +static WindowPtr +PointerWin(DeviceIntPtr dev) +{ + return PointerWindows[dev->id]; +} + +/** + * Search for the first window below @win that has a pointer directly within + * it's boundaries (excluding boundaries of its own descendants). + * + * @return The child window that has the pointer within its boundaries or + * NULL. + */ +static WindowPtr +FirstPointerChild(WindowPtr win) +{ + int i; + for (i = 0; i < MAXDEVICES; i++) + { + if (PointerWindows[i] && IsParent(win, PointerWindows[i])) + return PointerWindows[i]; + } + + return NULL; +} + +/** + * Search for the first window below @win that has a focus directly within + * it's boundaries (excluding boundaries of its own descendants). + * + * @return The child window that has the pointer within its boundaries or + * NULL. + */ +static WindowPtr +FirstFocusChild(WindowPtr win) +{ + int i; + for (i = 0; i < MAXDEVICES; i++) + { + if (FocusWindows[i] && FocusWindows[i] != PointerRootWin && + IsParent(win, FocusWindows[i])) + return FocusWindows[i]; + } + + return NULL; +} + +/** + * Set the presence flag for @dev to mark that it is now in @win. + */ +void +EnterWindow(DeviceIntPtr dev, WindowPtr win, int mode) +{ + PointerWindows[dev->id] = win; +} + +/** + * Unset the presence flag for @dev to mark that it is not in @win anymore. + */ +static void +LeaveWindow(DeviceIntPtr dev, WindowPtr win, int mode) +{ + PointerWindows[dev->id] = NULL; +} + +/** + * Set the presence flag for @dev to mark that it is now in @win. + */ +void +SetFocusIn(DeviceIntPtr dev, WindowPtr win) +{ + FocusWindows[dev->id] = win; +} + +/** + * Unset the presence flag for @dev to mark that it is not in @win anymore. + */ +void +SetFocusOut(DeviceIntPtr dev, WindowPtr win) +{ + FocusWindows[dev->id] = NULL; +} + + + + +/** + * @return The window that is the first ancestor of both a and b. + */ +WindowPtr +CommonAncestor( + WindowPtr a, + WindowPtr b) +{ + for (b = b->parent; b; b = b->parent) + if (IsParent(b, a)) return b; + return NullWindow; +} + + +#if 0 +/** + * Send enter notifies to all windows between @ancestor and @child (excluding + * both). Events are sent running up the window hierarchy. This function + * recurses. + * If @core is TRUE, core events are sent, otherwise XI events will be sent. + */ +static void +DeviceEnterNotifies(DeviceIntPtr dev, + WindowPtr ancestor, + WindowPtr child, + int mode, + int detail) +{ + WindowPtr parent = child->parent; + + if (ancestor == parent) + return; + DeviceEnterNotifies(dev, ancestor, parent, mode, detail); + DeviceEnterLeaveEvent(dev, DeviceEnterNotify, mode, detail, parent, + child->drawable.id); +} +#endif + +/** + * Send enter notifies to all windows between @ancestor and @child (excluding + * both). Events are sent running down the window hierarchy. This function + * recurses. + */ +static void +CoreEnterNotifies(DeviceIntPtr dev, + WindowPtr ancestor, + WindowPtr child, + int mode, + int detail) +{ + WindowPtr parent = child->parent; + if (ancestor == parent) + return; + CoreEnterNotifies(dev, ancestor, parent, mode, detail); + + + /* Case 3: + A is above W, B is a descendant + + Classically: The move generates an EnterNotify on W with a detail of + Virtual or NonlinearVirtual + + MPX: + Case 3A: There is at least one other pointer on W itself + P(W) doesn't change, so the event should be suppressed + Case 3B: Otherwise, if there is at least one other pointer in a + descendant + P(W) stays on the same descendant, or changes to a different + descendant. The event should be suppressed. + Case 3C: Otherwise: + P(W) moves from a window above W to a descendant. The subwindow + field is set to the child containing the descendant. The detail + may need to be changed from Virtual to NonlinearVirtual depending + on the previous P(W). */ + + if (!HasPointer(parent) && !FirstPointerChild(parent)) + CoreEnterLeaveEvent(dev, EnterNotify, mode, detail, parent, + child->drawable.id); +} + +static void +CoreLeaveNotifies(DeviceIntPtr dev, + WindowPtr child, + WindowPtr ancestor, + int mode, + int detail) +{ + WindowPtr win; + + if (ancestor == child) + return; + + for (win = child->parent; win != ancestor; win = win->parent) + { + /*Case 7: + A is a descendant of W, B is above W + + Classically: A LeaveNotify is generated on W with a detail of Virtual + or NonlinearVirtual. + + MPX: + Case 3A: There is at least one other pointer on W itself + P(W) doesn't change, the event should be suppressed. + Case 3B: Otherwise, if there is at least one other pointer in a + descendant + P(W) stays on the same descendant, or changes to a different + descendant. The event should be suppressed. + Case 3C: Otherwise: + P(W) changes from the descendant of W to a window above W. + The detail may need to be changed from Virtual to NonlinearVirtual + or vice-versa depending on the new P(W).*/ + + /* If one window has a pointer or a child with a pointer, skip some + * work and exit. */ + if (HasPointer(win) || FirstPointerChild(win)) + return; + + CoreEnterLeaveEvent(dev, LeaveNotify, mode, detail, win, child->drawable.id); + + child = win; + } +} + +#if 0 +/** + * Send leave notifies to all windows between @child and @ancestor. + * Events are sent running up the hierarchy. + */ +static void +DeviceLeaveNotifies(DeviceIntPtr dev, + WindowPtr child, + WindowPtr ancestor, + int mode, + int detail) +{ + WindowPtr win; + + if (ancestor == child) + return; + for (win = child->parent; win != ancestor; win = win->parent) + { + DeviceEnterLeaveEvent(dev, DeviceLeaveNotify, mode, detail, win, + child->drawable.id); + child = win; + } +} +#endif + +/** + * Pointer @dev moves from @A to @B and @A neither a descendant of @B nor is + * @B a descendant of @A. + */ +static void +CoreEnterLeaveNonLinear(DeviceIntPtr dev, + WindowPtr A, + WindowPtr B, + int mode) +{ + WindowPtr X = CommonAncestor(A, B); + /* Case 4: + A is W, B is above W + + Classically: The move generates a LeaveNotify on W with a detail of + Ancestor or Nonlinear + + MPX: + Case 3A: There is at least one other pointer on W itself + P(W) doesn't change, the event should be suppressed + Case 3B: Otherwise, if there is at least one other pointer in a + descendant of W + P(W) changes from W to a descendant of W. The subwindow field + is set to the child containing the new P(W), the detail field + is set to Inferior + Case 3C: Otherwise: + The pointer window moves from W to a window above W. + The detail may need to be changed from Ancestor to Nonlinear or + vice versa depending on the the new P(W) + */ + + if (!HasPointer(A)) + { + WindowPtr child = FirstPointerChild(A); + if (child) + CoreEnterLeaveEvent(dev, LeaveNotify, mode, NotifyInferior, A, None); + else + CoreEnterLeaveEvent(dev, LeaveNotify, mode, NotifyNonlinear, A, None); + } + + + CoreLeaveNotifies(dev, A, X, mode, NotifyNonlinearVirtual); + + /* + Case 9: + A is a descendant of W, B is a descendant of W + + Classically: No events are generated on W + MPX: The pointer window stays the same or moves to a different + descendant of W. No events should be generated on W. + + + Therefore, no event to X. + */ + + CoreEnterNotifies(dev, X, B, mode, NotifyNonlinearVirtual); + + /* Case 2: + A is above W, B=W + + Classically: The move generates an EnterNotify on W with a detail of + Ancestor or Nonlinear + + MPX: + Case 2A: There is at least one other pointer on W itself + P(W) doesn't change, so the event should be suppressed + Case 2B: Otherwise, if there is at least one other pointer in a + descendant + P(W) moves from a descendant to W. detail is changed to Inferior, + subwindow is set to the child containing the previous P(W) + Case 2C: Otherwise: + P(W) changes from a window above W to W itself. + The detail may need to be changed from Ancestor to Nonlinear + or vice-versa depending on the previous P(W). */ + + if (!HasPointer(B)) + { + WindowPtr child = FirstPointerChild(B); + if (child) + CoreEnterLeaveEvent(dev, EnterNotify, mode, NotifyInferior, B, None); + else + CoreEnterLeaveEvent(dev, EnterNotify, mode, NotifyNonlinear, B, None); + } +} + +/** + * Pointer @dev moves from @A to @B and @A is a descendant of @B. + */ +static void +CoreEnterLeaveToAncestor(DeviceIntPtr dev, + WindowPtr A, + WindowPtr B, + int mode) +{ + /* Case 4: + A is W, B is above W + + Classically: The move generates a LeaveNotify on W with a detail of + Ancestor or Nonlinear + + MPX: + Case 3A: There is at least one other pointer on W itself + P(W) doesn't change, the event should be suppressed + Case 3B: Otherwise, if there is at least one other pointer in a + descendant of W + P(W) changes from W to a descendant of W. The subwindow field + is set to the child containing the new P(W), the detail field + is set to Inferior + Case 3C: Otherwise: + The pointer window moves from W to a window above W. + The detail may need to be changed from Ancestor to Nonlinear or + vice versa depending on the the new P(W) + */ + if (!HasPointer(A)) + { + WindowPtr child = FirstPointerChild(A); + if (child) + CoreEnterLeaveEvent(dev, LeaveNotify, mode, NotifyInferior, A, None); + else + CoreEnterLeaveEvent(dev, LeaveNotify, mode, NotifyAncestor, A, None); + } + + CoreLeaveNotifies(dev, A, B, mode, NotifyVirtual); + + /* Case 8: + A is a descendant of W, B is W + + Classically: A EnterNotify is generated on W with a detail of + NotifyInferior + + MPX: + Case 3A: There is at least one other pointer on W itself + P(W) doesn't change, the event should be suppressed + Case 3B: Otherwise: + P(W) changes from a descendant to W itself. The subwindow + field should be set to the child containing the old P(W) <<< WRONG */ + + if (!HasPointer(B)) + CoreEnterLeaveEvent(dev, EnterNotify, mode, NotifyInferior, B, None); + +} + + +/** + * Pointer @dev moves from @A to @B and @B is a descendant of @A. + */ +static void +CoreEnterLeaveToDescendant(DeviceIntPtr dev, + WindowPtr A, + WindowPtr B, + int mode) +{ + /* Case 6: + A is W, B is a descendant of W + + Classically: A LeaveNotify is generated on W with a detail of + NotifyInferior + + MPX: + Case 3A: There is at least one other pointer on W itself + P(W) doesn't change, the event should be suppressed + Case 3B: Otherwise: + P(W) changes from W to a descendant of W. The subwindow field + is set to the child containing the new P(W) <<< THIS IS WRONG */ + + if (!HasPointer(A)) + CoreEnterLeaveEvent(dev, LeaveNotify, mode, NotifyInferior, A, None); + + + CoreEnterNotifies(dev, A, B, mode, NotifyVirtual); + + /* Case 2: + A is above W, B=W + + Classically: The move generates an EnterNotify on W with a detail of + Ancestor or Nonlinear + + MPX: + Case 2A: There is at least one other pointer on W itself + P(W) doesn't change, so the event should be suppressed + Case 2B: Otherwise, if there is at least one other pointer in a + descendant + P(W) moves from a descendant to W. detail is changed to Inferior, + subwindow is set to the child containing the previous P(W) + Case 2C: Otherwise: + P(W) changes from a window above W to W itself. + The detail may need to be changed from Ancestor to Nonlinear + or vice-versa depending on the previous P(W). */ + + if (!HasPointer(B)) + { + WindowPtr child = FirstPointerChild(B); + if (child) + CoreEnterLeaveEvent(dev, EnterNotify, mode, NotifyInferior, B, None); + else + CoreEnterLeaveEvent(dev, EnterNotify, mode, NotifyAncestor, B, None); + } +} + +static void +CoreEnterLeaveEvents(DeviceIntPtr dev, + WindowPtr from, + WindowPtr to, + int mode) +{ + if (!dev->isMaster) + return; + + LeaveWindow(dev, from, mode); + + if (IsParent(from, to)) + CoreEnterLeaveToDescendant(dev, from, to, mode); + else if (IsParent(to, from)) + CoreEnterLeaveToAncestor(dev, from, to, mode); + else + CoreEnterLeaveNonLinear(dev, from, to, mode); + + EnterWindow(dev, to, mode); +} + +#if 0 +static void +DeviceEnterLeaveEvents(DeviceIntPtr dev, + WindowPtr from, + WindowPtr to, + int mode) +{ + if (IsParent(from, to)) + { + DeviceEnterLeaveEvent(dev, DeviceLeaveNotify, mode, NotifyInferior, from, None); + DeviceEnterNotifies(dev, from, to, mode, NotifyVirtual); + DeviceEnterLeaveEvent(dev, DeviceEnterNotify, mode, NotifyAncestor, to, None); + } + else if (IsParent(to, from)) + { + DeviceEnterLeaveEvent(dev, DeviceLeaveNotify, mode, NotifyAncestor, from, None); + DeviceLeaveNotifies(dev, from, to, mode, NotifyVirtual); + DeviceEnterLeaveEvent(dev, DeviceEnterNotify, mode, NotifyInferior, to, None); + } + else + { /* neither from nor to is descendent of the other */ + WindowPtr common = CommonAncestor(to, from); + /* common == NullWindow ==> different screens */ + DeviceEnterLeaveEvent(dev, DeviceLeaveNotify, mode, NotifyNonlinear, from, None); + DeviceLeaveNotifies(dev, from, common, mode, NotifyNonlinearVirtual); + DeviceEnterNotifies(dev, common, to, mode, NotifyNonlinearVirtual); + DeviceEnterLeaveEvent(dev, DeviceEnterNotify, mode, NotifyNonlinear, to, None); + } +} +#endif + +/** + * Figure out if enter/leave events are necessary and send them to the + * appropriate windows. + * + * @param fromWin Window the sprite moved out of. + * @param toWin Window the sprite moved into. + */ +void +DoEnterLeaveEvents(DeviceIntPtr pDev, + WindowPtr fromWin, + WindowPtr toWin, + int mode) +{ + if (!IsPointerDevice(pDev)) + return; + + if (fromWin == toWin) + return; + + CoreEnterLeaveEvents(pDev, fromWin, toWin, mode); +#if 0 + DeviceEnterLeaveEvents(pDev, fromWin, toWin, mode); +#endif +} + +/** + * Send focus out events to all windows between @child and @ancestor. + * Events are sent running up the hierarchy. + */ +static void +DeviceFocusOutEvents(DeviceIntPtr dev, + WindowPtr child, + WindowPtr ancestor, + int mode, + int detail) +{ + WindowPtr win; + + if (ancestor == child) + return; + for (win = child->parent; win != ancestor; win = win->parent) + DeviceFocusEvent(dev, DeviceFocusOut, mode, detail, win); +} + + +/** + * Send enter notifies to all windows between @ancestor and @child (excluding + * both). Events are sent running up the window hierarchy. This function + * recurses. + */ +static void +DeviceFocusInEvents(DeviceIntPtr dev, + WindowPtr ancestor, + WindowPtr child, + int mode, + int detail) +{ + WindowPtr parent = child->parent; + + if (ancestor == parent || !parent) + return; + DeviceFocusInEvents(dev, ancestor, parent, mode, detail); + DeviceFocusEvent(dev, DeviceFocusIn, mode, detail, parent); +} + +/** + * Send FocusIn events to all windows between @ancestor and @child (excluding + * both). Events are sent running down the window hierarchy. This function + * recurses. + */ +static void +CoreFocusInEvents(DeviceIntPtr dev, + WindowPtr ancestor, + WindowPtr child, + int mode, + int detail) +{ + WindowPtr parent = child->parent; + if (ancestor == parent) + return; + CoreFocusInEvents(dev, ancestor, parent, mode, detail); + + + /* Case 3: + A is above W, B is a descendant + + Classically: The move generates an FocusIn on W with a detail of + Virtual or NonlinearVirtual + + MPX: + Case 3A: There is at least one other focus on W itself + F(W) doesn't change, so the event should be suppressed + Case 3B: Otherwise, if there is at least one other focus in a + descendant + F(W) stays on the same descendant, or changes to a different + descendant. The event should be suppressed. + Case 3C: Otherwise: + F(W) moves from a window above W to a descendant. The detail may + need to be changed from Virtual to NonlinearVirtual depending + on the previous F(W). */ + + if (!HasFocus(parent) && !FirstFocusChild(parent)) + CoreFocusEvent(dev, FocusIn, mode, detail, parent); +} + +static void +CoreFocusOutEvents(DeviceIntPtr dev, + WindowPtr child, + WindowPtr ancestor, + int mode, + int detail) +{ + WindowPtr win; + + if (ancestor == child) + return; + + for (win = child->parent; win != ancestor; win = win->parent) + { + /*Case 7: + A is a descendant of W, B is above W + + Classically: A FocusOut is generated on W with a detail of Virtual + or NonlinearVirtual. + + MPX: + Case 3A: There is at least one other focus on W itself + F(W) doesn't change, the event should be suppressed. + Case 3B: Otherwise, if there is at least one other focus in a + descendant + F(W) stays on the same descendant, or changes to a different + descendant. The event should be suppressed. + Case 3C: Otherwise: + F(W) changes from the descendant of W to a window above W. + The detail may need to be changed from Virtual to NonlinearVirtual + or vice-versa depending on the new P(W).*/ + + /* If one window has a focus or a child with a focuspointer, skip some + * work and exit. */ + if (HasFocus(win) || FirstFocusChild(win)) + return; + + CoreFocusEvent(dev, FocusOut, mode, detail, win); + } +} + +/** + * Send FocusOut(NotifyPointer) events from the current pointer window (which + * is a descendant of @pwin_parent) up to (excluding) @pwin_parent. + * + * NotifyPointer events are only sent for the device paired with @dev. + * + * If the current pointer window is a descendat of @exclude or an ancestor of + * @exclude, no events are sent. Note: If the current pointer IS @exclude, + * events are sent! + */ +static void +CoreFocusOutNotifyPointerEvents(DeviceIntPtr dev, + WindowPtr pwin_parent, + WindowPtr exclude, + int mode, + int inclusive) +{ + WindowPtr P, stopAt; + + P = PointerWin(GetPairedDevice(dev)); + + if (!P) + return; + if (!IsParent(pwin_parent, P)) + if (!(pwin_parent == P && inclusive)) + return; + + if (exclude != None && exclude != PointerRootWin && + (IsParent(exclude, P) || IsParent(P, exclude))) + return; + + stopAt = (inclusive) ? pwin_parent->parent : pwin_parent; + + for (; P && P != stopAt; P = P->parent) + CoreFocusEvent(dev, FocusOut, mode, NotifyPointer, P); +} + +/** + * DO NOT CALL DIRECTLY. + * Recursion helper for CoreFocusInNotifyPointerEvents. + */ +static void +CoreFocusInRecurse(DeviceIntPtr dev, + WindowPtr win, + WindowPtr stopAt, + int mode, + int inclusive) +{ + if ((!inclusive && win == stopAt) || !win) + return; + + CoreFocusInRecurse(dev, win->parent, stopAt, mode, inclusive); + CoreFocusEvent(dev, FocusIn, mode, NotifyPointer, win); +} + + +/** + * Send FocusIn(NotifyPointer) events from @pwin_parent down to + * including the current pointer window (which is a descendant of @pwin_parent). + * If @inclusive is TRUE, @pwin_parent will receive the event too. + * + * @pwin is the pointer window. + * + * If the current pointer window is a child of @exclude, no events are sent. + */ +static void +CoreFocusInNotifyPointerEvents(DeviceIntPtr dev, + WindowPtr pwin_parent, + WindowPtr exclude, + int mode, + int inclusive) +{ + WindowPtr P; + + P = PointerWin(GetPairedDevice(dev)); + + if (!P || P == exclude || (pwin_parent != P && !IsParent(pwin_parent, P))) + return; + + if (exclude != None && (IsParent(exclude, P) || IsParent(P, exclude))) + return; + + CoreFocusInRecurse(dev, P, pwin_parent, mode, inclusive); +} + + +/** + * Focus of @dev moves from @A to @B and @A neither a descendant of @B nor is + * @B a descendant of @A. + */ +static void +CoreFocusNonLinear(DeviceIntPtr dev, + WindowPtr A, + WindowPtr B, + int mode) +{ + WindowPtr X = CommonAncestor(A, B); + + /* Case 4: + A is W, B is above W + + Classically: The change generates a FocusOut on W with a detail of + Ancestor or Nonlinear + + MPX: + Case 3A: There is at least one other focus on W itself + F(W) doesn't change, the event should be suppressed + Case 3B: Otherwise, if there is at least one other focus in a + descendant of W + F(W) changes from W to a descendant of W. The detail field + is set to Inferior + Case 3C: Otherwise: + The focus window moves from W to a window above W. + The detail may need to be changed from Ancestor to Nonlinear or + vice versa depending on the the new F(W) + */ + + if (!HasFocus(A)) + { + WindowPtr child = FirstFocusChild(A); + if (child) + { + /* NotifyPointer P-A unless P is child or below*/ + CoreFocusOutNotifyPointerEvents(dev, A, child, mode, FALSE); + CoreFocusEvent(dev, FocusOut, mode, NotifyInferior, A); + } else + { + /* NotifyPointer P-A */ + CoreFocusOutNotifyPointerEvents(dev, A, None, mode, FALSE); + CoreFocusEvent(dev, FocusOut, mode, NotifyNonlinear, A); + } + } + + + CoreFocusOutEvents(dev, A, X, mode, NotifyNonlinearVirtual); + + /* + Case 9: + A is a descendant of W, B is a descendant of W + + Classically: No events are generated on W + MPX: The focus window stays the same or moves to a different + descendant of W. No events should be generated on W. + + + Therefore, no event to X. + */ + + CoreFocusInEvents(dev, X, B, mode, NotifyNonlinearVirtual); + + /* Case 2: + A is above W, B=W + + Classically: The move generates an EnterNotify on W with a detail of + Ancestor or Nonlinear + + MPX: + Case 2A: There is at least one other focus on W itself + F(W) doesn't change, so the event should be suppressed + Case 2B: Otherwise, if there is at least one other focus in a + descendant + F(W) moves from a descendant to W. detail is changed to Inferior. + Case 2C: Otherwise: + F(W) changes from a window above W to W itself. + The detail may need to be changed from Ancestor to Nonlinear + or vice-versa depending on the previous F(W). */ + + if (!HasFocus(B)) + { + WindowPtr child = FirstFocusChild(B); + if (child) + { + CoreFocusEvent(dev, FocusIn, mode, NotifyInferior, B); + /* NotifyPointer B-P unless P is child or below. */ + CoreFocusInNotifyPointerEvents(dev, B, child, mode, FALSE); + } else { + CoreFocusEvent(dev, FocusIn, mode, NotifyNonlinear, B); + /* NotifyPointer B-P unless P is child or below. */ + CoreFocusInNotifyPointerEvents(dev, B, None, mode, FALSE); + } + } +} + + +/** + * Focus of @dev moves from @A to @B and @A is a descendant of @B. + */ +static void +CoreFocusToAncestor(DeviceIntPtr dev, + WindowPtr A, + WindowPtr B, + int mode) +{ + /* Case 4: + A is W, B is above W + + Classically: The change generates a FocusOut on W with a detail of + Ancestor or Nonlinear + + MPX: + Case 3A: There is at least one other focus on W itself + F(W) doesn't change, the event should be suppressed + Case 3B: Otherwise, if there is at least one other focus in a + descendant of W + F(W) changes from W to a descendant of W. The detail field + is set to Inferior + Case 3C: Otherwise: + The focus window moves from W to a window above W. + The detail may need to be changed from Ancestor to Nonlinear or + vice versa depending on the the new F(W) + */ + if (!HasFocus(A)) + { + WindowPtr child = FirstFocusChild(A); + if (child) + { + /* NotifyPointer P-A unless P is child or below*/ + CoreFocusOutNotifyPointerEvents(dev, A, child, mode, FALSE); + CoreFocusEvent(dev, FocusOut, mode, NotifyInferior, A); + } else + CoreFocusEvent(dev, FocusOut, mode, NotifyAncestor, A); + } + + CoreFocusOutEvents(dev, A, B, mode, NotifyVirtual); + + /* Case 8: + A is a descendant of W, B is W + + Classically: A FocusOut is generated on W with a detail of + NotifyInferior + + MPX: + Case 3A: There is at least one other focus on W itself + F(W) doesn't change, the event should be suppressed + Case 3B: Otherwise: + F(W) changes from a descendant to W itself. */ + + if (!HasFocus(B)) + { + CoreFocusEvent(dev, FocusIn, mode, NotifyInferior, B); + /* NotifyPointer B-P unless P is A or below. */ + CoreFocusInNotifyPointerEvents(dev, B, A, mode, FALSE); + } +} + +/** + * Focus of @dev moves from @A to @B and @B is a descendant of @A. + */ +static void +CoreFocusToDescendant(DeviceIntPtr dev, + WindowPtr A, + WindowPtr B, + int mode) +{ + /* Case 6: + A is W, B is a descendant of W + + Classically: A FocusOut is generated on W with a detail of + NotifyInferior + + MPX: + Case 3A: There is at least one other focus on W itself + F(W) doesn't change, the event should be suppressed + Case 3B: Otherwise: + F(W) changes from W to a descendant of W. */ + + if (!HasFocus(A)) + { + /* NotifyPointer P-A unless P is B or below*/ + CoreFocusOutNotifyPointerEvents(dev, A, B, mode, FALSE); + CoreFocusEvent(dev, FocusOut, mode, NotifyInferior, A); + } + + + CoreFocusInEvents(dev, A, B, mode, NotifyVirtual); + + /* Case 2: + A is above W, B=W + + Classically: The move generates an FocusIn on W with a detail of + Ancestor or Nonlinear + + MPX: + Case 2A: There is at least one other focus on W itself + F(W) doesn't change, so the event should be suppressed + Case 2B: Otherwise, if there is at least one other focus in a + descendant + F(W) moves from a descendant to W. detail is changed to Inferior. + Case 2C: Otherwise: + F(W) changes from a window above W to W itself. + The detail may need to be changed from Ancestor to Nonlinear + or vice-versa depending on the previous F(W). */ + + if (!HasFocus(B)) + { + WindowPtr child = FirstFocusChild(B); + if (child) + { + CoreFocusEvent(dev, FocusIn, mode, NotifyInferior, B); + /* NotifyPointer B-P unless P is child or below. */ + CoreFocusInNotifyPointerEvents(dev, B, child, mode, FALSE); + } else + CoreFocusEvent(dev, FocusIn, mode, NotifyAncestor, B); + } +} + +static BOOL +HasOtherPointer(WindowPtr win, DeviceIntPtr exclude) +{ + int i; + + for (i = 0; i < MAXDEVICES; i++) + if (i != exclude->id && PointerWindows[i] == win) + return TRUE; + + return FALSE; +} + +/** + * Focus moves from PointerRoot to None or from None to PointerRoot. + * Assumption: Neither A nor B are valid windows. + */ +static void +CoreFocusPointerRootNoneSwitch(DeviceIntPtr dev, + WindowPtr A, /* PointerRootWin or NoneWin */ + WindowPtr B, /* NoneWin or PointerRootWin */ + int mode) +{ + WindowPtr root; + int i; + int nscreens = screenInfo.numScreens; + +#ifdef PANORAMIX + if (!noPanoramiXExtension) + nscreens = 1; +#endif + + for (i = 0; i < nscreens; i++) + { + root = WindowTable[i]; + if (!HasOtherPointer(root, GetPairedDevice(dev)) && !FirstFocusChild(root)) + { + /* If pointer was on PointerRootWin and changes to NoneWin, and + * the pointer paired with @dev is below the current root window, + * do a NotifyPointer run. */ + if (dev->focus && dev->focus->win == PointerRootWin && + B != PointerRootWin) + { + WindowPtr ptrwin = PointerWin(GetPairedDevice(dev)); + if (ptrwin && IsParent(root, ptrwin)) + CoreFocusOutNotifyPointerEvents(dev, root, None, mode, TRUE); + } + CoreFocusEvent(dev, FocusOut, mode, ((int)A) ? NotifyPointerRoot : NotifyDetailNone, root); + CoreFocusEvent(dev, FocusIn, mode, ((int)B) ? NotifyPointerRoot : NotifyDetailNone, root); + if (B == PointerRootWin) + CoreFocusInNotifyPointerEvents(dev, root, None, mode, TRUE); + } + + } +} + +/** + * Focus moves from window @A to PointerRoot or to None. + * Assumption: @A is a valid window and not PointerRoot or None. + */ +static void +CoreFocusToPointerRootOrNone(DeviceIntPtr dev, + WindowPtr A, + WindowPtr B, /* PointerRootWin or NoneWin */ + int mode) +{ + WindowPtr root; + int i; + int nscreens = screenInfo.numScreens; + +#ifdef PANORAMIX + if (!noPanoramiXExtension) + nscreens = 1; +#endif + + if (!HasFocus(A)) + { + WindowPtr child = FirstFocusChild(A); + if (child) + { + /* NotifyPointer P-A unless P is B or below*/ + CoreFocusOutNotifyPointerEvents(dev, A, B, mode, FALSE); + CoreFocusEvent(dev, FocusOut, mode, NotifyInferior, A); + } else { + /* NotifyPointer P-A */ + CoreFocusOutNotifyPointerEvents(dev, A, None, mode, FALSE); + CoreFocusEvent(dev, FocusOut, mode, NotifyNonlinear, A); + } + } + + /* NullWindow means we include the root window */ + CoreFocusOutEvents(dev, A, NullWindow, mode, NotifyNonlinearVirtual); + + for (i = 0; i < nscreens; i++) + { + root = WindowTable[i]; + if (!HasFocus(root) && !FirstFocusChild(root)) + { + CoreFocusEvent(dev, FocusIn, mode, ((int)B) ? NotifyPointerRoot : NotifyDetailNone, root); + if (B == PointerRootWin) + CoreFocusInNotifyPointerEvents(dev, root, None, mode, TRUE); + } + } +} + +/** + * Focus moves from PointerRoot or None to a window @to. + * Assumption: @to is a valid window and not PointerRoot or None. + */ +static void +CoreFocusFromPointerRootOrNone(DeviceIntPtr dev, + WindowPtr A, /* PointerRootWin or NoneWin */ + WindowPtr B, + int mode) +{ + WindowPtr root; + int i; + int nscreens = screenInfo.numScreens; + +#ifdef PANORAMIX + if (!noPanoramiXExtension) + nscreens = 1; +#endif + + for (i = 0; i < nscreens; i++) + { + root = WindowTable[i]; + if (!HasFocus(root) && !FirstFocusChild(root)) + { + /* If pointer was on PointerRootWin and changes to NoneWin, and + * the pointer paired with @dev is below the current root window, + * do a NotifyPointer run. */ + if (dev->focus && dev->focus->win == PointerRootWin && + B != PointerRootWin) + { + WindowPtr ptrwin = PointerWin(GetPairedDevice(dev)); + if (ptrwin) + CoreFocusOutNotifyPointerEvents(dev, root, None, mode, TRUE); + } + CoreFocusEvent(dev, FocusOut, mode, ((int)A) ? NotifyPointerRoot : NotifyDetailNone, root); + } + } + + root = B; /* get B's root window */ + while(root->parent) + root = root->parent; + + if (B != root) + { + CoreFocusEvent(dev, FocusIn, mode, NotifyNonlinearVirtual, root); + CoreFocusInEvents(dev, root, B, mode, NotifyNonlinearVirtual); + } + + + if (!HasFocus(B)) + { + WindowPtr child = FirstFocusChild(B); + if (child) + { + CoreFocusEvent(dev, FocusIn, mode, NotifyInferior, B); + /* NotifyPointer B-P unless P is child or below. */ + CoreFocusInNotifyPointerEvents(dev, B, child, mode, FALSE); + } else { + CoreFocusEvent(dev, FocusIn, mode, NotifyNonlinear, B); + /* NotifyPointer B-P unless P is child or below. */ + CoreFocusInNotifyPointerEvents(dev, B, None, mode, FALSE); + } + } + +} + +static void +CoreFocusEvents(DeviceIntPtr dev, + WindowPtr from, + WindowPtr to, + int mode) +{ + if (!dev->isMaster) + return; + + SetFocusOut(dev, from); + + if (((to == NullWindow) || (to == PointerRootWin)) && + ((from == NullWindow) || (from == PointerRootWin))) + CoreFocusPointerRootNoneSwitch(dev, from, to, mode); + else if ((to == NullWindow) || (to == PointerRootWin)) + CoreFocusToPointerRootOrNone(dev, from, to, mode); + else if ((from == NullWindow) || (from == PointerRootWin)) + CoreFocusFromPointerRootOrNone(dev, from, to, mode); + else if (IsParent(from, to)) + CoreFocusToDescendant(dev, from, to, mode); + else if (IsParent(to, from)) + CoreFocusToAncestor(dev, from, to, mode); + else + CoreFocusNonLinear(dev, from, to, mode); + + SetFocusIn(dev, to); +} + +#define RootWindow(dev) dev->spriteInfo->sprite->spriteTrace[0] + +static void +DeviceFocusEvents(DeviceIntPtr dev, + WindowPtr from, + WindowPtr to, + int mode) +{ + int out, in; /* for holding details for to/from + PointerRoot/None */ + int i; + int nscreens = screenInfo.numScreens; + SpritePtr sprite = dev->spriteInfo->sprite; + + if (from == to) + return; + out = (from == NoneWin) ? NotifyDetailNone : NotifyPointerRoot; + in = (to == NoneWin) ? NotifyDetailNone : NotifyPointerRoot; + /* wrong values if neither, but then not referenced */ + +#ifdef PANORAMIX + if (!noPanoramiXExtension) + nscreens = 1; +#endif + + if ((to == NullWindow) || (to == PointerRootWin)) + { + if ((from == NullWindow) || (from == PointerRootWin)) + { + if (from == PointerRootWin) + DeviceFocusOutEvents(dev, sprite->win, RootWindow(dev), mode, + NotifyPointer); + /* Notify all the roots */ + for (i = 0; i < nscreens; i++) + DeviceFocusEvent(dev, FocusOut, mode, out, WindowTable[i]); + } + else + { + if (IsParent(from, sprite->win)) + DeviceFocusOutEvents(dev, sprite->win, from, mode, + NotifyPointer); + DeviceFocusEvent(dev, FocusOut, mode, NotifyNonlinear, from); + /* next call catches the root too, if the screen changed */ + DeviceFocusOutEvents(dev, from->parent, NullWindow, mode, + NotifyNonlinearVirtual); + } + /* Notify all the roots */ + for (i = 0; i < nscreens; i++) + DeviceFocusEvent(dev, FocusIn, mode, in, WindowTable[i]); + if (to == PointerRootWin) + DeviceFocusInEvents(dev, RootWindow(dev), sprite->win, mode, NotifyPointer); + } + else + { + if ((from == NullWindow) || (from == PointerRootWin)) + { + if (from == PointerRootWin) + DeviceFocusOutEvents(dev, sprite->win, RootWindow(dev), mode, + NotifyPointer); + for (i = 0; i < nscreens; i++) + DeviceFocusEvent(dev, FocusOut, mode, out, WindowTable[i]); + if (to->parent != NullWindow) + DeviceFocusInEvents(dev, RootWindow(dev), to, mode, NotifyNonlinearVirtual); + DeviceFocusEvent(dev, FocusIn, mode, NotifyNonlinear, to); + if (IsParent(to, sprite->win)) + DeviceFocusInEvents(dev, to, sprite->win, mode, NotifyPointer); + } + else + { + if (IsParent(to, from)) + { + DeviceFocusEvent(dev, FocusOut, mode, NotifyAncestor, from); + DeviceFocusOutEvents(dev, from->parent, to, mode, + NotifyVirtual); + DeviceFocusEvent(dev, FocusIn, mode, NotifyInferior, to); + if ((IsParent(to, sprite->win)) && + (sprite->win != from) && + (!IsParent(from, sprite->win)) && + (!IsParent(sprite->win, from))) + DeviceFocusInEvents(dev, to, sprite->win, mode, NotifyPointer); + } + else + if (IsParent(from, to)) + { + if ((IsParent(from, sprite->win)) && + (sprite->win != from) && + (!IsParent(to, sprite->win)) && + (!IsParent(sprite->win, to))) + DeviceFocusOutEvents(dev, sprite->win, from, mode, + NotifyPointer); + DeviceFocusEvent(dev, FocusOut, mode, NotifyInferior, from); + DeviceFocusInEvents(dev, from, to, mode, NotifyVirtual); + DeviceFocusEvent(dev, FocusIn, mode, NotifyAncestor, to); + } + else + { + /* neither from or to is child of other */ + WindowPtr common = CommonAncestor(to, from); + /* common == NullWindow ==> different screens */ + if (IsParent(from, sprite->win)) + DeviceFocusOutEvents(dev, sprite->win, from, mode, + NotifyPointer); + DeviceFocusEvent(dev, FocusOut, mode, NotifyNonlinear, from); + if (from->parent != NullWindow) + DeviceFocusOutEvents(dev, from->parent, common, mode, + NotifyNonlinearVirtual); + if (to->parent != NullWindow) + DeviceFocusInEvents(dev, common, to, mode, NotifyNonlinearVirtual); + DeviceFocusEvent(dev, FocusIn, mode, NotifyNonlinear, to); + if (IsParent(to, sprite->win)) + DeviceFocusInEvents(dev, to, sprite->win, mode, NotifyPointer); + } + } + } +} + +/** + * Figure out if focus events are necessary and send them to the + * appropriate windows. + * + * @param from Window the focus moved out of. + * @param to Window the focus moved into. + */ +void +DoFocusEvents(DeviceIntPtr pDev, + WindowPtr from, + WindowPtr to, + int mode) +{ + if (!IsKeyboardDevice(pDev)) + return; + + if (from == to) + return; + + CoreFocusEvents(pDev, from, to, mode); + DeviceFocusEvents(pDev, from, to, mode); +} diff --git a/xorg-server/dix/enterleave.h b/xorg-server/dix/enterleave.h new file mode 100644 index 000000000..edca38664 --- /dev/null +++ b/xorg-server/dix/enterleave.h @@ -0,0 +1,95 @@ +/* + * Copyright © 2008 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 + * + */ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#ifndef ENTERLEAVE_H +#define ENTERLEAVE_H + +extern void DoEnterLeaveEvents( + DeviceIntPtr pDev, + WindowPtr fromWin, + WindowPtr toWin, + int mode +); + +extern void DoFocusEvents( + DeviceIntPtr pDev, + WindowPtr fromWin, + WindowPtr toWin, + int mode +); + +extern void EnterLeaveEvent( + DeviceIntPtr mouse, + int type, + int mode, + int detail, + WindowPtr pWin, + Window child); + +extern WindowPtr CommonAncestor( + WindowPtr a, + WindowPtr b); + +extern void CoreEnterLeaveEvent(DeviceIntPtr mouse, + int type, + int mode, + int detail, + WindowPtr pWin, + Window child); +extern void DeviceEnterLeaveEvent(DeviceIntPtr mouse, + int type, + int mode, + int detail, + WindowPtr pWin, + Window child); + +extern void EnterWindow(DeviceIntPtr dev, + WindowPtr win, + int mode); + + +extern void CoreFocusEvent(DeviceIntPtr kbd, + int type, + int mode, + int detail, + WindowPtr pWin); + +extern void DeviceFocusEvent(DeviceIntPtr kbd, + int type, + int mode, + int detail, + WindowPtr pWin); + +extern void SetFocusIn(DeviceIntPtr kbd, + WindowPtr win); + +extern void SetFocusOut(DeviceIntPtr dev, + WindowPtr win); +#endif /* _ENTERLEAVE_H_ */ diff --git a/xorg-server/dix/events.c b/xorg-server/dix/events.c index 4a8e480c8..f15c46090 100644 --- a/xorg-server/dix/events.c +++ b/xorg-server/dix/events.c @@ -27,13 +27,13 @@ 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, +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 +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. +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 @@ -149,20 +149,8 @@ typedef const char *string; #include "Xserver-dtrace.h" #endif -#ifdef XEVIE -extern WindowPtr *WindowTable; -extern int xevieFlag; -extern int xevieClientIndex; -extern DeviceIntPtr xeviemouse; -extern DeviceIntPtr xeviekb; -extern Mask xevieMask; -extern Mask xevieFilters[128]; -extern int xevieEventSent; -extern int xevieKBEventSent; -int xeviegrabState = 0; -#endif - #include <X11/extensions/XIproto.h> +#include <X11/extensions/XI.h> #include "exglobals.h" #include "exevents.h" #include "exglobals.h" @@ -171,11 +159,16 @@ int xeviegrabState = 0; #include "dixevents.h" #include "dixgrabs.h" #include "dispatch.h" + +#include <X11/extensions/ge.h> +#include "geext.h" +#include "geint.h" + +#include "enterleave.h" + /** * Extension events type numbering starts at EXTENSION_EVENT_BASE. */ -#define EXTENSION_EVENT_BASE 64 - #define NoSuchEvent 0x80000000 /* so doesn't match NoEventMask */ #define StructureAndSubMask ( StructureNotifyMask | SubstructureNotifyMask ) #define AllButtonsMask ( \ @@ -196,6 +189,12 @@ int xeviegrabState = 0; ShiftMask | LockMask | ControlMask | Mod1Mask | Mod2Mask | \ Mod3Mask | Mod4Mask | Mod5Mask ) #define AllEventMasks (lastEventMask|(lastEventMask-1)) + +/** + * Used to indicate a implicit passive grab created by a ButtonPress event. + * See DeliverEventsToWindow(). + */ +#define ImplicitGrabMask (1 << 7) /* * The following relies on the fact that the Button<n>MotionMasks are equal * to the corresponding Button<n>Masks from the current modifier/button state. @@ -219,21 +218,21 @@ _X_EXPORT CallbackListPtr DeviceEventCallback; Mask DontPropagateMasks[DNPMCOUNT]; static int DontPropagateRefCnts[DNPMCOUNT]; + /** - * Main input device struct. - * inputInfo.pointer + * Main input device struct. + * inputInfo.pointer * is the core pointer. Referred to as "virtual core pointer", "VCP", * "core pointer" or inputInfo.pointer. There is exactly one core pointer, - * but multiple devices may send core events. If a device generates core - * events, those events will appear to originate from the core pointer. - * + * but multiple devices may send core events. The VCP is the first master + * pointer device and cannot be deleted. + * * inputInfo.keyboard * is the core keyboard ("virtual core keyboard", "VCK", "core keyboard"). * See inputInfo.pointer. - * + * * inputInfo.devices - * linked list containing all devices including VCK and VCP. The VCK will - * always be the first entry, the VCP the second entry in the device list. + * linked list containing all devices including VCP and VCK. * * inputInfo.off_devices * Devices that have not been initialized and are thus turned off. @@ -243,6 +242,24 @@ static int DontPropagateRefCnts[DNPMCOUNT]; */ _X_EXPORT InputInfo inputInfo; +/** + * syncEvents is the global structure for queued events. + * Devices can be frozen through GrabModeSync pointer grabs. If this is the + * case, events from these devices are added to "pending" instead of being + * processed normally. When the device is unfrozen, events in "pending" are + * replayed and processed as if they would come from the device directly. + * + * pending ... list of queued events + * pendtail ... last event in list + * replayDev ... The device to replay events for. Only set in AllowEvents, in + * which case it is set to the device specified in the request. + * replayWin ... the window the events are supposed to be replayed on. This + * window may be set to the grab's window (but only when + * Replay{Pointer|Keyboard} is given in the XAllowEvents + * request. + * playingEvents ... flag to indicate whether we're in the process of + * replaying events. Only set in ComputeFreezes(). + */ static struct { QdEventPtr pending, *pendtail; DeviceIntPtr replayDev; /* kludgy rock to put flag for */ @@ -251,55 +268,68 @@ static struct { TimeStamp time; } syncEvents; -/* - * The window trace information is used to avoid having to compute all the - * windows between the root and the current pointer window each time a button - * or key goes down. The grabs on each of those windows must be checked. - * - * @see XYToWindow() for a documentation on how the array is set up. +#define RootWindow(dev) dev->spriteInfo->sprite->spriteTrace[0] + +static xEvent* swapEvent = NULL; +static int swapEventLen = 0; + +/** + * Convert the given event type from an XI event to a core event. + * @return The matching core event type or 0 if there is none. */ -static WindowPtr *spriteTrace = (WindowPtr *)NULL; -#define ROOT spriteTrace[0] -static int spriteTraceSize = 0; -static int spriteTraceGood; +_X_EXPORT int +XItoCoreType(int xitype) +{ + int coretype = 0; + if (xitype == DeviceMotionNotify) + coretype = MotionNotify; + else if (xitype == DeviceButtonPress) + coretype = ButtonPress; + else if (xitype == DeviceButtonRelease) + coretype = ButtonRelease; + else if (xitype == DeviceKeyPress) + coretype = KeyPress; + else if (xitype == DeviceKeyRelease) + coretype = KeyRelease; + + return coretype; +} /** - * DIX sprite information. This is the sprite as seen from the DIX. It does - * not represent the actual sprite rendered to the screen. - * + * True if device owns a cursor, false if device shares a cursor sprite with + * another device. */ -static struct { - CursorPtr current; - BoxRec hotLimits; /* logical constraints of hot spot */ - Bool confined; /* confined to screen */ -#if defined(SHAPE) || defined(PANORAMIX) - RegionPtr hotShape; /* additional logical shape constraint */ -#endif - BoxRec physLimits; /* physical constraints of hot spot */ - WindowPtr win; /* window of logical position */ - HotSpot hot; /* logical pointer position */ - HotSpot hotPhys; /* physical pointer position */ -#ifdef PANORAMIX - ScreenPtr screen; /* all others are in Screen 0 coordinates */ - RegionRec Reg1; /* Region 1 for confining motion */ - RegionRec Reg2; /* Region 2 for confining virtual motion */ - WindowPtr windows[MAXSCREENS]; - WindowPtr confineWin; /* confine window */ -#endif -} sprite; /* info about the cursor sprite */ +_X_EXPORT Bool +DevHasCursor(DeviceIntPtr pDev) +{ + return pDev->spriteInfo->spriteOwner; +} -#ifdef XEVIE -_X_EXPORT WindowPtr xeviewin; -_X_EXPORT HotSpot xeviehot; -#endif +/* + * Return true if a device is a pointer, check is the same as used by XI to + * fill the 'use' field. + */ +_X_EXPORT Bool +IsPointerDevice(DeviceIntPtr dev) +{ + return (dev->valuator && dev->button); +} -static void DoEnterLeaveEvents( - WindowPtr fromWin, - WindowPtr toWin, - int mode -); +/* + * Return true if a device is a keyboard, check is the same as used by XI to + * fill the 'use' field. + * + * Some pointer devices have keys as well (e.g. multimedia keys). Try to not + * count them as keyboard devices. + */ +_X_EXPORT Bool +IsKeyboardDevice(DeviceIntPtr dev) +{ + return (dev->key && dev->kbdfeed) && !IsPointerDevice(dev); +} static WindowPtr XYToWindow( + DeviceIntPtr pDev, int x, int y ); @@ -311,12 +341,14 @@ extern int lastEvent; static Mask lastEventMask; -#ifdef XINPUT extern int DeviceMotionNotify; -#endif +/** + * Event filters. One set of filters for each device, but only the first layer + * is initialized. The rest is memcpy'd in InitEvents. + */ #define CantBeFiltered NoEventMask -static Mask filters[128] = +static Mask filters[MAXDEVICES][128] = { { NoSuchEvent, /* 0 */ NoSuchEvent, /* 1 */ @@ -353,48 +385,57 @@ static Mask filters[128] = ColormapChangeMask, /* ColormapNotify */ CantBeFiltered, /* ClientMessage */ CantBeFiltered /* MappingNotify */ -}; +}}; + + +/** + * same principle as filters, but one set of filters for each extension. + * The extension is responsible for setting the filters by calling + * SetGenericFilter(). + */ +static Mask* generic_filters[MAXEXTENSIONS]; static CARD8 criticalEvents[32] = { - 0x7c /* key and button events */ + 0x7c, 0x30, 0x40 /* key, button, expose, and configure events */ }; #ifdef PANORAMIX -static void ConfineToShape(RegionPtr shape, int *px, int *py); -static void PostNewCursor(void); +static void PostNewCursor(DeviceIntPtr pDev); -#define SyntheticMotion(x, y) \ - PostSyntheticMotion(x, y, noPanoramiXExtension ? 0 : \ - sprite.screen->myNum, \ +#define SyntheticMotion(dev, x, y) \ + PostSyntheticMotion(dev, x, y, noPanoramiXExtension ? 0 : \ + dev->spriteInfo->sprite->screen->myNum, \ syncEvents.playingEvents ? \ syncEvents.time.milliseconds : \ currentTime.milliseconds); static Bool XineramaSetCursorPosition( - int x, - int y, + DeviceIntPtr pDev, + int x, + int y, Bool generateEvent ){ ScreenPtr pScreen; BoxRec box; int i; + SpritePtr pSprite = pDev->spriteInfo->sprite; /* x,y are in Screen 0 coordinates. We need to decide what Screen - to send the message too and what the coordinates relative to + to send the message too and what the coordinates relative to that screen are. */ - pScreen = sprite.screen; + pScreen = pSprite->screen; x += panoramiXdataPtr[0].x; y += panoramiXdataPtr[0].y; if(!POINT_IN_REGION(pScreen, &XineramaScreenRegions[pScreen->myNum], - x, y, &box)) + x, y, &box)) { - FOR_NSCREENS(i) + FOR_NSCREENS(i) { - if(i == pScreen->myNum) + if(i == pScreen->myNum) continue; if(POINT_IN_REGION(pScreen, &XineramaScreenRegions[i], x, y, &box)) { @@ -404,21 +445,25 @@ XineramaSetCursorPosition( } } - sprite.screen = pScreen; - sprite.hotPhys.x = x - panoramiXdataPtr[0].x; - sprite.hotPhys.y = y - panoramiXdataPtr[0].y; + pSprite->screen = pScreen; + pSprite->hotPhys.x = x - panoramiXdataPtr[0].x; + pSprite->hotPhys.y = y - panoramiXdataPtr[0].y; x -= panoramiXdataPtr[pScreen->myNum].x; y -= panoramiXdataPtr[pScreen->myNum].y; - return (*pScreen->SetCursorPosition)(pScreen, x, y, generateEvent); + return (*pScreen->SetCursorPosition)(pDev, pScreen, x, y, generateEvent); } static void -XineramaConstrainCursor(void) +XineramaConstrainCursor(DeviceIntPtr pDev) { - ScreenPtr pScreen = sprite.screen; - BoxRec newBox = sprite.physLimits; + SpritePtr pSprite = pDev->spriteInfo->sprite; + ScreenPtr pScreen; + BoxRec newBox; + + pScreen = pSprite->screen; + newBox = pSprite->physLimits; /* Translate the constraining box to the screen the sprite is actually on */ @@ -427,56 +472,60 @@ XineramaConstrainCursor(void) newBox.y1 += panoramiXdataPtr[0].y - panoramiXdataPtr[pScreen->myNum].y; newBox.y2 += panoramiXdataPtr[0].y - panoramiXdataPtr[pScreen->myNum].y; - (* pScreen->ConstrainCursor)(pScreen, &newBox); + (* pScreen->ConstrainCursor)(pDev, pScreen, &newBox); } static void XineramaCheckPhysLimits( + DeviceIntPtr pDev, CursorPtr cursor, Bool generateEvents ){ HotSpot new; + SpritePtr pSprite = pDev->spriteInfo->sprite; if (!cursor) return; - - new = sprite.hotPhys; + + new = pSprite->hotPhys; /* I don't care what the DDX has to say about it */ - sprite.physLimits = sprite.hotLimits; + pSprite->physLimits = pSprite->hotLimits; /* constrain the pointer to those limits */ - if (new.x < sprite.physLimits.x1) - new.x = sprite.physLimits.x1; + if (new.x < pSprite->physLimits.x1) + new.x = pSprite->physLimits.x1; else - if (new.x >= sprite.physLimits.x2) - new.x = sprite.physLimits.x2 - 1; - if (new.y < sprite.physLimits.y1) - new.y = sprite.physLimits.y1; + if (new.x >= pSprite->physLimits.x2) + new.x = pSprite->physLimits.x2 - 1; + if (new.y < pSprite->physLimits.y1) + new.y = pSprite->physLimits.y1; else - if (new.y >= sprite.physLimits.y2) - new.y = sprite.physLimits.y2 - 1; + if (new.y >= pSprite->physLimits.y2) + new.y = pSprite->physLimits.y2 - 1; - if (sprite.hotShape) /* more work if the shape is a mess */ - ConfineToShape(sprite.hotShape, &new.x, &new.y); + if (pSprite->hotShape) /* more work if the shape is a mess */ + ConfineToShape(pDev, pSprite->hotShape, &new.x, &new.y); - if((new.x != sprite.hotPhys.x) || (new.y != sprite.hotPhys.y)) + if((new.x != pSprite->hotPhys.x) || (new.y != pSprite->hotPhys.y)) { - XineramaSetCursorPosition (new.x, new.y, generateEvents); + XineramaSetCursorPosition (pDev, new.x, new.y, generateEvents); if (!generateEvents) - SyntheticMotion(new.x, new.y); + SyntheticMotion(pDev, new.x, new.y); } /* Tell DDX what the limits are */ - XineramaConstrainCursor(); + XineramaConstrainCursor(pDev); } static Bool -XineramaSetWindowPntrs(WindowPtr pWin) +XineramaSetWindowPntrs(DeviceIntPtr pDev, WindowPtr pWin) { + SpritePtr pSprite = pDev->spriteInfo->sprite; + if(pWin == WindowTable[0]) { - memcpy(sprite.windows, WindowTable, + memcpy(pSprite->windows, WindowTable, PanoramiXNumScreens*sizeof(WindowPtr)); } else { PanoramiXRes *win; @@ -488,8 +537,8 @@ XineramaSetWindowPntrs(WindowPtr pWin) return FALSE; for(i = 0; i < PanoramiXNumScreens; i++) { - sprite.windows[i] = LookupIDByType(win->info[i].id, RT_WINDOW); - if(!sprite.windows[i]) /* window is being unmapped */ + pSprite->windows[i] = LookupIDByType(win->info[i].id, RT_WINDOW); + if(!pSprite->windows[i]) /* window is being unmapped */ return FALSE; } } @@ -498,16 +547,18 @@ XineramaSetWindowPntrs(WindowPtr pWin) static void XineramaCheckVirtualMotion( + DeviceIntPtr pDev, QdEventPtr qe, - WindowPtr pWin -){ + WindowPtr pWin) +{ + SpritePtr pSprite = pDev->spriteInfo->sprite; if (qe) { - sprite.hot.pScreen = qe->pScreen; /* should always be Screen 0 */ - sprite.hot.x = qe->event->u.keyButtonPointer.rootX; - sprite.hot.y = qe->event->u.keyButtonPointer.rootY; - pWin = inputInfo.pointer->grab ? inputInfo.pointer->grab->confineTo : + pSprite->hot.pScreen = qe->pScreen; /* should always be Screen 0 */ + pSprite->hot.x = qe->event->u.keyButtonPointer.rootX; + pSprite->hot.y = qe->event->u.keyButtonPointer.rootY; + pWin = pDev->deviceGrab.grab ? pDev->deviceGrab.grab->confineTo : NullWindow; } if (pWin) @@ -515,13 +566,13 @@ XineramaCheckVirtualMotion( int x, y, off_x, off_y, i; BoxRec lims; - if(!XineramaSetWindowPntrs(pWin)) + if(!XineramaSetWindowPntrs(pDev, pWin)) return; i = PanoramiXNumScreens - 1; - - REGION_COPY(sprite.screen, &sprite.Reg2, - &sprite.windows[i]->borderSize); + + REGION_COPY(pSprite->screen, &pSprite->Reg2, + &pSprite->windows[i]->borderSize); off_x = panoramiXdataPtr[i].x; off_y = panoramiXdataPtr[i].y; @@ -530,97 +581,110 @@ XineramaCheckVirtualMotion( y = off_y - panoramiXdataPtr[i].y; if(x || y) - REGION_TRANSLATE(sprite.screen, &sprite.Reg2, x, y); - - REGION_UNION(sprite.screen, &sprite.Reg2, &sprite.Reg2, - &sprite.windows[i]->borderSize); + REGION_TRANSLATE(pSprite->screen, &pSprite->Reg2, x, y); + + REGION_UNION(pSprite->screen, &pSprite->Reg2, &pSprite->Reg2, + &pSprite->windows[i]->borderSize); off_x = panoramiXdataPtr[i].x; off_y = panoramiXdataPtr[i].y; } - lims = *REGION_EXTENTS(sprite.screen, &sprite.Reg2); + lims = *REGION_EXTENTS(pSprite->screen, &pSprite->Reg2); - if (sprite.hot.x < lims.x1) - sprite.hot.x = lims.x1; - else if (sprite.hot.x >= lims.x2) - sprite.hot.x = lims.x2 - 1; - if (sprite.hot.y < lims.y1) - sprite.hot.y = lims.y1; - else if (sprite.hot.y >= lims.y2) - sprite.hot.y = lims.y2 - 1; + if (pSprite->hot.x < lims.x1) + pSprite->hot.x = lims.x1; + else if (pSprite->hot.x >= lims.x2) + pSprite->hot.x = lims.x2 - 1; + if (pSprite->hot.y < lims.y1) + pSprite->hot.y = lims.y1; + else if (pSprite->hot.y >= lims.y2) + pSprite->hot.y = lims.y2 - 1; - if (REGION_NUM_RECTS(&sprite.Reg2) > 1) - ConfineToShape(&sprite.Reg2, &sprite.hot.x, &sprite.hot.y); + if (REGION_NUM_RECTS(&pSprite->Reg2) > 1) + ConfineToShape(pDev, &pSprite->Reg2, + &pSprite->hot.x, &pSprite->hot.y); if (qe) { - qe->pScreen = sprite.hot.pScreen; - qe->event->u.keyButtonPointer.rootX = sprite.hot.x; - qe->event->u.keyButtonPointer.rootY = sprite.hot.y; + qe->pScreen = pSprite->hot.pScreen; + qe->event->u.keyButtonPointer.rootX = pSprite->hot.x; + qe->event->u.keyButtonPointer.rootY = pSprite->hot.y; } } -#ifdef XEVIE - xeviehot.x = sprite.hot.x; - xeviehot.y = sprite.hot.y; -#endif } static Bool -XineramaCheckMotion(xEvent *xE) +XineramaCheckMotion(xEvent *xE, DeviceIntPtr pDev) { - WindowPtr prevSpriteWin = sprite.win; + WindowPtr prevSpriteWin; + SpritePtr pSprite = pDev->spriteInfo->sprite; + + prevSpriteWin = pSprite->win; if (xE && !syncEvents.playingEvents) { + /* GetPointerEvents() guarantees that pointer events have the correct + rootX/Y set already. */ + switch(xE->u.u.type) + { + case ButtonPress: + case ButtonRelease: + case MotionNotify: + break; + default: + if (xE->u.u.type == DeviceButtonPress || + xE->u.u.type == DeviceButtonRelease || + xE->u.u.type == DeviceMotionNotify) + break; + /* all other events return FALSE */ + return FALSE; + } + /* Motion events entering DIX get translated to Screen 0 - coordinates. Replayed events have already been + coordinates. Replayed events have already been translated since they've entered DIX before */ - XE_KBPTR.rootX += panoramiXdataPtr[sprite.screen->myNum].x - + XE_KBPTR.rootX += panoramiXdataPtr[pSprite->screen->myNum].x - panoramiXdataPtr[0].x; - XE_KBPTR.rootY += panoramiXdataPtr[sprite.screen->myNum].y - + XE_KBPTR.rootY += panoramiXdataPtr[pSprite->screen->myNum].y - panoramiXdataPtr[0].y; - sprite.hot.x = XE_KBPTR.rootX; - sprite.hot.y = XE_KBPTR.rootY; - if (sprite.hot.x < sprite.physLimits.x1) - sprite.hot.x = sprite.physLimits.x1; - else if (sprite.hot.x >= sprite.physLimits.x2) - sprite.hot.x = sprite.physLimits.x2 - 1; - if (sprite.hot.y < sprite.physLimits.y1) - sprite.hot.y = sprite.physLimits.y1; - else if (sprite.hot.y >= sprite.physLimits.y2) - sprite.hot.y = sprite.physLimits.y2 - 1; - - if (sprite.hotShape) - ConfineToShape(sprite.hotShape, &sprite.hot.x, &sprite.hot.y); - - sprite.hotPhys = sprite.hot; - if ((sprite.hotPhys.x != XE_KBPTR.rootX) || - (sprite.hotPhys.y != XE_KBPTR.rootY)) + pSprite->hot.x = XE_KBPTR.rootX; + pSprite->hot.y = XE_KBPTR.rootY; + if (pSprite->hot.x < pSprite->physLimits.x1) + pSprite->hot.x = pSprite->physLimits.x1; + else if (pSprite->hot.x >= pSprite->physLimits.x2) + pSprite->hot.x = pSprite->physLimits.x2 - 1; + if (pSprite->hot.y < pSprite->physLimits.y1) + pSprite->hot.y = pSprite->physLimits.y1; + else if (pSprite->hot.y >= pSprite->physLimits.y2) + pSprite->hot.y = pSprite->physLimits.y2 - 1; + + if (pSprite->hotShape) + ConfineToShape(pDev, pSprite->hotShape, &pSprite->hot.x, &pSprite->hot.y); + + pSprite->hotPhys = pSprite->hot; + if ((pSprite->hotPhys.x != XE_KBPTR.rootX) || + (pSprite->hotPhys.y != XE_KBPTR.rootY)) { XineramaSetCursorPosition( - sprite.hotPhys.x, sprite.hotPhys.y, FALSE); + pDev, pSprite->hotPhys.x, pSprite->hotPhys.y, FALSE); } - XE_KBPTR.rootX = sprite.hot.x; - XE_KBPTR.rootY = sprite.hot.y; + XE_KBPTR.rootX = pSprite->hot.x; + XE_KBPTR.rootY = pSprite->hot.y; } -#ifdef XEVIE - xeviehot.x = sprite.hot.x; - xeviehot.y = sprite.hot.y; - xeviewin = -#endif - sprite.win = XYToWindow(sprite.hot.x, sprite.hot.y); + pSprite->win = XYToWindow(pDev, pSprite->hot.x, pSprite->hot.y); - if (sprite.win != prevSpriteWin) + if (pSprite->win != prevSpriteWin) { if (prevSpriteWin != NullWindow) { if (!xE) UpdateCurrentTimeIf(); - DoEnterLeaveEvents(prevSpriteWin, sprite.win, NotifyNormal); - } - PostNewCursor(); + DoEnterLeaveEvents(pDev, prevSpriteWin, pSprite->win, + NotifyNormal); + } + PostNewCursor(pDev); return FALSE; } return TRUE; @@ -628,25 +692,28 @@ XineramaCheckMotion(xEvent *xE) static void -XineramaConfineCursorToWindow(WindowPtr pWin, Bool generateEvents) +XineramaConfineCursorToWindow(DeviceIntPtr pDev, + WindowPtr pWin, + Bool generateEvents) { + SpritePtr pSprite = pDev->spriteInfo->sprite; if (syncEvents.playingEvents) { - XineramaCheckVirtualMotion((QdEventPtr)NULL, pWin); - SyntheticMotion(sprite.hot.x, sprite.hot.y); + XineramaCheckVirtualMotion(pDev, (QdEventPtr)NULL, pWin); + SyntheticMotion(pDev, pSprite->hot.x, pSprite->hot.y); } else { int x, y, off_x, off_y, i; - if(!XineramaSetWindowPntrs(pWin)) + if(!XineramaSetWindowPntrs(pDev, pWin)) return; i = PanoramiXNumScreens - 1; - - REGION_COPY(sprite.screen, &sprite.Reg1, - &sprite.windows[i]->borderSize); + + REGION_COPY(pSprite->screen, &pSprite->Reg1, + &pSprite->windows[i]->borderSize); off_x = panoramiXdataPtr[i].x; off_y = panoramiXdataPtr[i].y; @@ -655,48 +722,51 @@ XineramaConfineCursorToWindow(WindowPtr pWin, Bool generateEvents) y = off_y - panoramiXdataPtr[i].y; if(x || y) - REGION_TRANSLATE(sprite.screen, &sprite.Reg1, x, y); - - REGION_UNION(sprite.screen, &sprite.Reg1, &sprite.Reg1, - &sprite.windows[i]->borderSize); + REGION_TRANSLATE(pSprite->screen, &pSprite->Reg1, x, y); + + REGION_UNION(pSprite->screen, &pSprite->Reg1, &pSprite->Reg1, + &pSprite->windows[i]->borderSize); off_x = panoramiXdataPtr[i].x; off_y = panoramiXdataPtr[i].y; } - sprite.hotLimits = *REGION_EXTENTS(sprite.screen, &sprite.Reg1); + pSprite->hotLimits = *REGION_EXTENTS(pSprite->screen, &pSprite->Reg1); - if(REGION_NUM_RECTS(&sprite.Reg1) > 1) - sprite.hotShape = &sprite.Reg1; + if(REGION_NUM_RECTS(&pSprite->Reg1) > 1) + pSprite->hotShape = &pSprite->Reg1; else - sprite.hotShape = NullRegion; - - sprite.confined = FALSE; - sprite.confineWin = (pWin == WindowTable[0]) ? NullWindow : pWin; + pSprite->hotShape = NullRegion; + + pSprite->confined = FALSE; + pSprite->confineWin = (pWin == WindowTable[0]) ? NullWindow : pWin; - XineramaCheckPhysLimits(sprite.current, generateEvents); + XineramaCheckPhysLimits(pDev, pSprite->current, + generateEvents); } } static void -XineramaChangeToCursor(CursorPtr cursor) +XineramaChangeToCursor(DeviceIntPtr pDev, CursorPtr cursor) { - if (cursor != sprite.current) + SpritePtr pSprite = pDev->spriteInfo->sprite; + + if (cursor != pSprite->current) { - if ((sprite.current->bits->xhot != cursor->bits->xhot) || - (sprite.current->bits->yhot != cursor->bits->yhot)) - XineramaCheckPhysLimits(cursor, FALSE); - (*sprite.screen->DisplayCursor)(sprite.screen, cursor); - FreeCursor(sprite.current, (Cursor)0); - sprite.current = cursor; - sprite.current->refcnt++; + if ((pSprite->current->bits->xhot != cursor->bits->xhot) || + (pSprite->current->bits->yhot != cursor->bits->yhot)) + XineramaCheckPhysLimits(pDev, cursor, FALSE); + (*pSprite->screen->DisplayCursor)(pDev, pSprite->screen, cursor); + FreeCursor(pSprite->current, (Cursor)0); + pSprite->current = cursor; + pSprite->current->refcnt++; } } #else -#define SyntheticMotion(x, y) \ - PostSyntheticMotion(x, y, \ +#define SyntheticMotion(dev, x, y) \ + PostSyntheticMotion(dev, x, y, \ 0, \ syncEvents.playingEvents ? \ syncEvents.time.milliseconds : \ @@ -705,11 +775,19 @@ XineramaChangeToCursor(CursorPtr cursor) #endif /* PANORAMIX */ void -SetMaskForEvent(Mask mask, int event) +SetMaskForEvent(int deviceid, Mask mask, int event) { + int coretype; + if (deviceid < 0 || deviceid >= MAXDEVICES) + FatalError("SetMaskForEvent: bogus device id"); if ((event < LASTEvent) || (event >= 128)) FatalError("SetMaskForEvent: bogus event number"); - filters[event] = mask; + filters[deviceid][event] = mask; + + /* Need to change the mask for the core events too */ + coretype = XItoCoreType(event); + if (coretype) + filters[deviceid][coretype] = mask; } _X_EXPORT void @@ -720,17 +798,18 @@ SetCriticalEvent(int event) criticalEvents[event >> 3] |= 1 << (event & 7); } -#ifdef SHAPE -static void -ConfineToShape(RegionPtr shape, int *px, int *py) +void +ConfineToShape(DeviceIntPtr pDev, RegionPtr shape, int *px, int *py) { BoxRec box; int x = *px, y = *py; int incx = 1, incy = 1; + SpritePtr pSprite; - if (POINT_IN_REGION(sprite.hot.pScreen, shape, x, y, &box)) + pSprite = pDev->spriteInfo->sprite; + if (POINT_IN_REGION(pSprite->hot.pScreen, shape, x, y, &box)) return; - box = *REGION_EXTENTS(sprite.hot.pScreen, shape); + box = *REGION_EXTENTS(pSprite->hot.pScreen, shape); /* this is rather crude */ do { x += incx; @@ -752,145 +831,141 @@ ConfineToShape(RegionPtr shape, int *px, int *py) else if (y < box.y1) return; /* should never get here! */ } - } while (!POINT_IN_REGION(sprite.hot.pScreen, shape, x, y, &box)); + } while (!POINT_IN_REGION(pSprite->hot.pScreen, shape, x, y, &box)); *px = x; *py = y; } -#endif static void CheckPhysLimits( + DeviceIntPtr pDev, CursorPtr cursor, Bool generateEvents, Bool confineToScreen, ScreenPtr pScreen) { HotSpot new; + SpritePtr pSprite = pDev->spriteInfo->sprite; if (!cursor) return; - new = sprite.hotPhys; + new = pSprite->hotPhys; if (pScreen) new.pScreen = pScreen; else pScreen = new.pScreen; - (*pScreen->CursorLimits) (pScreen, cursor, &sprite.hotLimits, - &sprite.physLimits); - sprite.confined = confineToScreen; - (* pScreen->ConstrainCursor)(pScreen, &sprite.physLimits); - if (new.x < sprite.physLimits.x1) - new.x = sprite.physLimits.x1; + (*pScreen->CursorLimits) (pDev, pScreen, cursor, &pSprite->hotLimits, + &pSprite->physLimits); + pSprite->confined = confineToScreen; + (* pScreen->ConstrainCursor)(pDev, pScreen, &pSprite->physLimits); + if (new.x < pSprite->physLimits.x1) + new.x = pSprite->physLimits.x1; else - if (new.x >= sprite.physLimits.x2) - new.x = sprite.physLimits.x2 - 1; - if (new.y < sprite.physLimits.y1) - new.y = sprite.physLimits.y1; + if (new.x >= pSprite->physLimits.x2) + new.x = pSprite->physLimits.x2 - 1; + if (new.y < pSprite->physLimits.y1) + new.y = pSprite->physLimits.y1; else - if (new.y >= sprite.physLimits.y2) - new.y = sprite.physLimits.y2 - 1; -#ifdef SHAPE - if (sprite.hotShape) - ConfineToShape(sprite.hotShape, &new.x, &new.y); -#endif - if ((pScreen != sprite.hotPhys.pScreen) || - (new.x != sprite.hotPhys.x) || (new.y != sprite.hotPhys.y)) - { - if (pScreen != sprite.hotPhys.pScreen) - sprite.hotPhys = new; - (*pScreen->SetCursorPosition) (pScreen, new.x, new.y, generateEvents); - if (!generateEvents) - SyntheticMotion(new.x, new.y); + if (new.y >= pSprite->physLimits.y2) + new.y = pSprite->physLimits.y2 - 1; + if (pSprite->hotShape) + ConfineToShape(pDev, pSprite->hotShape, &new.x, &new.y); + if ((pScreen != pSprite->hotPhys.pScreen) || + (new.x != pSprite->hotPhys.x) || (new.y != pSprite->hotPhys.y)) + { + if (pScreen != pSprite->hotPhys.pScreen) + pSprite->hotPhys = new; + (*pScreen->SetCursorPosition) + (pDev, pScreen, new.x, new.y, generateEvents); + if (!generateEvents) + SyntheticMotion(pDev, new.x, new.y); } } static void CheckVirtualMotion( + DeviceIntPtr pDev, QdEventPtr qe, WindowPtr pWin) { + SpritePtr pSprite = pDev->spriteInfo->sprite; + #ifdef PANORAMIX if(!noPanoramiXExtension) { - XineramaCheckVirtualMotion(qe, pWin); + XineramaCheckVirtualMotion(pDev, qe, pWin); return; } #endif if (qe) { - sprite.hot.pScreen = qe->pScreen; - sprite.hot.x = qe->event->u.keyButtonPointer.rootX; - sprite.hot.y = qe->event->u.keyButtonPointer.rootY; - pWin = inputInfo.pointer->grab ? inputInfo.pointer->grab->confineTo : - NullWindow; + pSprite->hot.pScreen = qe->pScreen; + pSprite->hot.x = qe->event->u.keyButtonPointer.rootX; + pSprite->hot.y = qe->event->u.keyButtonPointer.rootY; + pWin = pDev->deviceGrab.grab ? pDev->deviceGrab.grab->confineTo : NullWindow; } if (pWin) { BoxRec lims; - if (sprite.hot.pScreen != pWin->drawable.pScreen) + if (pSprite->hot.pScreen != pWin->drawable.pScreen) { - sprite.hot.pScreen = pWin->drawable.pScreen; - sprite.hot.x = sprite.hot.y = 0; + pSprite->hot.pScreen = pWin->drawable.pScreen; + pSprite->hot.x = pSprite->hot.y = 0; } lims = *REGION_EXTENTS(pWin->drawable.pScreen, &pWin->borderSize); - if (sprite.hot.x < lims.x1) - sprite.hot.x = lims.x1; - else if (sprite.hot.x >= lims.x2) - sprite.hot.x = lims.x2 - 1; - if (sprite.hot.y < lims.y1) - sprite.hot.y = lims.y1; - else if (sprite.hot.y >= lims.y2) - sprite.hot.y = lims.y2 - 1; -#ifdef SHAPE + if (pSprite->hot.x < lims.x1) + pSprite->hot.x = lims.x1; + else if (pSprite->hot.x >= lims.x2) + pSprite->hot.x = lims.x2 - 1; + if (pSprite->hot.y < lims.y1) + pSprite->hot.y = lims.y1; + else if (pSprite->hot.y >= lims.y2) + pSprite->hot.y = lims.y2 - 1; if (wBoundingShape(pWin)) - ConfineToShape(&pWin->borderSize, &sprite.hot.x, &sprite.hot.y); -#endif + ConfineToShape(pDev, &pWin->borderSize, + &pSprite->hot.x, &pSprite->hot.y); if (qe) { - qe->pScreen = sprite.hot.pScreen; - qe->event->u.keyButtonPointer.rootX = sprite.hot.x; - qe->event->u.keyButtonPointer.rootY = sprite.hot.y; + qe->pScreen = pSprite->hot.pScreen; + qe->event->u.keyButtonPointer.rootX = pSprite->hot.x; + qe->event->u.keyButtonPointer.rootY = pSprite->hot.y; } } -#ifdef XEVIE - xeviehot.x = sprite.hot.x; - xeviehot.y = sprite.hot.y; -#endif - ROOT = WindowTable[sprite.hot.pScreen->myNum]; + RootWindow(pDev) = WindowTable[pSprite->hot.pScreen->myNum]; } static void -ConfineCursorToWindow(WindowPtr pWin, Bool generateEvents, Bool confineToScreen) +ConfineCursorToWindow(DeviceIntPtr pDev, WindowPtr pWin, Bool generateEvents, Bool confineToScreen) { ScreenPtr pScreen = pWin->drawable.pScreen; + SpritePtr pSprite = pDev->spriteInfo->sprite; #ifdef PANORAMIX if(!noPanoramiXExtension) { - XineramaConfineCursorToWindow(pWin, generateEvents); + XineramaConfineCursorToWindow(pDev, pWin, generateEvents); return; - } + } #endif if (syncEvents.playingEvents) { - CheckVirtualMotion((QdEventPtr)NULL, pWin); - SyntheticMotion(sprite.hot.x, sprite.hot.y); + CheckVirtualMotion(pDev, (QdEventPtr)NULL, pWin); + SyntheticMotion(pDev, pSprite->hot.x, pSprite->hot.y); } else { - sprite.hotLimits = *REGION_EXTENTS( pScreen, &pWin->borderSize); -#ifdef SHAPE - sprite.hotShape = wBoundingShape(pWin) ? &pWin->borderSize + pSprite->hotLimits = *REGION_EXTENTS( pScreen, &pWin->borderSize); + pSprite->hotShape = wBoundingShape(pWin) ? &pWin->borderSize : NullRegion; -#endif - CheckPhysLimits(sprite.current, generateEvents, confineToScreen, - pScreen); + CheckPhysLimits(pDev, pSprite->current, generateEvents, + confineToScreen, pScreen); } } _X_EXPORT Bool -PointerConfinedToScreen(void) +PointerConfinedToScreen(DeviceIntPtr pDev) { - return sprite.confined; + return pDev->spriteInfo->sprite->confined; } /** @@ -901,31 +976,34 @@ PointerConfinedToScreen(void) * happens. */ static void -ChangeToCursor(CursorPtr cursor) +ChangeToCursor(DeviceIntPtr pDev, CursorPtr cursor) { + SpritePtr pSprite = pDev->spriteInfo->sprite; + #ifdef PANORAMIX if(!noPanoramiXExtension) { - XineramaChangeToCursor(cursor); + XineramaChangeToCursor(pDev, cursor); return; } #endif - if (cursor != sprite.current) + if (cursor != pSprite->current) { - if ((sprite.current->bits->xhot != cursor->bits->xhot) || - (sprite.current->bits->yhot != cursor->bits->yhot)) - CheckPhysLimits(cursor, FALSE, sprite.confined, + if ((pSprite->current->bits->xhot != cursor->bits->xhot) || + (pSprite->current->bits->yhot != cursor->bits->yhot)) + CheckPhysLimits(pDev, cursor, FALSE, pSprite->confined, (ScreenPtr)NULL); - (*sprite.hotPhys.pScreen->DisplayCursor) (sprite.hotPhys.pScreen, - cursor); - FreeCursor(sprite.current, (Cursor)0); - sprite.current = cursor; - sprite.current->refcnt++; + (*pSprite->hotPhys.pScreen->DisplayCursor) (pDev, + pSprite->hotPhys.pScreen, + cursor); + FreeCursor(pSprite->current, (Cursor)0); + pSprite->current = cursor; + pSprite->current->refcnt++; } } /** - * @returns true if b is a descendent of a + * @returns true if b is a descendent of a */ Bool IsParent(WindowPtr a, WindowPtr b) @@ -938,13 +1016,15 @@ IsParent(WindowPtr a, WindowPtr b) /** * Update the cursor displayed on the screen. * - * Called whenever a cursor may have changed shape or position. + * Called whenever a cursor may have changed shape or position. */ static void -PostNewCursor(void) +PostNewCursor(DeviceIntPtr pDev) { WindowPtr win; - GrabPtr grab = inputInfo.pointer->grab; + GrabPtr grab = pDev->deviceGrab.grab; + SpritePtr pSprite = pDev->spriteInfo->sprite; + CursorPtr pCursor; if (syncEvents.playingEvents) return; @@ -952,67 +1032,78 @@ PostNewCursor(void) { if (grab->cursor) { - ChangeToCursor(grab->cursor); + ChangeToCursor(pDev, grab->cursor); return; } - if (IsParent(grab->window, sprite.win)) - win = sprite.win; + if (IsParent(grab->window, pSprite->win)) + win = pSprite->win; else win = grab->window; } else - win = sprite.win; + win = pSprite->win; for (; win; win = win->parent) - if (win->optional && win->optional->cursor != NullCursor) - { - ChangeToCursor(win->optional->cursor); - return; + { + if (win->optional) + { + pCursor = WindowGetDeviceCursor(win, pDev); + if (!pCursor && win->optional->cursor != NullCursor) + pCursor = win->optional->cursor; + if (pCursor) + { + ChangeToCursor(pDev, pCursor); + return; + } } + } } + /** - * @return root window of current active screen. + * @param dev device which you want to know its current root window + * @return root window where dev's sprite is located */ _X_EXPORT WindowPtr -GetCurrentRootWindow(void) +GetCurrentRootWindow(DeviceIntPtr dev) { - return ROOT; + return RootWindow(dev); } /** * @return window underneath the cursor sprite. */ _X_EXPORT WindowPtr -GetSpriteWindow(void) +GetSpriteWindow(DeviceIntPtr pDev) { - return sprite.win; + return pDev->spriteInfo->sprite->win; } /** * @return current sprite cursor. */ _X_EXPORT CursorPtr -GetSpriteCursor(void) +GetSpriteCursor(DeviceIntPtr pDev) { - return sprite.current; + return pDev->spriteInfo->sprite->current; } /** * Set x/y current sprite position in screen coordinates. */ _X_EXPORT void -GetSpritePosition(int *px, int *py) +GetSpritePosition(DeviceIntPtr pDev, int *px, int *py) { - *px = sprite.hotPhys.x; - *py = sprite.hotPhys.y; + SpritePtr pSprite = pDev->spriteInfo->sprite; + *px = pSprite->hotPhys.x; + *py = pSprite->hotPhys.y; } #ifdef PANORAMIX _X_EXPORT int -XineramaGetCursorScreen(void) +XineramaGetCursorScreen(DeviceIntPtr pDev) { if(!noPanoramiXExtension) { - return sprite.screen->myNum; + return pDev->spriteInfo->sprite->screen->myNum; } else { return 0; } @@ -1051,18 +1142,25 @@ NoticeEventTime(xEvent *xE) * The following procedures deal with synchronous events * **************************************************************************/ +/** + * EnqueueEvent is a device's processInputProc if a device is frozen. + * Instead of delivering the events to the client, the event is tacked onto a + * linked list for later delivery. + */ void EnqueueEvent(xEvent *xE, DeviceIntPtr device, int count) { - QdEventPtr tail = *syncEvents.pendtail; - QdEventPtr qe; - xEvent *qxE; + QdEventPtr tail = *syncEvents.pendtail; + QdEventPtr qe; + SpritePtr pSprite = device->spriteInfo->sprite; + int eventlen; + NoticeTime(xE); #ifdef XKB /* Fix for key repeating bug. */ - if (device->key != NULL && device->key->xkbInfo != NULL && + if (device->key != NULL && device->key->xkbInfo != NULL && xE->u.u.type == KeyRelease) AccessXCancelRepeatKey(device->key->xkbInfo, xE->u.u.detail); #endif @@ -1079,89 +1177,126 @@ EnqueueEvent(xEvent *xE, DeviceIntPtr device, int count) * the data that GetCurrentRootWindow relies on hasn't been * updated yet. */ - if (xE->u.u.type == MotionNotify) + if (xE->u.u.type == DeviceMotionNotify) XE_KBPTR.root = - WindowTable[sprite.hotPhys.pScreen->myNum]->drawable.id; + WindowTable[pSprite->hotPhys.pScreen->myNum]->drawable.id; eventinfo.events = xE; eventinfo.count = count; CallCallbacks(&DeviceEventCallback, (pointer)&eventinfo); } - if (xE->u.u.type == MotionNotify) + if (xE->u.u.type == DeviceMotionNotify) { #ifdef PANORAMIX if(!noPanoramiXExtension) { - XE_KBPTR.rootX += panoramiXdataPtr[sprite.screen->myNum].x - + XE_KBPTR.rootX += panoramiXdataPtr[pSprite->screen->myNum].x - panoramiXdataPtr[0].x; - XE_KBPTR.rootY += panoramiXdataPtr[sprite.screen->myNum].y - + XE_KBPTR.rootY += panoramiXdataPtr[pSprite->screen->myNum].y - panoramiXdataPtr[0].y; } #endif - sprite.hotPhys.x = XE_KBPTR.rootX; - sprite.hotPhys.y = XE_KBPTR.rootY; + pSprite->hotPhys.x = XE_KBPTR.rootX; + pSprite->hotPhys.y = XE_KBPTR.rootY; /* do motion compression, but not if from different devices */ if (tail && - (tail->event->u.u.type == MotionNotify) && + (tail->event->u.u.type == DeviceMotionNotify) && (tail->device == device) && - (tail->pScreen == sprite.hotPhys.pScreen)) + (tail->pScreen == pSprite->hotPhys.pScreen)) { - tail->event->u.keyButtonPointer.rootX = sprite.hotPhys.x; - tail->event->u.keyButtonPointer.rootY = sprite.hotPhys.y; + tail->event->u.keyButtonPointer.rootX = pSprite->hotPhys.x; + tail->event->u.keyButtonPointer.rootY = pSprite->hotPhys.y; tail->event->u.keyButtonPointer.time = XE_KBPTR.time; tail->months = currentTime.months; return; } } - qe = (QdEventPtr)xalloc(sizeof(QdEventRec) + (count * sizeof(xEvent))); + + eventlen = count * sizeof(xEvent); + if (xE->u.u.type == GenericEvent) /* count is 1 for GenericEvents */ + eventlen += ((xGenericEvent*)xE)->length * 4; + + qe = (QdEventPtr)xalloc(sizeof(QdEventRec) + eventlen); if (!qe) return; qe->next = (QdEventPtr)NULL; qe->device = device; - qe->pScreen = sprite.hotPhys.pScreen; + qe->pScreen = pSprite->hotPhys.pScreen; qe->months = currentTime.months; qe->event = (xEvent *)(qe + 1); qe->evcount = count; - for (qxE = qe->event; --count >= 0; qxE++, xE++) - *qxE = *xE; + if (xE->u.u.type == GenericEvent) + { + memcpy(qe->event, xE, eventlen); + } else + { + xEvent *qxE; + for (qxE = qe->event; --count >= 0; qxE++, xE++) + { + *qxE = *xE; + } + } if (tail) syncEvents.pendtail = &tail->next; *syncEvents.pendtail = qe; } +/** + * Run through the list of events queued up in syncEvents. + * For each event do: + * If the device for this event is not frozen anymore, take it and process it + * as usually. + * After that, check if there's any devices in the list that are not frozen. + * If there is none, we're done. If there is at least one device that is not + * frozen, then re-run from the beginning of the event queue. + */ static void PlayReleasedEvents(void) { QdEventPtr *prev, qe; DeviceIntPtr dev; + DeviceIntPtr pDev; + static CARD32 lastKnownMillis = 0; /* Hack, see comment below */ prev = &syncEvents.pending; while ( (qe = *prev) ) { - if (!qe->device->sync.frozen) + if (!qe->device->deviceGrab.sync.frozen) { *prev = qe->next; + pDev = qe->device; if (*syncEvents.pendtail == *prev) syncEvents.pendtail = prev; - if (qe->event->u.u.type == MotionNotify) - CheckVirtualMotion(qe, NullWindow); + if (qe->event->u.u.type == DeviceMotionNotify) + CheckVirtualMotion(pDev, qe, NullWindow); syncEvents.time.months = qe->months; - syncEvents.time.milliseconds = qe->event->u.keyButtonPointer.time; + /* XXX: Hack! We can't reliably get the time from GenericEvents, + since we don't know which struct it may be. So we store the time + when we know it, and re-use it when we can't get it. */ + if (qe->event->u.u.type == GenericEvent) + { + syncEvents.time.milliseconds = lastKnownMillis; + } else + { + syncEvents.time.milliseconds = qe->event->u.keyButtonPointer.time; + lastKnownMillis = syncEvents.time.milliseconds; + } #ifdef PANORAMIX /* Translate back to the sprite screen since processInputProc will translate from sprite screen to screen 0 upon reentry to the DIX layer */ + /* XXX: we can't do that for generic events */ if(!noPanoramiXExtension) { - qe->event->u.keyButtonPointer.rootX += - panoramiXdataPtr[0].x - - panoramiXdataPtr[sprite.screen->myNum].x; - qe->event->u.keyButtonPointer.rootY += - panoramiXdataPtr[0].y - - panoramiXdataPtr[sprite.screen->myNum].y; + qe->event->u.keyButtonPointer.rootX += + panoramiXdataPtr[0].x - + panoramiXdataPtr[pDev->spriteInfo->sprite->screen->myNum].x; + qe->event->u.keyButtonPointer.rootY += + panoramiXdataPtr[0].y - + panoramiXdataPtr[pDev->spriteInfo->sprite->screen->myNum].y; } #endif (*qe->device->public.processInputProc)(qe->event, qe->device, qe->evcount); xfree(qe); - for (dev = inputInfo.devices; dev && dev->sync.frozen; dev = dev->next) + for (dev = inputInfo.devices; dev && dev->deviceGrab.sync.frozen; dev = dev->next) ; if (!dev) break; @@ -1171,19 +1306,38 @@ PlayReleasedEvents(void) } else prev = &qe->next; - } + } } +/** + * Freeze or thaw the given devices. The device's processing proc is + * switched to either the real processing proc (in case of thawing) or an + * enqueuing processing proc (usually EnqueueEvent()). + * + * @param dev The device to freeze/thaw + * @param frozen True to freeze or false to thaw. + */ static void FreezeThaw(DeviceIntPtr dev, Bool frozen) { - dev->sync.frozen = frozen; + dev->deviceGrab.sync.frozen = frozen; if (frozen) dev->public.processInputProc = dev->public.enqueueInputProc; else dev->public.processInputProc = dev->public.realInputProc; } +/** + * Unfreeze devices and replay all events to the respective clients. + * + * ComputeFreezes takes the first event in the device's frozen event queue. It + * runs up the sprite tree (spriteTrace) and searches for the window to replay + * the events from. If it is found, it checks for passive grabs one down from + * the window or delivers the events. + * + * Since the events in the EQ are always XI events, we need to emulate core + * events here. + */ static void ComputeFreezes(void) { @@ -1196,23 +1350,25 @@ ComputeFreezes(void) DeviceIntPtr dev; for (dev = inputInfo.devices; dev; dev = dev->next) - FreezeThaw(dev, dev->sync.other || (dev->sync.state >= FROZEN)); + FreezeThaw(dev, dev->deviceGrab.sync.other || + (dev->deviceGrab.sync.state >= FROZEN)); if (syncEvents.playingEvents || (!replayDev && !syncEvents.pending)) return; syncEvents.playingEvents = TRUE; if (replayDev) { - xE = replayDev->sync.event; - count = replayDev->sync.evcount; + xE = replayDev->deviceGrab.sync.event; + count = replayDev->deviceGrab.sync.evcount; syncEvents.replayDev = (DeviceIntPtr)NULL; - w = XYToWindow( XE_KBPTR.rootX, XE_KBPTR.rootY); - for (i = 0; i < spriteTraceGood; i++) + w = XYToWindow(replayDev, XE_KBPTR.rootX, XE_KBPTR.rootY); + for (i = 0; i < replayDev->spriteInfo->sprite->spriteTraceGood; i++) { - if (syncEvents.replayWin == spriteTrace[i]) + if (syncEvents.replayWin == + replayDev->spriteInfo->sprite->spriteTrace[i]) { if (!CheckDeviceGrabs(replayDev, xE, i+1, count)) { - if (replayDev->focus) + if (replayDev->focus && !IsPointerEvent(xE)) DeliverFocusedEvent(replayDev, xE, w, count); else DeliverDeviceEvents(w, xE, NullGrab, NullWindow, @@ -1222,7 +1378,7 @@ ComputeFreezes(void) } } /* must not still be in the same stack */ - if (replayDev->focus) + if (replayDev->focus && !IsPointerEvent(xE)) DeliverFocusedEvent(replayDev, xE, w, count); else DeliverDeviceEvents(w, xE, NullGrab, NullWindow, replayDev, count); @@ -1230,24 +1386,34 @@ ComputeFreezes(void) playmore: for (dev = inputInfo.devices; dev; dev = dev->next) { - if (!dev->sync.frozen) + if (!dev->deviceGrab.sync.frozen) { PlayReleasedEvents(); break; } } syncEvents.playingEvents = FALSE; - /* the following may have been skipped during replay, so do it now */ - if ((grab = inputInfo.pointer->grab) && grab->confineTo) + for (dev = inputInfo.devices; dev; dev = dev->next) { - if (grab->confineTo->drawable.pScreen != sprite.hotPhys.pScreen) - sprite.hotPhys.x = sprite.hotPhys.y = 0; - ConfineCursorToWindow(grab->confineTo, TRUE, TRUE); + if (DevHasCursor(dev)) + { + /* the following may have been skipped during replay, + so do it now */ + if ((grab = dev->deviceGrab.grab) && grab->confineTo) + { + if (grab->confineTo->drawable.pScreen != + dev->spriteInfo->sprite->hotPhys.pScreen) + dev->spriteInfo->sprite->hotPhys.x = + dev->spriteInfo->sprite->hotPhys.y = 0; + ConfineCursorToWindow(dev, grab->confineTo, TRUE, TRUE); + } + else + ConfineCursorToWindow(dev, + WindowTable[dev->spriteInfo->sprite->hotPhys.pScreen->myNum], + TRUE, FALSE); + PostNewCursor(dev); + } } - else - ConfineCursorToWindow(WindowTable[sprite.hotPhys.pScreen->myNum], - TRUE, FALSE); - PostNewCursor(); } #ifdef RANDR @@ -1255,232 +1421,280 @@ void ScreenRestructured (ScreenPtr pScreen) { GrabPtr grab; + DeviceIntPtr pDev; - if ((grab = inputInfo.pointer->grab) && grab->confineTo) + for (pDev = inputInfo.devices; pDev; pDev = pDev->next) { - if (grab->confineTo->drawable.pScreen != sprite.hotPhys.pScreen) - sprite.hotPhys.x = sprite.hotPhys.y = 0; - ConfineCursorToWindow(grab->confineTo, TRUE, TRUE); + if (!DevHasCursor(pDev)) + continue; + + /* GrabDevice doesn't have a confineTo field, so we don't need to + * worry about it. */ + if ((grab = pDev->deviceGrab.grab) && grab->confineTo) + { + if (grab->confineTo->drawable.pScreen + != pDev->spriteInfo->sprite->hotPhys.pScreen) + pDev->spriteInfo->sprite->hotPhys.x = pDev->spriteInfo->sprite->hotPhys.y = 0; + ConfineCursorToWindow(pDev, grab->confineTo, TRUE, TRUE); + } + else + ConfineCursorToWindow(pDev, + WindowTable[pDev->spriteInfo->sprite->hotPhys.pScreen->myNum], + TRUE, FALSE); } - else - ConfineCursorToWindow(WindowTable[sprite.hotPhys.pScreen->myNum], - TRUE, FALSE); } #endif static void CheckGrabForSyncs(DeviceIntPtr thisDev, Bool thisMode, Bool otherMode) { - GrabPtr grab = thisDev->grab; + GrabPtr grab = thisDev->deviceGrab.grab; DeviceIntPtr dev; if (thisMode == GrabModeSync) - thisDev->sync.state = FROZEN_NO_EVENT; + thisDev->deviceGrab.sync.state = FROZEN_NO_EVENT; else { /* free both if same client owns both */ - thisDev->sync.state = THAWED; - if (thisDev->sync.other && - (CLIENT_BITS(thisDev->sync.other->resource) == + thisDev->deviceGrab.sync.state = THAWED; + if (thisDev->deviceGrab.sync.other && + (CLIENT_BITS(thisDev->deviceGrab.sync.other->resource) == CLIENT_BITS(grab->resource))) - thisDev->sync.other = NullGrab; + thisDev->deviceGrab.sync.other = NullGrab; } - for (dev = inputInfo.devices; dev; dev = dev->next) - { - if (dev != thisDev) - { - if (otherMode == GrabModeSync) - dev->sync.other = grab; - else - { /* free both if same client owns both */ - if (dev->sync.other && - (CLIENT_BITS(dev->sync.other->resource) == - CLIENT_BITS(grab->resource))) - dev->sync.other = NullGrab; - } - } + + /* + XXX: Direct slave grab won't freeze the paired master device. + The correct thing to do would be to freeze all SDs attached to the + paired master device. + */ + if (thisDev->isMaster) + { + dev = GetPairedDevice(thisDev); + if (otherMode == GrabModeSync) + dev->deviceGrab.sync.other = grab; + else + { /* free both if same client owns both */ + if (dev->deviceGrab.sync.other && + (CLIENT_BITS(dev->deviceGrab.sync.other->resource) == + CLIENT_BITS(grab->resource))) + dev->deviceGrab.sync.other = NullGrab; + } } ComputeFreezes(); } /** * Activate a pointer grab on the given device. A pointer grab will cause all - * core pointer events to be delivered to the grabbing client only. Can cause - * the cursor to change if a grab cursor is set. - * - * As a pointer grab can only be issued on the core devices, mouse is always - * inputInfo.pointer. Extension devices are set up for ActivateKeyboardGrab(). - * + * core pointer events of this device to be delivered to the grabbing client only. + * No other device will send core events to the grab client while the grab is + * on, but core events will be sent to other clients. + * Can cause the cursor to change if a grab cursor is set. + * + * Note that parameter autoGrab may be (True & ImplicitGrabMask) if the grab + * is an implicit grab caused by a ButtonPress event. + * * @param mouse The device to grab. * @param grab The grab structure, needs to be setup. * @param autoGrab True if the grab was caused by a button down event and not - * explicitely by a client. + * explicitely by a client. */ void -ActivatePointerGrab(DeviceIntPtr mouse, GrabPtr grab, +ActivatePointerGrab(DeviceIntPtr mouse, GrabPtr grab, TimeStamp time, Bool autoGrab) { - WindowPtr oldWin = (mouse->grab) ? mouse->grab->window - : sprite.win; + GrabInfoPtr grabinfo = &mouse->deviceGrab; + WindowPtr oldWin = (grabinfo->grab) ? + grabinfo->grab->window + : mouse->spriteInfo->sprite->win; + Bool isPassive = autoGrab & ~ImplicitGrabMask; if (grab->confineTo) { - if (grab->confineTo->drawable.pScreen != sprite.hotPhys.pScreen) - sprite.hotPhys.x = sprite.hotPhys.y = 0; - ConfineCursorToWindow(grab->confineTo, FALSE, TRUE); + if (grab->confineTo->drawable.pScreen + != mouse->spriteInfo->sprite->hotPhys.pScreen) + mouse->spriteInfo->sprite->hotPhys.x = + mouse->spriteInfo->sprite->hotPhys.y = 0; + ConfineCursorToWindow(mouse, grab->confineTo, FALSE, TRUE); } - DoEnterLeaveEvents(oldWin, grab->window, NotifyGrab); + DoEnterLeaveEvents(mouse, oldWin, grab->window, NotifyGrab); mouse->valuator->motionHintWindow = NullWindow; if (syncEvents.playingEvents) - mouse->grabTime = syncEvents.time; + grabinfo->grabTime = syncEvents.time; else - mouse->grabTime = time; + grabinfo->grabTime = time; if (grab->cursor) grab->cursor->refcnt++; - mouse->activeGrab = *grab; - mouse->grab = &mouse->activeGrab; - mouse->fromPassiveGrab = autoGrab; - PostNewCursor(); + grabinfo->activeGrab = *grab; + grabinfo->grab = &grabinfo->activeGrab; + grabinfo->fromPassiveGrab = isPassive; + grabinfo->implicitGrab = autoGrab & ImplicitGrabMask; + PostNewCursor(mouse); CheckGrabForSyncs(mouse,(Bool)grab->pointerMode, (Bool)grab->keyboardMode); } /** * Delete grab on given device, update the sprite. * - * As a pointer grab can only be issued on the core devices, mouse is always - * inputInfo.pointer. Extension devices are set up for ActivateKeyboardGrab(). + * Extension devices are set up for ActivateKeyboardGrab(). */ void DeactivatePointerGrab(DeviceIntPtr mouse) { - GrabPtr grab = mouse->grab; + GrabPtr grab = mouse->deviceGrab.grab; DeviceIntPtr dev; mouse->valuator->motionHintWindow = NullWindow; - mouse->grab = NullGrab; - mouse->sync.state = NOT_GRABBED; - mouse->fromPassiveGrab = FALSE; + mouse->deviceGrab.grab = NullGrab; + mouse->deviceGrab.sync.state = NOT_GRABBED; + mouse->deviceGrab.fromPassiveGrab = FALSE; + + /* make sure the potential XGE event mask is freed too*/ + if (grab->genericMasks) + { + xfree(grab->genericMasks); + grab->genericMasks = NULL; + } + for (dev = inputInfo.devices; dev; dev = dev->next) { - if (dev->sync.other == grab) - dev->sync.other = NullGrab; + if (dev->deviceGrab.sync.other == grab) + dev->deviceGrab.sync.other = NullGrab; } - DoEnterLeaveEvents(grab->window, sprite.win, NotifyUngrab); + DoEnterLeaveEvents(mouse, grab->window, + mouse->spriteInfo->sprite->win, NotifyUngrab); if (grab->confineTo) - ConfineCursorToWindow(ROOT, FALSE, FALSE); - PostNewCursor(); + ConfineCursorToWindow(mouse, RootWindow(mouse), FALSE, FALSE); + PostNewCursor(mouse); if (grab->cursor) FreeCursor(grab->cursor, (Cursor)0); + ComputeFreezes(); } /** - * Activate a keyboard grab on the given device. + * Activate a keyboard grab on the given device. * * Extension devices have ActivateKeyboardGrab() set as their grabbing proc. */ void ActivateKeyboardGrab(DeviceIntPtr keybd, GrabPtr grab, TimeStamp time, Bool passive) { + GrabInfoPtr grabinfo = &keybd->deviceGrab; WindowPtr oldWin; - if (keybd->grab) - oldWin = keybd->grab->window; + if (grabinfo->grab) + oldWin = grabinfo->grab->window; else if (keybd->focus) oldWin = keybd->focus->win; else - oldWin = sprite.win; + oldWin = keybd->spriteInfo->sprite->win; if (oldWin == FollowKeyboardWin) oldWin = inputInfo.keyboard->focus->win; if (keybd->valuator) keybd->valuator->motionHintWindow = NullWindow; DoFocusEvents(keybd, oldWin, grab->window, NotifyGrab); if (syncEvents.playingEvents) - keybd->grabTime = syncEvents.time; + grabinfo->grabTime = syncEvents.time; else - keybd->grabTime = time; - keybd->activeGrab = *grab; - keybd->grab = &keybd->activeGrab; - keybd->fromPassiveGrab = passive; + grabinfo->grabTime = time; + grabinfo->activeGrab = *grab; + grabinfo->grab = &grabinfo->activeGrab; + grabinfo->fromPassiveGrab = passive; CheckGrabForSyncs(keybd, (Bool)grab->keyboardMode, (Bool)grab->pointerMode); } /** - * Delete keyboard grab for the given device. + * Delete keyboard grab for the given device. */ void DeactivateKeyboardGrab(DeviceIntPtr keybd) { - GrabPtr grab = keybd->grab; + GrabPtr grab = keybd->deviceGrab.grab; DeviceIntPtr dev; WindowPtr focusWin = keybd->focus ? keybd->focus->win - : sprite.win; + : keybd->spriteInfo->sprite->win; if (focusWin == FollowKeyboardWin) focusWin = inputInfo.keyboard->focus->win; if (keybd->valuator) keybd->valuator->motionHintWindow = NullWindow; - keybd->grab = NullGrab; - keybd->sync.state = NOT_GRABBED; - keybd->fromPassiveGrab = FALSE; + keybd->deviceGrab.grab = NullGrab; + keybd->deviceGrab.sync.state = NOT_GRABBED; + keybd->deviceGrab.fromPassiveGrab = FALSE; + if (grab->genericMasks) + { + xfree(grab->genericMasks); + grab->genericMasks = NULL; + } + for (dev = inputInfo.devices; dev; dev = dev->next) { - if (dev->sync.other == grab) - dev->sync.other = NullGrab; + if (dev->deviceGrab.sync.other == grab) + dev->deviceGrab.sync.other = NullGrab; } DoFocusEvents(keybd, grab->window, focusWin, NotifyUngrab); + ComputeFreezes(); } void -AllowSome(ClientPtr client, TimeStamp time, DeviceIntPtr thisDev, int newState) +AllowSome(ClientPtr client, + TimeStamp time, + DeviceIntPtr thisDev, + int newState, + Bool core) { Bool thisGrabbed, otherGrabbed, othersFrozen, thisSynced; TimeStamp grabTime; DeviceIntPtr dev; + GrabInfoPtr devgrabinfo, + grabinfo = &thisDev->deviceGrab; - thisGrabbed = thisDev->grab && SameClient(thisDev->grab, client); + thisGrabbed = grabinfo->grab && SameClient(grabinfo->grab, client); thisSynced = FALSE; otherGrabbed = FALSE; othersFrozen = TRUE; - grabTime = thisDev->grabTime; + grabTime = grabinfo->grabTime; for (dev = inputInfo.devices; dev; dev = dev->next) { + devgrabinfo = &dev->deviceGrab; + if (dev == thisDev) continue; - if (dev->grab && SameClient(dev->grab, client)) + if (devgrabinfo->grab && SameClient(devgrabinfo->grab, client)) { if (!(thisGrabbed || otherGrabbed) || - (CompareTimeStamps(dev->grabTime, grabTime) == LATER)) - grabTime = dev->grabTime; + (CompareTimeStamps(devgrabinfo->grabTime, grabTime) == LATER)) + grabTime = devgrabinfo->grabTime; otherGrabbed = TRUE; - if (thisDev->sync.other == dev->grab) + if (grabinfo->sync.other == devgrabinfo->grab) thisSynced = TRUE; - if (dev->sync.state < FROZEN) + if (devgrabinfo->sync.state < FROZEN) othersFrozen = FALSE; } - else if (!dev->sync.other || !SameClient(dev->sync.other, client)) + else if (!devgrabinfo->sync.other || !SameClient(devgrabinfo->sync.other, client)) othersFrozen = FALSE; } - if (!((thisGrabbed && thisDev->sync.state >= FROZEN) || thisSynced)) + if (!((thisGrabbed && grabinfo->sync.state >= FROZEN) || thisSynced)) return; if ((CompareTimeStamps(time, currentTime) == LATER) || (CompareTimeStamps(time, grabTime) == EARLIER)) return; switch (newState) { - case THAWED: /* Async */ + case THAWED: /* Async */ if (thisGrabbed) - thisDev->sync.state = THAWED; + grabinfo->sync.state = THAWED; if (thisSynced) - thisDev->sync.other = NullGrab; + grabinfo->sync.other = NullGrab; ComputeFreezes(); break; case FREEZE_NEXT_EVENT: /* Sync */ if (thisGrabbed) { - thisDev->sync.state = FREEZE_NEXT_EVENT; + grabinfo->sync.state = FREEZE_NEXT_EVENT; if (thisSynced) - thisDev->sync.other = NullGrab; + grabinfo->sync.other = NullGrab; ComputeFreezes(); } break; @@ -1489,10 +1703,13 @@ AllowSome(ClientPtr client, TimeStamp time, DeviceIntPtr thisDev, int newState) { for (dev = inputInfo.devices; dev; dev = dev->next) { - if (dev->grab && SameClient(dev->grab, client)) - dev->sync.state = THAWED; - if (dev->sync.other && SameClient(dev->sync.other, client)) - dev->sync.other = NullGrab; + devgrabinfo = &dev->deviceGrab; + if (devgrabinfo->grab + && SameClient(devgrabinfo->grab, client)) + devgrabinfo->sync.state = THAWED; + if (devgrabinfo->sync.other && + SameClient(devgrabinfo->sync.other, client)) + devgrabinfo->sync.other = NullGrab; } ComputeFreezes(); } @@ -1502,22 +1719,25 @@ AllowSome(ClientPtr client, TimeStamp time, DeviceIntPtr thisDev, int newState) { for (dev = inputInfo.devices; dev; dev = dev->next) { - if (dev->grab && SameClient(dev->grab, client)) - dev->sync.state = FREEZE_BOTH_NEXT_EVENT; - if (dev->sync.other && SameClient(dev->sync.other, client)) - dev->sync.other = NullGrab; + devgrabinfo = &dev->deviceGrab; + if (devgrabinfo->grab + && SameClient(devgrabinfo->grab, client)) + devgrabinfo->sync.state = FREEZE_BOTH_NEXT_EVENT; + if (devgrabinfo->sync.other + && SameClient(devgrabinfo->sync.other, client)) + devgrabinfo->sync.other = NullGrab; } ComputeFreezes(); } break; case NOT_GRABBED: /* Replay */ - if (thisGrabbed && thisDev->sync.state == FROZEN_WITH_EVENT) + if (thisGrabbed && grabinfo->sync.state == FROZEN_WITH_EVENT) { if (thisSynced) - thisDev->sync.other = NullGrab; + grabinfo->sync.other = NullGrab; syncEvents.replayDev = thisDev; - syncEvents.replayWin = thisDev->grab->window; - (*thisDev->DeactivateGrab)(thisDev); + syncEvents.replayWin = grabinfo->grab->window; + (*grabinfo->DeactivateGrab)(thisDev); syncEvents.replayDev = (DeviceIntPtr)NULL; } break; @@ -1528,10 +1748,13 @@ AllowSome(ClientPtr client, TimeStamp time, DeviceIntPtr thisDev, int newState) { if (dev == thisDev) continue; - if (dev->grab && SameClient(dev->grab, client)) - dev->sync.state = THAWED; - if (dev->sync.other && SameClient(dev->sync.other, client)) - dev->sync.other = NullGrab; + devgrabinfo = (core) ? &dev->deviceGrab : &dev->deviceGrab; + if (devgrabinfo->grab + && SameClient(devgrabinfo->grab, client)) + devgrabinfo->sync.state = THAWED; + if (devgrabinfo->sync.other + && SameClient(devgrabinfo->sync.other, client)) + devgrabinfo->sync.other = NullGrab; } ComputeFreezes(); } @@ -1542,45 +1765,49 @@ AllowSome(ClientPtr client, TimeStamp time, DeviceIntPtr thisDev, int newState) /** * Server-side protocol handling for AllowEvents request. * - * Release some events from a frozen device. Only applicable for core devices. + * Release some events from a frozen device. */ int ProcAllowEvents(ClientPtr client) { TimeStamp time; - DeviceIntPtr mouse = inputInfo.pointer; - DeviceIntPtr keybd = inputInfo.keyboard; + DeviceIntPtr mouse = NULL; + DeviceIntPtr keybd = NULL; REQUEST(xAllowEventsReq); REQUEST_SIZE_MATCH(xAllowEventsReq); time = ClientTimeToServerTime(stuff->time); + + mouse = PickPointer(client); + keybd = PickKeyboard(client); + switch (stuff->mode) { case ReplayPointer: - AllowSome(client, time, mouse, NOT_GRABBED); + AllowSome(client, time, mouse, NOT_GRABBED, True); break; - case SyncPointer: - AllowSome(client, time, mouse, FREEZE_NEXT_EVENT); + case SyncPointer: + AllowSome(client, time, mouse, FREEZE_NEXT_EVENT, True); break; - case AsyncPointer: - AllowSome(client, time, mouse, THAWED); + case AsyncPointer: + AllowSome(client, time, mouse, THAWED, True); break; - case ReplayKeyboard: - AllowSome(client, time, keybd, NOT_GRABBED); + case ReplayKeyboard: + AllowSome(client, time, keybd, NOT_GRABBED, True); break; - case SyncKeyboard: - AllowSome(client, time, keybd, FREEZE_NEXT_EVENT); + case SyncKeyboard: + AllowSome(client, time, keybd, FREEZE_NEXT_EVENT, True); break; - case AsyncKeyboard: - AllowSome(client, time, keybd, THAWED); + case AsyncKeyboard: + AllowSome(client, time, keybd, THAWED, True); break; case SyncBoth: - AllowSome(client, time, keybd, FREEZE_BOTH_NEXT_EVENT); + AllowSome(client, time, keybd, FREEZE_BOTH_NEXT_EVENT, True); break; case AsyncBoth: - AllowSome(client, time, keybd, THAWED_BOTH); + AllowSome(client, time, keybd, THAWED_BOTH, True); break; - default: + default: client->errorValue = stuff->mode; return BadValue; } @@ -1600,15 +1827,15 @@ ReleaseActiveGrabs(ClientPtr client) * releasing active grabs. */ do { - done = TRUE; - for (dev = inputInfo.devices; dev; dev = dev->next) - { - if (dev->grab && SameClient(dev->grab, client)) + done = TRUE; + for (dev = inputInfo.devices; dev; dev = dev->next) + { + if (dev->deviceGrab.grab && SameClient(dev->deviceGrab.grab, client)) { - (*dev->DeactivateGrab)(dev); - done = FALSE; + (*dev->deviceGrab.DeactivateGrab)(dev); + done = FALSE; } - } + } } while (!done); } @@ -1624,31 +1851,32 @@ ReleaseActiveGrabs(ClientPtr client) * * TryClientEvents() is the last station before actually writing the events to * the socket. Anything that is not filtered here, will get delivered to the - * client. - * An event is only delivered if + * client. + * An event is only delivered if * - mask and filter match up. * - no other client has a grab on the device that caused the event. - * + * * * @param client The target client to deliver to. + * @param dev The device the event came from. May be NULL. * @param pEvents The events to be delivered. * @param count Number of elements in pEvents. * @param mask Event mask as set by the window. * @param filter Mask based on event type. - * @param grab Possible grab on the device that caused the event. + * @param grab Possible grab on the device that caused the event. * * @return 1 if event was delivered, 0 if not or -1 if grab was not set by the * client. */ _X_EXPORT int -TryClientEvents (ClientPtr client, xEvent *pEvents, int count, Mask mask, - Mask filter, GrabPtr grab) +TryClientEvents (ClientPtr client, DeviceIntPtr dev, xEvent *pEvents, + int count, Mask mask, Mask filter, GrabPtr grab) { int i; int type; #ifdef DEBUG_EVENTS - ErrorF("Event([%d, %d], mask=0x%x), client=%d", + ErrorF("[dix] Event([%d, %d], mask=0x%x), client=%d", pEvents->u.u.type, pEvents->u.u.detail, mask, client->index); #endif if ((client) && (client != serverClient) && (!client->clientGone) && @@ -1661,12 +1889,12 @@ TryClientEvents (ClientPtr client, xEvent *pEvents, int count, Mask mask, { if (mask & PointerMotionHintMask) { - if (WID(inputInfo.pointer->valuator->motionHintWindow) == + if (WID(dev->valuator->motionHintWindow) == pEvents->u.keyButtonPointer.event) { #ifdef DEBUG_EVENTS - ErrorF("\n"); - ErrorF("motionHintWindow == keyButtonPointer.event\n"); + ErrorF("[dix] \n"); + ErrorF("[dix] motionHintWindow == keyButtonPointer.event\n"); #endif return 1; /* don't send, but pretend we did */ } @@ -1677,7 +1905,6 @@ TryClientEvents (ClientPtr client, xEvent *pEvents, int count, Mask mask, pEvents->u.u.detail = NotifyNormal; } } -#ifdef XINPUT else { if ((type == DeviceMotionNotify) && @@ -1685,7 +1912,6 @@ TryClientEvents (ClientPtr client, xEvent *pEvents, int count, Mask mask, ((deviceKeyButtonPointer*)pEvents, mask) != 0) return 1; } -#endif type &= 0177; if (type != KeymapNotify) { @@ -1696,23 +1922,21 @@ TryClientEvents (ClientPtr client, xEvent *pEvents, int count, Mask mask, if (BitIsOn(criticalEvents, type)) { -#ifdef SMART_SCHEDULE if (client->smart_priority < SMART_MAX_PRIORITY) client->smart_priority++; -#endif SetCriticalOutputPending(); } WriteEventsToClient(client, count, pEvents); #ifdef DEBUG_EVENTS - ErrorF( " delivered\n"); + ErrorF("[dix] delivered\n"); #endif return 1; } else { #ifdef DEBUG_EVENTS - ErrorF("\n"); + ErrorF("[dix] \n"); #endif return 0; } @@ -1723,21 +1947,25 @@ TryClientEvents (ClientPtr client, xEvent *pEvents, int count, Mask mask, * actually needs to be delivered. May activate a grab if the event is a * button press. * + * Core events are always delivered to the window owner. If the filter is + * something other than CantBeFiltered, the event is also delivered to other + * clients with the matching mask on the window. + * * More than one event may be delivered at a time. This is the case with * DeviceMotionNotifies which may be followed by DeviceValuator events. - * + * * @param pWin The window that would get the event. * @param pEvents The events to be delivered. * @param count Number of elements in pEvents. * @param filter Mask based on event type. - * @param grab Possible grab on the device that caused the event. + * @param grab Possible grab on the device that caused the event. * @param mskidx Mask index, depending on device that caused event. * * @return Number of events delivered to various clients. */ int -DeliverEventsToWindow(WindowPtr pWin, xEvent *pEvents, int count, - Mask filter, GrabPtr grab, int mskidx) +DeliverEventsToWindow(DeviceIntPtr pDev, WindowPtr pWin, xEvent + *pEvents, int count, Mask filter, GrabPtr grab, int mskidx) { int deliveries = 0, nondeliveries = 0; int attempt; @@ -1748,16 +1976,23 @@ DeliverEventsToWindow(WindowPtr pWin, xEvent *pEvents, int count, int type = pEvents->u.u.type; /* CantBeFiltered means only window owner gets the event */ - if ((filter == CantBeFiltered) || !(type & EXTENSION_EVENT_BASE)) + if ((filter == CantBeFiltered) || + (!(type & EXTENSION_EVENT_BASE) && type != GenericEvent)) { /* if nobody ever wants to see this event, skip some work */ if (filter != CantBeFiltered && !((wOtherEventMasks(pWin)|pWin->eventMask) & filter)) return 0; + + if (!(type & EXTENSION_EVENT_BASE) && + IsInterferingGrab(wClient(pWin), pDev, pEvents)) + return 0; + if (XaceHook(XACE_RECEIVE_ACCESS, wClient(pWin), pWin, pEvents, count)) /* do nothing */; - else if ( (attempt = TryClientEvents(wClient(pWin), pEvents, count, - pWin->eventMask, filter, grab)) ) + else if ( (attempt = TryClientEvents(wClient(pWin), pDev, pEvents, + count, pWin->eventMask, + filter, grab)) ) { if (attempt > 0) { @@ -1770,41 +2005,94 @@ DeliverEventsToWindow(WindowPtr pWin, xEvent *pEvents, int count, } if (filter != CantBeFiltered) { - if (type & EXTENSION_EVENT_BASE) - { - OtherInputMasks *inputMasks; + /* Handle generic events */ + if (type == GenericEvent) + { + GenericMaskPtr gmask; + /* We don't do more than one GenericEvent at a time. */ + if (count > 1) + { + ErrorF("[dix] Do not send more than one GenericEvent at a time!\n"); + return 0; + } - inputMasks = wOtherInputMasks(pWin); - if (!inputMasks || - !(inputMasks->inputEvents[mskidx] & filter)) - return 0; - other = inputMasks->inputClients; - } - else - other = (InputClients *)wOtherClients(pWin); - for (; other; other = other->next) - { - if (XaceHook(XACE_RECEIVE_ACCESS, rClient(other), pWin, pEvents, - count)) - /* do nothing */; - else if ( (attempt = TryClientEvents(rClient(other), pEvents, count, - other->mask[mskidx], filter, grab)) ) - { - if (attempt > 0) - { - deliveries++; - client = rClient(other); - deliveryMask = other->mask[mskidx]; - } else - nondeliveries--; - } - } + /* if we get here, filter should be set to the GE specific mask. + check if any client wants it */ + if (!GEDeviceMaskIsSet(pWin, pDev, GEEXT(pEvents), filter)) + return 0; + + /* run through all clients, deliver event */ + for (gmask = GECLIENT(pWin); gmask; gmask = gmask->next) + { + if (gmask->eventMask[GEEXTIDX(pEvents)] & filter) + { + if (XaceHook(XACE_RECEIVE_ACCESS, rClient(gmask), pWin, + pEvents, count)) + /* do nothing */; + else if (TryClientEvents(rClient(gmask), pDev, + pEvents, count, + gmask->eventMask[GEEXTIDX(pEvents)], + filter, grab) > 0) + { + deliveries++; + } else + nondeliveries--; + } + } + } + else { + /* Traditional event */ + if (type & EXTENSION_EVENT_BASE) + { + OtherInputMasks *inputMasks; + + inputMasks = wOtherInputMasks(pWin); + if (!inputMasks || + !(inputMasks->inputEvents[mskidx] & filter)) + return 0; + other = inputMasks->inputClients; + } + else + other = (InputClients *)wOtherClients(pWin); + for (; other; other = other->next) + { + /* core event? check for grab interference */ + if (!(type & EXTENSION_EVENT_BASE) && + IsInterferingGrab(rClient(other), pDev, pEvents)) + continue; + + if (XaceHook(XACE_RECEIVE_ACCESS, rClient(other), pWin, + pEvents, count)) + /* do nothing */; + else if ( (attempt = TryClientEvents(rClient(other), pDev, + pEvents, count, + other->mask[mskidx], + filter, grab)) ) + { + if (attempt > 0) + { + deliveries++; + client = rClient(other); + deliveryMask = other->mask[mskidx]; + } else + nondeliveries--; + } + } + } } - if ((type == ButtonPress) && deliveries && (!grab)) + /* + * Note that since core events are delivered first, an implicit grab may + * be activated on a core grab, stopping the XI events. + */ + if ((type == DeviceButtonPress || type == ButtonPress) + && deliveries + && (!grab)) { GrabRec tempGrab; + OtherInputMasks *inputMasks; - tempGrab.device = inputInfo.pointer; + tempGrab.next = NULL; + tempGrab.device = pDev; tempGrab.resource = client->clientAsMask; tempGrab.window = pWin; tempGrab.ownerEvents = (deliveryMask & OwnerGrabButtonMask) ? TRUE : FALSE; @@ -1813,12 +2101,32 @@ DeliverEventsToWindow(WindowPtr pWin, xEvent *pEvents, int count, tempGrab.pointerMode = GrabModeAsync; tempGrab.confineTo = NullWindow; tempGrab.cursor = NullCursor; - (*inputInfo.pointer->ActivateGrab)(inputInfo.pointer, &tempGrab, - currentTime, TRUE); + tempGrab.coreGrab = (type == ButtonPress); + + /* get the XI device mask */ + inputMasks = wOtherInputMasks(pWin); + tempGrab.deviceMask = (inputMasks) ? inputMasks->inputEvents[pDev->id]: 0; + + /* get the XGE event mask. */ + tempGrab.genericMasks = NULL; + if (pWin->optional && pWin->optional->geMasks) + { + GenericClientMasksPtr gemasks = pWin->optional->geMasks; + GenericMaskPtr geclient = gemasks->geClients; + while(geclient && rClient(geclient) != client) + geclient = geclient->next; + if (geclient) + { + tempGrab.genericMasks = xcalloc(1, sizeof(GenericMaskRec)); + *tempGrab.genericMasks = *geclient; + tempGrab.genericMasks->next = NULL; + } + } + (*pDev->deviceGrab.ActivateGrab)(pDev, &tempGrab, + currentTime, TRUE | ImplicitGrabMask); } else if ((type == MotionNotify) && deliveries) - inputInfo.pointer->valuator->motionHintWindow = pWin; -#ifdef XINPUT + pDev->valuator->motionHintWindow = pWin; else { if (((type == DeviceMotionNotify) @@ -1830,7 +2138,6 @@ DeliverEventsToWindow(WindowPtr pWin, xEvent *pEvents, int count, (deviceKeyButtonPointer*) pEvents, grab, client, deliveryMask); } -#endif if (deliveries) return deliveries; return nondeliveries; @@ -1842,11 +2149,11 @@ DeliverEventsToWindow(WindowPtr pWin, xEvent *pEvents, int count, */ #ifdef PANORAMIX -static int +static int XineramaTryClientEventsResult( ClientPtr client, GrabPtr grab, - Mask mask, + Mask mask, Mask filter ){ if ((client) && (client != serverClient) && (!client->clientGone) && @@ -1869,7 +2176,7 @@ XineramaTryClientEventsResult( * @param dontClient Don't deliver to the dontClient. */ int -MaybeDeliverEventsToClient(WindowPtr pWin, xEvent *pEvents, +MaybeDeliverEventsToClient(WindowPtr pWin, xEvent *pEvents, int count, Mask filter, ClientPtr dontClient) { OtherClients *other; @@ -1880,13 +2187,13 @@ MaybeDeliverEventsToClient(WindowPtr pWin, xEvent *pEvents, if (wClient(pWin) == dontClient) return 0; #ifdef PANORAMIX - if(!noPanoramiXExtension && pWin->drawable.pScreen->myNum) + if(!noPanoramiXExtension && pWin->drawable.pScreen->myNum) return XineramaTryClientEventsResult( wClient(pWin), NullGrab, pWin->eventMask, filter); #endif if (XaceHook(XACE_RECEIVE_ACCESS, wClient(pWin), pWin, pEvents, count)) return 1; /* don't send, but pretend we did */ - return TryClientEvents(wClient(pWin), pEvents, count, + return TryClientEvents(wClient(pWin), NULL, pEvents, count, pWin->eventMask, filter, NullGrab); } for (other = wOtherClients(pWin); other; other = other->next) @@ -1896,14 +2203,14 @@ MaybeDeliverEventsToClient(WindowPtr pWin, xEvent *pEvents, if (SameClient(other, dontClient)) return 0; #ifdef PANORAMIX - if(!noPanoramiXExtension && pWin->drawable.pScreen->myNum) + if(!noPanoramiXExtension && pWin->drawable.pScreen->myNum) return XineramaTryClientEventsResult( rClient(other), NullGrab, other->mask, filter); #endif if (XaceHook(XACE_RECEIVE_ACCESS, rClient(other), pWin, pEvents, count)) return 1; /* don't send, but pretend we did */ - return TryClientEvents(rClient(other), pEvents, count, + return TryClientEvents(rClient(other), NULL, pEvents, count, other->mask, filter, NullGrab); } } @@ -1920,41 +2227,47 @@ MaybeDeliverEventsToClient(WindowPtr pWin, xEvent *pEvents, */ static void FixUpEventFromWindow( + DeviceIntPtr pDev, xEvent *xE, WindowPtr pWin, Window child, Bool calcChild) { + SpritePtr pSprite = pDev->spriteInfo->sprite; + + if (xE->u.u.type == GenericEvent) /* just a safety barrier */ + return; + if (calcChild) { - WindowPtr w=spriteTrace[spriteTraceGood-1]; - /* If the search ends up past the root should the child field be - set to none or should the value in the argument be passed - through. It probably doesn't matter since everyone calls + WindowPtr w= pSprite->spriteTrace[pSprite->spriteTraceGood-1]; + /* If the search ends up past the root should the child field be + set to none or should the value in the argument be passed + through. It probably doesn't matter since everyone calls this function with child == None anyway. */ - while (w) + while (w) { /* If the source window is same as event window, child should be none. Don't bother going all all the way back to the root. */ - if (w == pWin) - { - child = None; - break; + if (w == pWin) + { + child = None; + break; } - + if (w->parent == pWin) { child = w->drawable.id; break; } - w = w->parent; - } + w = w->parent; + } } - XE_KBPTR.root = ROOT->drawable.id; + XE_KBPTR.root = RootWindow(pDev)->drawable.id; XE_KBPTR.event = pWin->drawable.id; - if (sprite.hot.pScreen == pWin->drawable.pScreen) + if (pSprite->hot.pScreen == pWin->drawable.pScreen) { XE_KBPTR.sameScreen = xTrue; XE_KBPTR.child = child; @@ -1973,12 +2286,14 @@ FixUpEventFromWindow( } /** - * Deliver events caused by input devices. Called for all core input events - * and XI events. No filtering of events happens before DeliverDeviceEvents(), - * it will be called for any event that comes out of the event queue. - * - * For all core events, dev is either inputInfo.pointer or inputInfo.keyboard. - * For all extension events, dev is the device that caused the event. + * Deliver events caused by input devices. Called for both core input events + * and XI events. + * For events from a non-grabbed, non-focus device, DeliverDeviceEvents is + * called directly from the processInputProc. + * For grabbed devices, DeliverGrabbedEvent is called first, and _may_ call + * DeliverDeviceEvents. + * For focused events, DeliverFocusedEvent is called first, and _may_ call + * DeliverDeviceEvents. * * @param pWin Window to deliver event to. * @param xE Events to deliver. @@ -1987,77 +2302,110 @@ FixUpEventFromWindow( * @param dev The device that is responsible for the event. * @param count number of events in xE. * + * @see DeliverGrabbedEvent + * @see DeliverFocusedEvent */ int -DeliverDeviceEvents(WindowPtr pWin, xEvent *xE, GrabPtr grab, +DeliverDeviceEvents(WindowPtr pWin, xEvent *xE, GrabPtr grab, WindowPtr stopAt, DeviceIntPtr dev, int count) { Window child = None; int type = xE->u.u.type; - Mask filter = filters[type]; + Mask filter = filters[dev->id][type]; int deliveries = 0; + OtherInputMasks *inputMasks; + int mskidx = dev->id; + xEvent core; if (XaceHook(XACE_SEND_ACCESS, NULL, dev, pWin, xE, count)) return 0; - if (type & EXTENSION_EVENT_BASE) + /* handle generic events */ + /* XXX: Generic events aren't quite handled correctly yet. They should + * eventually fit in with the rest of the stuff + */ + if (type == GenericEvent) { - OtherInputMasks *inputMasks; - int mskidx = dev->id; + WindowPtr win = pWin; + xGenericEvent* ge = (xGenericEvent*)xE; - inputMasks = wOtherInputMasks(pWin); - if (inputMasks && !(filter & inputMasks->deliverableEvents[mskidx])) - return 0; - while (pWin) - { - if (inputMasks && (inputMasks->inputEvents[mskidx] & filter)) - { - FixUpEventFromWindow(xE, pWin, child, FALSE); - deliveries = DeliverEventsToWindow(pWin, xE, count, filter, - grab, mskidx); - if (deliveries > 0) - return deliveries; - } - if ((deliveries < 0) || - (pWin == stopAt) || - (inputMasks && - (filter & inputMasks->dontPropagateMask[mskidx]))) - return 0; - child = pWin->drawable.id; - pWin = pWin->parent; - if (pWin) - inputMasks = wOtherInputMasks(pWin); - } + if (count > 1) + { + ErrorF("[dix] Do not send more than one GenericEvent at a time!\n"); + return 0; + } + filter = generic_filters[GEEXTIDX(xE)][ge->evtype]; + + while(win) + { + if (GEDeviceMaskIsSet(win, dev, GEEXT(xE), filter)) + { + if (GEExtensions[GEEXTIDX(xE)].evfill) + GEExtensions[GEEXTIDX(xE)].evfill(ge, dev, win, grab); + deliveries = DeliverEventsToWindow(dev, win, xE, count, + filter, grab, 0); + if (deliveries > 0) + return deliveries; + } + + win = win->parent; + } } - else + + while (pWin && type != GenericEvent) { - if (!(filter & pWin->deliverableEvents)) - return 0; - while (pWin) - { - if ((wOtherEventMasks(pWin)|pWin->eventMask) & filter) - { - FixUpEventFromWindow(xE, pWin, child, FALSE); - deliveries = DeliverEventsToWindow(pWin, xE, count, filter, - grab, 0); - if (deliveries > 0) - return deliveries; - } - if ((deliveries < 0) || - (pWin == stopAt) || - (filter & wDontPropagateMask(pWin))) - return 0; - child = pWin->drawable.id; - pWin = pWin->parent; - } + if (!dev->isMaster) + { + inputMasks = wOtherInputMasks(pWin); + if (inputMasks && (filter & inputMasks->deliverableEvents[mskidx])) + { + + if (inputMasks && (inputMasks->inputEvents[mskidx] & filter)) + { + FixUpEventFromWindow(dev, xE, pWin, child, FALSE); + deliveries = DeliverEventsToWindow(dev, pWin, xE, count, + filter, grab, mskidx); + if (deliveries > 0) + return deliveries; + } + } + + if ((deliveries < 0) || (pWin == stopAt) || + (inputMasks && (filter & inputMasks->dontPropagateMask[mskidx]))) + return 0; + } else + { + core = *xE; + core.u.u.type = XItoCoreType(xE->u.u.type); + + if (core.u.u.type && filter & pWin->deliverableEvents) + { + if ((wOtherEventMasks(pWin)|pWin->eventMask) & filter) + { + FixUpEventFromWindow(dev, &core, pWin, child, FALSE); + deliveries = DeliverEventsToWindow(dev, pWin, &core, 1, + filter, grab, 0); + if (deliveries > 0) + return deliveries; + } + } + + if ((deliveries < 0) || (pWin == stopAt) || + (filter & wDontPropagateMask(pWin))) + return 0; + } + + child = pWin->drawable.id; + pWin = pWin->parent; } + return 0; } /** * Deliver event to a window and it's immediate parent. Used for most window * events (CreateNotify, ConfigureNotify, etc.). Not useful for events that - * propagate up the tree or extension events + * propagate up the tree or extension events * * In case of a ReparentNotify event, the event will be delivered to the * otherParent as well. @@ -2068,7 +2416,7 @@ DeliverDeviceEvents(WindowPtr pWin, xEvent *xE, GrabPtr grab, * @param otherParent Used for ReparentNotify events. */ _X_EXPORT int -DeliverEvents(WindowPtr pWin, xEvent *xE, int count, +DeliverEvents(WindowPtr pWin, xEvent *xE, int count, WindowPtr otherParent) { Mask filter; @@ -2081,24 +2429,26 @@ DeliverEvents(WindowPtr pWin, xEvent *xE, int count, if (!count) return 0; - filter = filters[xE->u.u.type]; + /* We don't know a device here. However, this should only ever be called + for a non-device event so we are safe to use 0*/ + filter = filters[0][xE->u.u.type]; if ((filter & SubstructureNotifyMask) && (xE->u.u.type != CreateNotify)) xE->u.destroyNotify.event = pWin->drawable.id; if (filter != StructureAndSubMask) - return DeliverEventsToWindow(pWin, xE, count, filter, NullGrab, 0); - deliveries = DeliverEventsToWindow(pWin, xE, count, StructureNotifyMask, + return DeliverEventsToWindow(inputInfo.pointer, pWin, xE, count, filter, NullGrab, 0); + deliveries = DeliverEventsToWindow(inputInfo.pointer, pWin, xE, count, StructureNotifyMask, NullGrab, 0); if (pWin->parent) { xE->u.destroyNotify.event = pWin->parent->drawable.id; - deliveries += DeliverEventsToWindow(pWin->parent, xE, count, + deliveries += DeliverEventsToWindow(inputInfo.pointer, pWin->parent, xE, count, SubstructureNotifyMask, NullGrab, 0); if (xE->u.u.type == ReparentNotify) { xE->u.destroyNotify.event = otherParent->drawable.id; - deliveries += DeliverEventsToWindow(otherParent, xE, count, - SubstructureNotifyMask, + deliveries += DeliverEventsToWindow(inputInfo.pointer, + otherParent, xE, count, SubstructureNotifyMask, NullGrab, 0); } } @@ -2106,23 +2456,25 @@ DeliverEvents(WindowPtr pWin, xEvent *xE, int count, } -static Bool +static Bool PointInBorderSize(WindowPtr pWin, int x, int y) { BoxRec box; + SpritePtr pSprite = inputInfo.pointer->spriteInfo->sprite; if(POINT_IN_REGION(pWin->drawable.pScreen, &pWin->borderSize, x, y, &box)) return TRUE; #ifdef PANORAMIX - if(!noPanoramiXExtension && XineramaSetWindowPntrs(pWin)) { + if(!noPanoramiXExtension && + XineramaSetWindowPntrs(inputInfo.pointer, pWin)) { int i; for(i = 1; i < PanoramiXNumScreens; i++) { - if(POINT_IN_REGION(sprite.screen, - &sprite.windows[i]->borderSize, - x + panoramiXdataPtr[0].x - panoramiXdataPtr[i].x, - y + panoramiXdataPtr[0].y - panoramiXdataPtr[i].y, + if(POINT_IN_REGION(pSprite->screen, + &pSprite->windows[i]->borderSize, + x + panoramiXdataPtr[0].x - panoramiXdataPtr[i].x, + y + panoramiXdataPtr[0].y - panoramiXdataPtr[i].y, &box)) return TRUE; } @@ -2142,14 +2494,16 @@ PointInBorderSize(WindowPtr pWin, int x, int y) * * @returns the window at the given coordinates. */ -static WindowPtr -XYToWindow(int x, int y) +static WindowPtr +XYToWindow(DeviceIntPtr pDev, int x, int y) { WindowPtr pWin; BoxRec box; + SpritePtr pSprite; - spriteTraceGood = 1; /* root window still there */ - pWin = ROOT->firstChild; + pSprite = pDev->spriteInfo->sprite; + pSprite->spriteTraceGood = 1; /* root window still there */ + pWin = RootWindow(pDev)->firstChild; while (pWin) { if ((pWin->mapped) && @@ -2159,7 +2513,6 @@ XYToWindow(int x, int y) (y >= pWin->drawable.y - wBorderWidth (pWin)) && (y < pWin->drawable.y + (int)pWin->drawable.height + wBorderWidth (pWin)) -#ifdef SHAPE /* When a window is shaped, a further check * is made to see if the point is inside * borderSize @@ -2170,24 +2523,28 @@ XYToWindow(int x, int y) wInputShape(pWin), x - pWin->drawable.x, y - pWin->drawable.y, &box)) +#ifdef ROOTLESS + /* In rootless mode windows may be offscreen, even when + * they're in X's stack. (E.g. if the native window system + * implements some form of virtual desktop system). + */ + && !pWin->rootlessUnhittable #endif ) { - if (spriteTraceGood >= spriteTraceSize) + if (pSprite->spriteTraceGood >= pSprite->spriteTraceSize) { - spriteTraceSize += 10; - Must_have_memory = TRUE; /* XXX */ - spriteTrace = (WindowPtr *)xrealloc( - spriteTrace, spriteTraceSize*sizeof(WindowPtr)); - Must_have_memory = FALSE; /* XXX */ + pSprite->spriteTraceSize += 10; + pSprite->spriteTrace = xrealloc(pSprite->spriteTrace, + pSprite->spriteTraceSize*sizeof(WindowPtr)); } - spriteTrace[spriteTraceGood++] = pWin; + pSprite->spriteTrace[pSprite->spriteTraceGood++] = pWin; pWin = pWin->firstChild; } else pWin = pWin->nextSib; } - return spriteTrace[spriteTraceGood-1]; + return pSprite->spriteTrace[pSprite->spriteTraceGood-1]; } /** @@ -2195,74 +2552,100 @@ XYToWindow(int x, int y) * position, then update the event with the new coordinates that may have been * changed. If the window underneath the sprite has changed, change to new * cursor and send enter/leave events. + * + * CheckMotion() will not do anything and return FALSE if the event is not a + * pointer event. + * + * @return TRUE if the sprite has moved or FALSE otherwise. */ -static Bool -CheckMotion(xEvent *xE) +Bool +CheckMotion(xEvent *xE, DeviceIntPtr pDev) { - WindowPtr prevSpriteWin = sprite.win; + INT16 *rootX, *rootY; + WindowPtr prevSpriteWin; + SpritePtr pSprite = pDev->spriteInfo->sprite; + + prevSpriteWin = pSprite->win; #ifdef PANORAMIX if(!noPanoramiXExtension) - return XineramaCheckMotion(xE); + return XineramaCheckMotion(xE, pDev); #endif if (xE && !syncEvents.playingEvents) { - if (sprite.hot.pScreen != sprite.hotPhys.pScreen) - { - sprite.hot.pScreen = sprite.hotPhys.pScreen; - ROOT = WindowTable[sprite.hot.pScreen->myNum]; - } - sprite.hot.x = XE_KBPTR.rootX; - sprite.hot.y = XE_KBPTR.rootY; - if (sprite.hot.x < sprite.physLimits.x1) - sprite.hot.x = sprite.physLimits.x1; - else if (sprite.hot.x >= sprite.physLimits.x2) - sprite.hot.x = sprite.physLimits.x2 - 1; - if (sprite.hot.y < sprite.physLimits.y1) - sprite.hot.y = sprite.physLimits.y1; - else if (sprite.hot.y >= sprite.physLimits.y2) - sprite.hot.y = sprite.physLimits.y2 - 1; -#ifdef SHAPE - if (sprite.hotShape) - ConfineToShape(sprite.hotShape, &sprite.hot.x, &sprite.hot.y); -#endif -#ifdef XEVIE - xeviehot.x = sprite.hot.x; - xeviehot.y = sprite.hot.y; -#endif - sprite.hotPhys = sprite.hot; - if ((sprite.hotPhys.x != XE_KBPTR.rootX) || - (sprite.hotPhys.y != XE_KBPTR.rootY)) + /* GetPointerEvents() guarantees that pointer events have the correct + rootX/Y set already. */ + switch(xE->u.u.type) + { + case ButtonPress: + case ButtonRelease: + case MotionNotify: + rootX = &XE_KBPTR.rootX; + rootY = &XE_KBPTR.rootY; + break; + default: + if (xE->u.u.type == DeviceButtonPress || + xE->u.u.type == DeviceButtonRelease || + xE->u.u.type == DeviceMotionNotify) + { + rootX = &((deviceKeyButtonPointer*)xE)->root_x; + rootY = &((deviceKeyButtonPointer*)xE)->root_y; + break; + } + /* all other events return FALSE */ + return FALSE; + } + + if (pSprite->hot.pScreen != pSprite->hotPhys.pScreen) + { + pSprite->hot.pScreen = pSprite->hotPhys.pScreen; + RootWindow(pDev) = WindowTable[pSprite->hot.pScreen->myNum]; + } + pSprite->hot.x = *rootX; + pSprite->hot.y = *rootY; + if (pSprite->hot.x < pSprite->physLimits.x1) + pSprite->hot.x = pSprite->physLimits.x1; + else if (pSprite->hot.x >= pSprite->physLimits.x2) + pSprite->hot.x = pSprite->physLimits.x2 - 1; + if (pSprite->hot.y < pSprite->physLimits.y1) + pSprite->hot.y = pSprite->physLimits.y1; + else if (pSprite->hot.y >= pSprite->physLimits.y2) + pSprite->hot.y = pSprite->physLimits.y2 - 1; + if (pSprite->hotShape) + ConfineToShape(pDev, pSprite->hotShape, &pSprite->hot.x, &pSprite->hot.y); + pSprite->hotPhys = pSprite->hot; + + if ((pSprite->hotPhys.x != *rootX) || + (pSprite->hotPhys.y != *rootY)) { - (*sprite.hotPhys.pScreen->SetCursorPosition)( - sprite.hotPhys.pScreen, - sprite.hotPhys.x, sprite.hotPhys.y, FALSE); + (*pSprite->hotPhys.pScreen->SetCursorPosition)( + pDev, pSprite->hotPhys.pScreen, + pSprite->hotPhys.x, pSprite->hotPhys.y, FALSE); } - XE_KBPTR.rootX = sprite.hot.x; - XE_KBPTR.rootY = sprite.hot.y; + + *rootX = pSprite->hot.x; + *rootY = pSprite->hot.y; } -#ifdef XEVIE - xeviewin = -#endif - sprite.win = XYToWindow(sprite.hot.x, sprite.hot.y); + pSprite->win = XYToWindow(pDev, pSprite->hot.x, pSprite->hot.y); #ifdef notyet - if (!(sprite.win->deliverableEvents & - Motion_Filter(inputInfo.pointer->button)) + if (!(pSprite->win->deliverableEvents & + Motion_Filter(pDev->button)) !syncEvents.playingEvents) { /* XXX Do PointerNonInterestBox here */ } #endif - if (sprite.win != prevSpriteWin) + if (pSprite->win != prevSpriteWin) { if (prevSpriteWin != NullWindow) { if (!xE) UpdateCurrentTimeIf(); - DoEnterLeaveEvents(prevSpriteWin, sprite.win, NotifyNormal); - } - PostNewCursor(); + DoEnterLeaveEvents(pDev, prevSpriteWin, pSprite->win, + NotifyNormal); + } + PostNewCursor(pDev); return FALSE; } return TRUE; @@ -2272,10 +2655,16 @@ CheckMotion(xEvent *xE) * Windows have restructured, we need to update the sprite position and the * sprite's cursor. */ -_X_EXPORT void +void WindowsRestructured(void) { - (void) CheckMotion((xEvent *)NULL); + DeviceIntPtr pDev = inputInfo.devices; + while(pDev) + { + if (DevHasCursor(pDev)) + CheckMotion((xEvent *)NULL, pDev); + pDev = pDev->next; + } } #ifdef PANORAMIX @@ -2287,81 +2676,174 @@ WindowsRestructured(void) void ReinitializeRootWindow(WindowPtr win, int xoff, int yoff) { GrabPtr grab; + DeviceIntPtr pDev; + SpritePtr pSprite; if (noPanoramiXExtension) return; - - sprite.hot.x -= xoff; - sprite.hot.y -= yoff; - - sprite.hotPhys.x -= xoff; - sprite.hotPhys.y -= yoff; - - sprite.hotLimits.x1 -= xoff; - sprite.hotLimits.y1 -= yoff; - sprite.hotLimits.x2 -= xoff; - sprite.hotLimits.y2 -= yoff; - - if (REGION_NOTEMPTY(sprite.screen, &sprite.Reg1)) - REGION_TRANSLATE(sprite.screen, &sprite.Reg1, xoff, yoff); - if (REGION_NOTEMPTY(sprite.screen, &sprite.Reg2)) - REGION_TRANSLATE(sprite.screen, &sprite.Reg2, xoff, yoff); - - /* FIXME: if we call ConfineCursorToWindow, must we do anything else? */ - if ((grab = inputInfo.pointer->grab) && grab->confineTo) { - if (grab->confineTo->drawable.pScreen != sprite.hotPhys.pScreen) - sprite.hotPhys.x = sprite.hotPhys.y = 0; - ConfineCursorToWindow(grab->confineTo, TRUE, TRUE); - } else - ConfineCursorToWindow(WindowTable[sprite.hotPhys.pScreen->myNum], - TRUE, FALSE); + + pDev = inputInfo.devices; + while(pDev) + { + if (DevHasCursor(pDev)) + { + pSprite = pDev->spriteInfo->sprite; + pSprite->hot.x -= xoff; + pSprite->hot.y -= yoff; + + pSprite->hotPhys.x -= xoff; + pSprite->hotPhys.y -= yoff; + + pSprite->hotLimits.x1 -= xoff; + pSprite->hotLimits.y1 -= yoff; + pSprite->hotLimits.x2 -= xoff; + pSprite->hotLimits.y2 -= yoff; + + if (REGION_NOTEMPTY(pSprite->screen, &pSprite->Reg1)) + REGION_TRANSLATE(pSprite->screen, &pSprite->Reg1, xoff, yoff); + if (REGION_NOTEMPTY(pSprite->screen, &pSprite->Reg2)) + REGION_TRANSLATE(pSprite->screen, &pSprite->Reg2, xoff, yoff); + + /* FIXME: if we call ConfineCursorToWindow, must we do anything else? */ + if ((grab = pDev->deviceGrab.grab) && grab->confineTo) { + if (grab->confineTo->drawable.pScreen + != pSprite->hotPhys.pScreen) + pSprite->hotPhys.x = pSprite->hotPhys.y = 0; + ConfineCursorToWindow(pDev, grab->confineTo, TRUE, TRUE); + } else + ConfineCursorToWindow( + pDev, + WindowTable[pSprite->hotPhys.pScreen->myNum], + TRUE, FALSE); + + } + pDev = pDev->next; + } } #endif /** - * Set the given window to sane values, display the cursor in the center of - * the screen. Called from main() with the root window on the first screen. + * Called from main() with the root window on the first screen. Used to do a + * lot more when MPX wasn't around yet. Things change. + * + * Should delete this now? -ds */ void DefineInitialRootWindow(WindowPtr win) { - ScreenPtr pScreen = win->drawable.pScreen; - - sprite.hotPhys.pScreen = pScreen; - sprite.hotPhys.x = pScreen->width / 2; - sprite.hotPhys.y = pScreen->height / 2; - sprite.hot = sprite.hotPhys; - sprite.hotLimits.x2 = pScreen->width; - sprite.hotLimits.y2 = pScreen->height; -#ifdef XEVIE - xeviewin = -#endif - sprite.win = win; - sprite.current = wCursor (win); - sprite.current->refcnt++; - spriteTraceGood = 1; - ROOT = win; - (*pScreen->CursorLimits) ( - pScreen, sprite.current, &sprite.hotLimits, &sprite.physLimits); - sprite.confined = FALSE; - (*pScreen->ConstrainCursor) (pScreen, &sprite.physLimits); - (*pScreen->SetCursorPosition) (pScreen, sprite.hot.x, sprite.hot.y, FALSE); - (*pScreen->DisplayCursor) (pScreen, sprite.current); +} + +/** + * Initialize a sprite for the given device and set it to some sane values. If + * the device already has a sprite alloc'd, don't realloc but just reset to + * default values. + * If a window is supplied, the sprite will be initialized with the window's + * cursor and positioned in the center of the window's screen. The root window + * is a good choice to pass in here. + * + * It's a good idea to call it only for pointer devices, unless you have a + * really talented keyboard. + * + * @param pDev The device to initialize. + * @param pWin The window where to generate the sprite in. + * + */ +void +InitializeSprite(DeviceIntPtr pDev, WindowPtr pWin) +{ + SpritePtr pSprite; + ScreenPtr pScreen; + + if (!pDev->spriteInfo->sprite) + { + DeviceIntPtr it; + + pDev->spriteInfo->sprite = (SpritePtr)xcalloc(1, sizeof(SpriteRec)); + if (!pDev->spriteInfo->sprite) + FatalError("InitializeSprite: failed to allocate sprite struct"); + + /* We may have paired another device with this device before our + * device had a actual sprite. We need to check for this and reset the + * sprite field for all paired devices. + * + * The VCK is always paired with the VCP before the VCP has a sprite. + */ + for (it = inputInfo.devices; it; it = it->next) + { + if (it->spriteInfo->paired == pDev) + it->spriteInfo->sprite = pDev->spriteInfo->sprite; + } + if (inputInfo.keyboard->spriteInfo->paired == pDev) + inputInfo.keyboard->spriteInfo->sprite = pDev->spriteInfo->sprite; + } + + pSprite = pDev->spriteInfo->sprite; + pDev->spriteInfo->spriteOwner = TRUE; + + pScreen = (pWin) ? pWin->drawable.pScreen : (ScreenPtr)NULL; + pSprite->hot.pScreen = pScreen; + pSprite->hotPhys.pScreen = pScreen; + if (pScreen) + { + pSprite->hotPhys.x = pScreen->width / 2; + pSprite->hotPhys.y = pScreen->height / 2; + pSprite->hotLimits.x2 = pScreen->width; + pSprite->hotLimits.y2 = pScreen->height; + } + pSprite->hot = pSprite->hotPhys; + pSprite->win = pWin; + + if (pWin) + { + pSprite->current = wCursor(pWin); + pSprite->current->refcnt++; + pSprite->spriteTrace = (WindowPtr *)xcalloc(1, 32*sizeof(WindowPtr)); + if (!pSprite->spriteTrace) + FatalError("Failed to allocate spriteTrace"); + pSprite->spriteTraceSize = 32; + + RootWindow(pDev) = pWin; + pSprite->spriteTraceGood = 1; + + pSprite->pEnqueueScreen = pScreen; + pSprite->pDequeueScreen = pSprite->pEnqueueScreen; + + } else { + pSprite->current = NullCursor; + pSprite->spriteTrace = NULL; + pSprite->spriteTraceSize = 0; + pSprite->spriteTraceGood = 0; + pSprite->pEnqueueScreen = screenInfo.screens[0]; + pSprite->pDequeueScreen = pSprite->pEnqueueScreen; + } + + if (pScreen) + { + (*pScreen->RealizeCursor) ( pDev, pScreen, pSprite->current); + (*pScreen->CursorLimits) ( pDev, pScreen, pSprite->current, + &pSprite->hotLimits, &pSprite->physLimits); + pSprite->confined = FALSE; + + (*pScreen->ConstrainCursor) (pDev, pScreen, + &pSprite->physLimits); + (*pScreen->SetCursorPosition) (pDev, pScreen, pSprite->hot.x, + pSprite->hot.y, + FALSE); + (*pScreen->DisplayCursor) (pDev, pScreen, pSprite->current); + } #ifdef PANORAMIX if(!noPanoramiXExtension) { - sprite.hotLimits.x1 = -panoramiXdataPtr[0].x; - sprite.hotLimits.y1 = -panoramiXdataPtr[0].y; - sprite.hotLimits.x2 = PanoramiXPixWidth - panoramiXdataPtr[0].x; - sprite.hotLimits.y2 = PanoramiXPixHeight - panoramiXdataPtr[0].y; - sprite.physLimits = sprite.hotLimits; - sprite.confineWin = NullWindow; -#ifdef SHAPE - sprite.hotShape = NullRegion; -#endif - sprite.screen = pScreen; - /* gotta UNINIT these someplace */ - REGION_NULL(pScreen, &sprite.Reg1); - REGION_NULL(pScreen, &sprite.Reg2); + pSprite->hotLimits.x1 = -panoramiXdataPtr[0].x; + pSprite->hotLimits.y1 = -panoramiXdataPtr[0].y; + pSprite->hotLimits.x2 = PanoramiXPixWidth - panoramiXdataPtr[0].x; + pSprite->hotLimits.y2 = PanoramiXPixHeight - panoramiXdataPtr[0].y; + pSprite->physLimits = pSprite->hotLimits; + pSprite->confineWin = NullWindow; + pSprite->hotShape = NullRegion; + pSprite->screen = pScreen; + /* gotta UNINIT these someplace */ + REGION_NULL(pScreen, &pSprite->Reg1); + REGION_NULL(pScreen, &pSprite->Reg2); } #endif } @@ -2382,41 +2864,46 @@ DefineInitialRootWindow(WindowPtr win) * @param win must be the new pScreen we are switching to. */ void -UpdateSpriteForScreen(ScreenPtr pScreen) +UpdateSpriteForScreen(DeviceIntPtr pDev, ScreenPtr pScreen) { + SpritePtr pSprite = NULL; WindowPtr win = NULL; if (!pScreen) return ; + + if (!pDev->spriteInfo->sprite) + return; + + pSprite = pDev->spriteInfo->sprite; + win = WindowTable[pScreen->myNum]; - sprite.hotPhys.pScreen = pScreen; - sprite.hot = sprite.hotPhys; - sprite.hotLimits.x2 = pScreen->width; - sprite.hotLimits.y2 = pScreen->height; -#ifdef XEVIE - xeviewin = -#endif - sprite.win = win; - sprite.current = wCursor (win); - sprite.current->refcnt++; - spriteTraceGood = 1; - ROOT = win; - (*pScreen->CursorLimits) (pScreen, - sprite.current, - &sprite.hotLimits, - &sprite.physLimits); - sprite.confined = FALSE; - (*pScreen->ConstrainCursor) (pScreen, &sprite.physLimits); - (*pScreen->DisplayCursor) (pScreen, sprite.current); + pSprite->hotPhys.pScreen = pScreen; + pSprite->hot = pSprite->hotPhys; + pSprite->hotLimits.x2 = pScreen->width; + pSprite->hotLimits.y2 = pScreen->height; + pSprite->win = win; + pSprite->current = wCursor (win); + pSprite->current->refcnt++; + pSprite->spriteTraceGood = 1; + pSprite->spriteTrace[0] = win; + (*pScreen->CursorLimits) (pDev, + pScreen, + pSprite->current, + &pSprite->hotLimits, + &pSprite->physLimits); + pSprite->confined = FALSE; + (*pScreen->ConstrainCursor) (pDev, pScreen, &pSprite->physLimits); + (*pScreen->DisplayCursor) (pDev, pScreen, pSprite->current); #ifdef PANORAMIX if(!noPanoramiXExtension) { - sprite.hotLimits.x1 = -panoramiXdataPtr[0].x; - sprite.hotLimits.y1 = -panoramiXdataPtr[0].y; - sprite.hotLimits.x2 = PanoramiXPixWidth - panoramiXdataPtr[0].x; - sprite.hotLimits.y2 = PanoramiXPixHeight - panoramiXdataPtr[0].y; - sprite.physLimits = sprite.hotLimits; - sprite.screen = pScreen; + pSprite->hotLimits.x1 = -panoramiXdataPtr[0].x; + pSprite->hotLimits.y1 = -panoramiXdataPtr[0].y; + pSprite->hotLimits.x2 = PanoramiXPixWidth - panoramiXdataPtr[0].x; + pSprite->hotLimits.y2 = PanoramiXPixHeight - panoramiXdataPtr[0].y; + pSprite->physLimits = pSprite->hotLimits; + pSprite->screen = pScreen; } #endif } @@ -2431,40 +2918,50 @@ UpdateSpriteForScreen(ScreenPtr pScreen) void WindowHasNewCursor(WindowPtr pWin) { - PostNewCursor(); + DeviceIntPtr pDev; + + for(pDev = inputInfo.devices; pDev; pDev = pDev->next) + if (DevHasCursor(pDev)) + PostNewCursor(pDev); } _X_EXPORT void -NewCurrentScreen(ScreenPtr newScreen, int x, int y) +NewCurrentScreen(DeviceIntPtr pDev, ScreenPtr newScreen, int x, int y) { - sprite.hotPhys.x = x; - sprite.hotPhys.y = y; + SpritePtr pSprite = pDev->spriteInfo->sprite; + + pSprite->hotPhys.x = x; + pSprite->hotPhys.y = y; #ifdef PANORAMIX if(!noPanoramiXExtension) { - sprite.hotPhys.x += panoramiXdataPtr[newScreen->myNum].x - + pSprite->hotPhys.x += panoramiXdataPtr[newScreen->myNum].x - panoramiXdataPtr[0].x; - sprite.hotPhys.y += panoramiXdataPtr[newScreen->myNum].y - + pSprite->hotPhys.y += panoramiXdataPtr[newScreen->myNum].y - panoramiXdataPtr[0].y; - if (newScreen != sprite.screen) { - sprite.screen = newScreen; + if (newScreen != pSprite->screen) { + pSprite->screen = newScreen; /* Make sure we tell the DDX to update its copy of the screen */ - if(sprite.confineWin) - XineramaConfineCursorToWindow(sprite.confineWin, TRUE); + if(pSprite->confineWin) + XineramaConfineCursorToWindow(pDev, + pSprite->confineWin, TRUE); else - XineramaConfineCursorToWindow(WindowTable[0], TRUE); - /* if the pointer wasn't confined, the DDX won't get + XineramaConfineCursorToWindow(pDev, WindowTable[0], TRUE); + /* if the pointer wasn't confined, the DDX won't get told of the pointer warp so we reposition it here */ if(!syncEvents.playingEvents) - (*sprite.screen->SetCursorPosition)(sprite.screen, - sprite.hotPhys.x + panoramiXdataPtr[0].x - - panoramiXdataPtr[sprite.screen->myNum].x, - sprite.hotPhys.y + panoramiXdataPtr[0].y - - panoramiXdataPtr[sprite.screen->myNum].y, FALSE); + (*pSprite->screen->SetCursorPosition)( + pDev, + pSprite->screen, + pSprite->hotPhys.x + panoramiXdataPtr[0].x - + panoramiXdataPtr[pSprite->screen->myNum].x, + pSprite->hotPhys.y + panoramiXdataPtr[0].y - + panoramiXdataPtr[pSprite->screen->myNum].y, FALSE); } - } else + } else #endif - if (newScreen != sprite.hotPhys.pScreen) - ConfineCursorToWindow(WindowTable[newScreen->myNum], TRUE, FALSE); + if (newScreen != pSprite->hotPhys.pScreen) + ConfineCursorToWindow(pDev, WindowTable[newScreen->myNum], + TRUE, FALSE); } #ifdef PANORAMIX @@ -2484,14 +2981,14 @@ XineramaPointInWindowIsVisible( if (POINT_IN_REGION(pScreen, &pWin->borderClip, x, y, &box)) return TRUE; - - if(!XineramaSetWindowPntrs(pWin)) return FALSE; - xoff = x + panoramiXdataPtr[0].x; - yoff = y + panoramiXdataPtr[0].y; + if(!XineramaSetWindowPntrs(inputInfo.pointer, pWin)) return FALSE; + + xoff = x + panoramiXdataPtr[0].x; + yoff = y + panoramiXdataPtr[0].y; for(i = 1; i < PanoramiXNumScreens; i++) { - pWin = sprite.windows[i]; + pWin = inputInfo.pointer->spriteInfo->sprite->windows[i]; pScreen = pWin->drawable.pScreen; x = xoff - panoramiXdataPtr[i].x; y = yoff - panoramiXdataPtr[i].y; @@ -2500,7 +2997,7 @@ XineramaPointInWindowIsVisible( && (!wInputShape(pWin) || POINT_IN_REGION(pWin->drawable.pScreen, wInputShape(pWin), - x - pWin->drawable.x, + x - pWin->drawable.x, y - pWin->drawable.y, &box))) return TRUE; @@ -2514,6 +3011,7 @@ XineramaWarpPointer(ClientPtr client) { WindowPtr dest = NULL; int x, y, rc; + SpritePtr pSprite = PickPointer(client)->spriteInfo->sprite; REQUEST(xWarpPointerReq); @@ -2523,15 +3021,15 @@ XineramaWarpPointer(ClientPtr client) if (rc != Success) return rc; } - x = sprite.hotPhys.x; - y = sprite.hotPhys.y; + x = pSprite->hotPhys.x; + y = pSprite->hotPhys.y; if (stuff->srcWid != None) { int winX, winY; - XID winID = stuff->srcWid; + XID winID = stuff->srcWid; WindowPtr source; - + rc = dixLookupWindow(&source, winID, client, DixReadAccess); if (rc != Success) return rc; @@ -2558,23 +3056,23 @@ XineramaWarpPointer(ClientPtr client) x -= panoramiXdataPtr[0].x; y -= panoramiXdataPtr[0].y; } - } + } x += stuff->dstX; y += stuff->dstY; - if (x < sprite.physLimits.x1) - x = sprite.physLimits.x1; - else if (x >= sprite.physLimits.x2) - x = sprite.physLimits.x2 - 1; - if (y < sprite.physLimits.y1) - y = sprite.physLimits.y1; - else if (y >= sprite.physLimits.y2) - y = sprite.physLimits.y2 - 1; - if (sprite.hotShape) - ConfineToShape(sprite.hotShape, &x, &y); + if (x < pSprite->physLimits.x1) + x = pSprite->physLimits.x1; + else if (x >= pSprite->physLimits.x2) + x = pSprite->physLimits.x2 - 1; + if (y < pSprite->physLimits.y1) + y = pSprite->physLimits.y1; + else if (y >= pSprite->physLimits.y2) + y = pSprite->physLimits.y2 - 1; + if (pSprite->hotShape) + ConfineToShape(PickPointer(client), pSprite->hotShape, &x, &y); - XineramaSetCursorPosition(x, y, TRUE); + XineramaSetCursorPosition(PickPointer(client), x, y, TRUE); return Success; } @@ -2593,9 +3091,12 @@ ProcWarpPointer(ClientPtr client) int x, y, rc; ScreenPtr newScreen; DeviceIntPtr dev; + SpritePtr pSprite; + REQUEST(xWarpPointerReq); REQUEST_SIZE_MATCH(xWarpPointerReq); + /* XXX XACE ??*/ for (dev = inputInfo.devices; dev; dev = dev->next) { if ((dev->coreEvents || dev == inputInfo.pointer) && dev->button) { rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixWriteAccess); @@ -2603,6 +3104,12 @@ ProcWarpPointer(ClientPtr client) return rc; } } + + dev = PickPointer(client); + if (dev->u.lastSlave) + dev = dev->u.lastSlave; + pSprite = dev->spriteInfo->sprite; + #ifdef PANORAMIX if(!noPanoramiXExtension) return XineramaWarpPointer(client); @@ -2613,22 +3120,22 @@ ProcWarpPointer(ClientPtr client) if (rc != Success) return rc; } - x = sprite.hotPhys.x; - y = sprite.hotPhys.y; + x = pSprite->hotPhys.x; + y = pSprite->hotPhys.y; if (stuff->srcWid != None) { int winX, winY; - XID winID = stuff->srcWid; + XID winID = stuff->srcWid; WindowPtr source; - + rc = dixLookupWindow(&source, winID, client, DixGetAttrAccess); if (rc != Success) return rc; winX = source->drawable.x; winY = source->drawable.y; - if (source->drawable.pScreen != sprite.hotPhys.pScreen || + if (source->drawable.pScreen != pSprite->hotPhys.pScreen || x < winX + stuff->srcX || y < winY + stuff->srcY || (stuff->srcWidth != 0 && @@ -2638,13 +3145,13 @@ ProcWarpPointer(ClientPtr client) !PointInWindowIsVisible(source, x, y)) return Success; } - if (dest) + if (dest) { x = dest->drawable.x; y = dest->drawable.y; newScreen = dest->drawable.pScreen; - } else - newScreen = sprite.hotPhys.pScreen; + } else + newScreen = pSprite->hotPhys.pScreen; x += stuff->dstX; y += stuff->dstY; @@ -2658,41 +3165,40 @@ ProcWarpPointer(ClientPtr client) else if (y >= newScreen->height) y = newScreen->height - 1; - if (newScreen == sprite.hotPhys.pScreen) - { - if (x < sprite.physLimits.x1) - x = sprite.physLimits.x1; - else if (x >= sprite.physLimits.x2) - x = sprite.physLimits.x2 - 1; - if (y < sprite.physLimits.y1) - y = sprite.physLimits.y1; - else if (y >= sprite.physLimits.y2) - y = sprite.physLimits.y2 - 1; -#if defined(SHAPE) - if (sprite.hotShape) - ConfineToShape(sprite.hotShape, &x, &y); -#endif - (*newScreen->SetCursorPosition)(newScreen, x, y, TRUE); + if (newScreen == pSprite->hotPhys.pScreen) + { + if (x < pSprite->physLimits.x1) + x = pSprite->physLimits.x1; + else if (x >= pSprite->physLimits.x2) + x = pSprite->physLimits.x2 - 1; + if (y < pSprite->physLimits.y1) + y = pSprite->physLimits.y1; + else if (y >= pSprite->physLimits.y2) + y = pSprite->physLimits.y2 - 1; + if (pSprite->hotShape) + ConfineToShape(dev, pSprite->hotShape, &x, &y); + (*newScreen->SetCursorPosition)(dev, newScreen, x, y, TRUE); } - else if (!PointerConfinedToScreen()) + else if (!PointerConfinedToScreen(dev)) { - NewCurrentScreen(newScreen, x, y); + NewCurrentScreen(dev, newScreen, x, y); } return Success; } -static Bool -BorderSizeNotEmpty(WindowPtr pWin) +static Bool +BorderSizeNotEmpty(DeviceIntPtr pDev, WindowPtr pWin) { - if(REGION_NOTEMPTY(sprite.hotPhys.pScreen, &pWin->borderSize)) + if(REGION_NOTEMPTY(pDev->spriteInfo->sprite->hotPhys.pScreen, &pWin->borderSize)) return TRUE; #ifdef PANORAMIX - if(!noPanoramiXExtension && XineramaSetWindowPntrs(pWin)) { + if(!noPanoramiXExtension && XineramaSetWindowPntrs(pDev, pWin)) { int i; for(i = 1; i < PanoramiXNumScreens; i++) { - if(REGION_NOTEMPTY(sprite.screen, &sprite.windows[i]->borderSize)) + if(REGION_NOTEMPTY(pDev->spriteInfo->sprite->screen, + &pDev->spriteInfo->sprite->windows[i]->borderSize)) return TRUE; } } @@ -2700,15 +3206,17 @@ BorderSizeNotEmpty(WindowPtr pWin) return FALSE; } -/** +/** * "CheckPassiveGrabsOnWindow" checks to see if the event passed in causes a - * passive grab set on the window to be activated. + * passive grab set on the window to be activated. * If a passive grab is activated, the event will be delivered to the client. - * + * * @param pWin The window that may be subject to a passive grab. * @param device Device that caused the event. * @param xE List of events (multiple ones for DeviceMotionNotify) - * @count number of elements in xE. + * @param count number of elements in xE. + * @param store The event that will be stored on the device (always XI) + * @param scount number of elements in store. */ static Bool @@ -2716,10 +3224,13 @@ CheckPassiveGrabsOnWindow( WindowPtr pWin, DeviceIntPtr device, xEvent *xE, - int count) + int count, + xEvent *store, + int scount) { GrabPtr grab = wPassiveGrabs(pWin); GrabRec tempGrab; + GrabInfoPtr grabinfo; xEvent *dxE; if (!grab) @@ -2730,39 +3241,49 @@ CheckPassiveGrabsOnWindow( tempGrab.detail.exact = xE->u.u.detail; tempGrab.detail.pMask = NULL; tempGrab.modifiersDetail.pMask = NULL; + tempGrab.next = NULL; for (; grab; grab = grab->next) { #ifdef XKB DeviceIntPtr gdev; - XkbSrvInfoPtr xkbi; + XkbSrvInfoPtr xkbi = NULL; gdev= grab->modifierDevice; - xkbi= gdev->key->xkbInfo; + if (grab->coreGrab) + { + if (IsPointerDevice(device)) + gdev = GetPairedDevice(device); + else + gdev = device; + } + if (gdev && gdev->key) + xkbi= gdev->key->xkbInfo; #endif tempGrab.modifierDevice = grab->modifierDevice; if ((device == grab->modifierDevice) && - ((xE->u.u.type == KeyPress) -#if defined(XINPUT) && defined(XKB) - || (xE->u.u.type == DeviceKeyPress) -#endif - )) + ((xE->u.u.type == KeyPress) || (xE->u.u.type == DeviceKeyPress))) tempGrab.modifiersDetail.exact = #ifdef XKB - (noXkbExtension?gdev->key->prev_state:xkbi->state.grab_mods); + (noXkbExtension) ? + ((gdev) ? gdev->key->prev_state : 0) : + ((xkbi) ? xkbi->state.grab_mods : 0); #else - grab->modifierDevice->key->prev_state; + (gdev) ? gdev->key->prev_state : 0; #endif else tempGrab.modifiersDetail.exact = #ifdef XKB - (noXkbExtension ? gdev->key->state : xkbi->state.grab_mods); + (noXkbExtension) ? + ((gdev) ? gdev->key->state : 0) : + ((xkbi) ? xkbi->state.grab_mods : 0); #else - grab->modifierDevice->key->state; + (gdev) ? gdev->key->state : 0; #endif - if (GrabMatchesSecond(&tempGrab, grab) && + /* ignore the device for core events when comparing grabs */ + if (GrabMatchesSecond(&tempGrab, grab, (xE->u.u.type < LASTEvent)) && (!grab->confineTo || - (grab->confineTo->realized && - BorderSizeNotEmpty(grab->confineTo)))) + (grab->confineTo->realized && + BorderSizeNotEmpty(device, grab->confineTo)))) { #ifdef XKB if (!noXkbExtension) { @@ -2771,29 +3292,70 @@ CheckPassiveGrabsOnWindow( tempGrab.modifiersDetail.exact&(~0x1f00); } #endif - (*device->ActivateGrab)(device, grab, currentTime, TRUE); - - FixUpEventFromWindow(xE, grab->window, None, TRUE); + grabinfo = &device->deviceGrab; + /* A passive grab may have been created for a different device + than it is assigned to at this point in time. + Update the grab's device and modifier device to reflect the + current state. + Since XGrabDeviceButton requires to specify the + modifierDevice explicitly, we don't override this choice. + */ + if (xE->u.u.type < LASTEvent) + { + grab->device = device; + grab->modifierDevice = GetPairedDevice(device); + } + + /* In some cases a passive core grab may exist, but the client + * already has a core grab on some other device. In this case we + * must not get the grab, otherwise we may never ungrab the + * device. + */ + + if (grab->coreGrab) + { + DeviceIntPtr other; + BOOL interfering = FALSE; + for (other = inputInfo.devices; other; other = other->next) + { + GrabPtr othergrab = other->deviceGrab.grab; + if (othergrab && othergrab->coreGrab && + SameClient(grab, rClient(othergrab)) && + ((IsPointerDevice(grab->device) && + IsPointerDevice(othergrab->device)) || + (IsKeyboardDevice(grab->device) && + IsKeyboardDevice(othergrab->device)))) + { + interfering = TRUE; + break; + } + } + if (interfering) + continue; + } + - (void) TryClientEvents(rClient(grab), xE, count, - filters[xE->u.u.type], - filters[xE->u.u.type], grab); + (*grabinfo->ActivateGrab)(device, grab, currentTime, TRUE); - if (device->sync.state == FROZEN_NO_EVENT) + FixUpEventFromWindow(device, xE, grab->window, None, TRUE); + + (void) TryClientEvents(rClient(grab), device, xE, count, + filters[device->id][xE->u.u.type], + filters[device->id][xE->u.u.type], grab); + + if (grabinfo->sync.state == FROZEN_NO_EVENT) { - if (device->sync.evcount < count) + if (grabinfo->sync.evcount < scount) { - Must_have_memory = TRUE; /* XXX */ - device->sync.event = (xEvent *)xrealloc(device->sync.event, - count* - sizeof(xEvent)); - Must_have_memory = FALSE; /* XXX */ + grabinfo->sync.event = xrealloc(grabinfo->sync.event, + scount * sizeof(xEvent)); } - device->sync.evcount = count; - for (dxE = device->sync.event; --count >= 0; dxE++, xE++) - *dxE = *xE; - device->sync.state = FROZEN_WITH_EVENT; - } + grabinfo->sync.evcount = scount; + /* we always store the XI event, never the core event */ + for (dxE = grabinfo->sync.event; --scount >= 0; dxE++, store++) + *dxE = *store; + grabinfo->sync.state = FROZEN_WITH_EVENT; + } return TRUE; } } @@ -2802,14 +3364,14 @@ CheckPassiveGrabsOnWindow( /** * CheckDeviceGrabs handles both keyboard and pointer events that may cause - * a passive grab to be activated. + * a passive grab to be activated. * * If the event is a keyboard event, the ancestors of the focus window are * traced down and tried to see if they have any passive grabs to be * activated. If the focus window itself is reached and it's descendants * contain the pointer, the ancestors of the window that the pointer is in * are then traced down starting at the focus window, otherwise no grabs are - * activated. + * activated. * If the event is a pointer event, the ancestors of the window that the * pointer is in are traced down starting at the root until CheckPassiveGrabs * causes a passive grab to activate or all the windows are @@ -2817,27 +3379,44 @@ CheckPassiveGrabsOnWindow( * * If a grab is activated, the event has been sent to the client already! * + * The event we pass in must always be an XI event. From this, we then emulate + * the core event and then check for grabs. + * * @param device The device that caused the event. - * @param xE The event to handle (most likely {Device}ButtonPress). + * @param xE The event to handle (Device{Button|Key}Press). * @param count Number of events in list. * @return TRUE if a grab has been activated or false otherwise. */ Bool -CheckDeviceGrabs(DeviceIntPtr device, xEvent *xE, +CheckDeviceGrabs(DeviceIntPtr device, xEvent *xE, int checkFirst, int count) { int i; WindowPtr pWin = NULL; - FocusClassPtr focus = device->focus; + FocusClassPtr focus = IsPointerEvent(xE) ? NULL : device->focus; + xEvent core; + BOOL sendCore = (device->isMaster && device->coreEvents); - if (((xE->u.u.type == ButtonPress) -#if defined(XINPUT) && defined(XKB) - || (xE->u.u.type == DeviceButtonPress) -#endif - ) && (device->button->buttonsDown != 1)) + if ((xE->u.u.type == DeviceButtonPress) + && (device->button->buttonsDown != 1)) return FALSE; + if (xE->u.u.type < EXTENSION_EVENT_BASE) + { + ErrorF("[dix] Core event passed into CheckDeviceGrabs.\n"); + return FALSE; + } + + + if (sendCore) + { + core = *xE; + core.u.u.type = XItoCoreType(xE->u.u.type); + if(!core.u.u.type) /* probably a Proximity event, can't grab for those */ + return FALSE; + } + i = checkFirst; if (focus) @@ -2845,22 +3424,28 @@ CheckDeviceGrabs(DeviceIntPtr device, xEvent *xE, for (; i < focus->traceGood; i++) { pWin = focus->trace[i]; + /* XI grabs have precendence */ if (pWin->optional && - CheckPassiveGrabsOnWindow(pWin, device, xE, count)) + (CheckPassiveGrabsOnWindow(pWin, device, xE, count, xE, count) + || (sendCore && CheckPassiveGrabsOnWindow(pWin, device, &core, + 1, xE, count)))) return TRUE; } - + if ((focus->win == NoneWin) || - (i >= spriteTraceGood) || - ((i > checkFirst) && (pWin != spriteTrace[i-1]))) + (i >= device->spriteInfo->sprite->spriteTraceGood) || + ((i > checkFirst) && + (pWin != device->spriteInfo->sprite->spriteTrace[i-1]))) return FALSE; } - for (; i < spriteTraceGood; i++) + for (; i < device->spriteInfo->sprite->spriteTraceGood; i++) { - pWin = spriteTrace[i]; + pWin = device->spriteInfo->sprite->spriteTrace[i]; if (pWin->optional && - CheckPassiveGrabsOnWindow(pWin, device, xE, count)) + (CheckPassiveGrabsOnWindow(pWin, device, xE, count, xE, count) || + (sendCore && CheckPassiveGrabsOnWindow(pWin, device, &core, 1, + xE, count)))) return TRUE; } @@ -2880,8 +3465,11 @@ CheckDeviceGrabs(DeviceIntPtr device, xEvent *xE, void DeliverFocusedEvent(DeviceIntPtr keybd, xEvent *xE, WindowPtr window, int count) { + DeviceIntPtr pointer; WindowPtr focus = keybd->focus->win; - int mskidx = 0; + BOOL sendCore = (keybd->isMaster && keybd->coreEvents); + xEvent core; + int deliveries = 0; if (focus == FollowKeyboardWin) focus = inputInfo.keyboard->focus->win; @@ -2897,14 +3485,32 @@ DeliverFocusedEvent(DeviceIntPtr keybd, xEvent *xE, WindowPtr window, int count) if (DeliverDeviceEvents(window, xE, NullGrab, focus, keybd, count)) return; } + pointer = GetPairedDevice(keybd); if (XaceHook(XACE_SEND_ACCESS, NULL, keybd, focus, xE, count)) return; + + if (sendCore) + { + core = *xE; + core.u.u.type = XItoCoreType(xE->u.u.type); + } + /* just deliver it to the focus window */ - FixUpEventFromWindow(xE, focus, None, FALSE); - if (xE->u.u.type & EXTENSION_EVENT_BASE) - mskidx = keybd->id; - (void)DeliverEventsToWindow(focus, xE, count, filters[xE->u.u.type], - NullGrab, mskidx); + FixUpEventFromWindow(pointer, xE, focus, None, FALSE); + deliveries = DeliverEventsToWindow(keybd, focus, xE, count, + filters[keybd->id][xE->u.u.type], + NullGrab, keybd->id); + + if (deliveries > 0) + return; + + if (sendCore && core.u.u.type) + { + FixUpEventFromWindow(keybd, &core, focus, None, FALSE); + deliveries = DeliverEventsToWindow(keybd, focus, &core, 1, + filters[keybd->id][xE->u.u.type], + NullGrab, 0); + } } /** @@ -2915,19 +3521,36 @@ DeliverFocusedEvent(DeviceIntPtr keybd, xEvent *xE, WindowPtr window, int count) * @param deactivateGrab True if the device's grab should be deactivated. */ void -DeliverGrabbedEvent(xEvent *xE, DeviceIntPtr thisDev, +DeliverGrabbedEvent(xEvent *xE, DeviceIntPtr thisDev, Bool deactivateGrab, int count) { - GrabPtr grab = thisDev->grab; + GrabPtr grab; + GrabInfoPtr grabinfo; int deliveries = 0; DeviceIntPtr dev; - xEvent *dxE; + xEvent *dxE, core; + SpritePtr pSprite = thisDev->spriteInfo->sprite; + BOOL sendCore = FALSE; + + grabinfo = &thisDev->deviceGrab; + grab = grabinfo->grab; if (grab->ownerEvents) { WindowPtr focus; - if (thisDev->focus) + /* Hack: Some pointer device have a focus class. So we need to check + * for the type of event, to see if we really want to deliver it to + * the focus window. For pointer events, the answer is no. + */ + if (xE->u.u.type == DeviceButtonPress || + xE->u.u.type == DeviceButtonRelease || + xE->u.u.type == DeviceMotionNotify || + xE->u.u.type == ProximityIn || + xE->u.u.type == ProximityOut) + { + focus = PointerRootWin; + } else if (thisDev->focus) { focus = thisDev->focus->win; if (focus == FollowKeyboardWin) @@ -2936,10 +3559,11 @@ DeliverGrabbedEvent(xEvent *xE, DeviceIntPtr thisDev, else focus = PointerRootWin; if (focus == PointerRootWin) - deliveries = DeliverDeviceEvents(sprite.win, xE, grab, NullWindow, - thisDev, count); - else if (focus && (focus == sprite.win || IsParent(focus, sprite.win))) - deliveries = DeliverDeviceEvents(sprite.win, xE, grab, focus, + deliveries = DeliverDeviceEvents(pSprite->win, xE, grab, + NullWindow, thisDev, count); + else if (focus && (focus == pSprite->win || + IsParent(focus, pSprite->win))) + deliveries = DeliverDeviceEvents(pSprite->win, xE, grab, focus, thisDev, count); else if (focus) deliveries = DeliverDeviceEvents(focus, xE, grab, focus, @@ -2947,28 +3571,65 @@ DeliverGrabbedEvent(xEvent *xE, DeviceIntPtr thisDev, } if (!deliveries) { - FixUpEventFromWindow(xE, grab->window, None, TRUE); - if (XaceHook(XACE_SEND_ACCESS, 0, thisDev, grab->window, xE, count) || - XaceHook(XACE_RECEIVE_ACCESS, rClient(grab), grab->window, xE, - count)) - deliveries = 1; /* don't send, but pretend we did */ - else - deliveries = TryClientEvents(rClient(grab), xE, count, - (Mask)grab->eventMask, - filters[xE->u.u.type], grab); - if (deliveries && (xE->u.u.type == MotionNotify -#ifdef XINPUT - || xE->u.u.type == DeviceMotionNotify -#endif - )) - thisDev->valuator->motionHintWindow = grab->window; + { + Mask mask = grab->eventMask; + + if (thisDev->isMaster) + { + core = *xE; + core.u.u.type = XItoCoreType(xE->u.u.type); + if(core.u.u.type) { + FixUpEventFromWindow(thisDev, &core, grab->window, + None, TRUE); + if (XaceHook(XACE_SEND_ACCESS, 0, thisDev, + grab->window, &core, 1) || + XaceHook(XACE_RECEIVE_ACCESS, rClient(grab), + grab->window, &core, 1)) + deliveries = 1; /* don't send, but pretend we did */ + else if (!IsInterferingGrab(rClient(grab), thisDev, + &core)) + { + deliveries = TryClientEvents(rClient(grab), thisDev, + &core, 1, mask, + filters[thisDev->id][core.u.u.type], + grab); + } + } + } else + { + /* try XI event */ + if (grabinfo->fromPassiveGrab && + grabinfo->implicitGrab && + (xE->u.u.type & EXTENSION_EVENT_BASE)) + mask = grab->deviceMask; + FixUpEventFromWindow(thisDev, xE, grab->window, + None, TRUE); + + if (XaceHook(XACE_SEND_ACCESS, 0, thisDev, + grab->window, xE, count) || + XaceHook(XACE_RECEIVE_ACCESS, rClient(grab), + grab->window, xE, count)) + deliveries = 1; /* don't send, but pretend we did */ + else + { + deliveries = + TryClientEvents(rClient(grab), thisDev, + xE, count, + mask, + filters[thisDev->id][xE->u.u.type], + grab); + } + + } + } + if (deliveries && (xE->u.u.type == MotionNotify + || xE->u.u.type == DeviceMotionNotify)) + thisDev->valuator->motionHintWindow = grab->window; } - if (deliveries && !deactivateGrab && (xE->u.u.type != MotionNotify -#ifdef XINPUT - && xE->u.u.type != DeviceMotionNotify -#endif - )) - switch (thisDev->sync.state) + if (deliveries && !deactivateGrab && + (xE->u.u.type != MotionNotify && xE->u.u.type != DeviceMotionNotify)) + { + switch (grabinfo->sync.state) { case FREEZE_BOTH_NEXT_EVENT: for (dev = inputInfo.devices; dev; dev = dev->next) @@ -2976,33 +3637,32 @@ DeliverGrabbedEvent(xEvent *xE, DeviceIntPtr thisDev, if (dev == thisDev) continue; FreezeThaw(dev, TRUE); - if ((dev->sync.state == FREEZE_BOTH_NEXT_EVENT) && - (CLIENT_BITS(dev->grab->resource) == - CLIENT_BITS(thisDev->grab->resource))) - dev->sync.state = FROZEN_NO_EVENT; + if ((grabinfo->sync.state == FREEZE_BOTH_NEXT_EVENT) && + (CLIENT_BITS(grab->resource) == + CLIENT_BITS(grab->resource))) + grabinfo->sync.state = FROZEN_NO_EVENT; else - dev->sync.other = thisDev->grab; + grabinfo->sync.other = grab; } /* fall through */ case FREEZE_NEXT_EVENT: - thisDev->sync.state = FROZEN_WITH_EVENT; + grabinfo->sync.state = FROZEN_WITH_EVENT; FreezeThaw(thisDev, TRUE); - if (thisDev->sync.evcount < count) + if (grabinfo->sync.evcount < count) { - Must_have_memory = TRUE; /* XXX */ - thisDev->sync.event = (xEvent *)xrealloc(thisDev->sync.event, - count*sizeof(xEvent)); - Must_have_memory = FALSE; /* XXX */ + grabinfo->sync.event = xrealloc(grabinfo->sync.event, + count * sizeof(xEvent)); } - thisDev->sync.evcount = count; - for (dxE = thisDev->sync.event; --count >= 0; dxE++, xE++) + grabinfo->sync.evcount = count; + for (dxE = grabinfo->sync.event; --count >= 0; dxE++, xE++) *dxE = *xE; break; } + } } /** - * Main keyboard event processing function for core keyboard events. + * Main keyboard event processing function for core keyboard events. * Updates the events fields from the current pointer state and delivers the * event. * @@ -3020,52 +3680,15 @@ ProcessKeyboardEvent (xEvent *xE, DeviceIntPtr keybd, int count) #endif { int key, bit; - BYTE *kptr; - int i; - CARD8 modifiers; - CARD16 mask; - GrabPtr grab = keybd->grab; + BYTE *kptr; + CARD8 modifiers; + GrabPtr grab; + GrabInfoPtr grabinfo; Bool deactivateGrab = FALSE; - KeyClassPtr keyc = keybd->key; -#ifdef XEVIE - static Window rootWin = 0; - - if(!xeviegrabState && xevieFlag && clients[xevieClientIndex] && - (xevieMask & xevieFilters[xE->u.u.type])) { - key = xE->u.u.detail; - kptr = &keyc->down[key >> 3]; - bit = 1 << (key & 7); - if((xE->u.u.type == KeyPress && (*kptr & bit)) || - (xE->u.u.type == KeyRelease && !(*kptr & bit))) - {} else { -#ifdef XKB - if(!noXkbExtension) - xevieKBEventSent = 1; -#endif - if(!xevieKBEventSent) - { - xeviekb = keybd; - if(!rootWin) { - rootWin = GetCurrentRootWindow()->drawable.id; - } - xE->u.keyButtonPointer.event = xeviewin->drawable.id; - xE->u.keyButtonPointer.root = rootWin; - xE->u.keyButtonPointer.child = (xeviewin->firstChild) ? xeviewin->firstChild-> -drawable.id:0; - xE->u.keyButtonPointer.rootX = xeviehot.x; - xE->u.keyButtonPointer.rootY = xeviehot.y; - xE->u.keyButtonPointer.state = keyc->state; - WriteToClient(clients[xevieClientIndex], sizeof(xEvent), (char *)xE); -#ifdef XKB - if(noXkbExtension) -#endif - return; - } else { - xevieKBEventSent = 0; - } - } - } -#endif + KeyClassPtr keyc = keybd->key; + + grabinfo = &keybd->deviceGrab; + grab = grabinfo->grab; if (!syncEvents.playingEvents) { @@ -3078,103 +3701,56 @@ drawable.id:0; CallCallbacks(&DeviceEventCallback, (pointer)&eventinfo); } } -#ifdef XEVIE - /* fix for bug5094030: don't change the state bit if the event is from XEvIE client */ - if(!(!xeviegrabState && xevieFlag && clients[xevieClientIndex] && - (xevieMask & xevieFilters[xE->u.u.type] -#ifdef XKB - && !noXkbExtension -#endif - ))) -#endif - XE_KBPTR.state = (keyc->state | inputInfo.pointer->button->state); - XE_KBPTR.rootX = sprite.hot.x; - XE_KBPTR.rootY = sprite.hot.y; + /* ProcessOtherEvent already updated the keyboard's state, so we need to + * access prev_state here! */ + XE_KBPTR.state = (keyc->prev_state | GetPairedDevice(keybd)->button->state); + XE_KBPTR.rootX = keybd->spriteInfo->sprite->hot.x; + XE_KBPTR.rootY = keybd->spriteInfo->sprite->hot.y; key = xE->u.u.detail; kptr = &keyc->down[key >> 3]; bit = 1 << (key & 7); modifiers = keyc->modifierMap[key]; -#if defined(XKB) && defined(XEVIE) - if(!noXkbExtension && !xeviegrabState && - xevieFlag && clients[xevieClientIndex] && - (xevieMask & xevieFilters[xE->u.u.type])) { - switch(xE->u.u.type) { - case KeyPress: *kptr &= ~bit; break; - case KeyRelease: *kptr |= bit; break; - } - } -#endif switch (xE->u.u.type) { - case KeyPress: - if (*kptr & bit) /* allow ddx to generate multiple downs */ - { - if (!modifiers) - { - xE->u.u.type = KeyRelease; - (*keybd->public.processInputProc)(xE, keybd, count); - xE->u.u.type = KeyPress; - /* release can have side effects, don't fall through */ - (*keybd->public.processInputProc)(xE, keybd, count); - } - return; - } - inputInfo.pointer->valuator->motionHintWindow = NullWindow; - *kptr |= bit; - keyc->prev_state = keyc->state; - for (i = 0, mask = 1; modifiers; i++, mask <<= 1) - { - if (mask & modifiers) - { - /* This key affects modifier "i" */ - keyc->modifierKeyCount[i]++; - keyc->state |= mask; - modifiers &= ~mask; - } - } + case KeyPress: + /* We MUST NOT change the device itself here. All device state + * changes must be performed in ProcessOtherEvents. We're dealing + * with the same device struct, so if we change it in POE and + * here, we've just screwed up the state by setting it twice. + * + * Devices may not send core events but always send XI events, so + * the state must be changed in POE, not here. + */ if (!grab && CheckDeviceGrabs(keybd, xE, 0, count)) { - keybd->activatingKey = key; + grabinfo->activatingKey = key; return; } break; - case KeyRelease: + case KeyRelease: if (!(*kptr & bit)) /* guard against duplicates */ return; - inputInfo.pointer->valuator->motionHintWindow = NullWindow; - *kptr &= ~bit; - keyc->prev_state = keyc->state; - for (i = 0, mask = 1; modifiers; i++, mask <<= 1) - { - if (mask & modifiers) { - /* This key affects modifier "i" */ - if (--keyc->modifierKeyCount[i] <= 0) { - keyc->state &= ~mask; - keyc->modifierKeyCount[i] = 0; - } - modifiers &= ~mask; - } - } - if (keybd->fromPassiveGrab && (key == keybd->activatingKey)) + /* No device state changes, see comment for KeyPress */ + if (grabinfo->fromPassiveGrab && (key == grabinfo->activatingKey)) deactivateGrab = TRUE; break; - default: + default: FatalError("Impossible keyboard event"); } if (grab) DeliverGrabbedEvent(xE, keybd, deactivateGrab, count); else - DeliverFocusedEvent(keybd, xE, sprite.win, count); + DeliverFocusedEvent(keybd, xE, keybd->spriteInfo->sprite->win, count); if (deactivateGrab) - (*keybd->DeactivateGrab)(keybd); + (*grabinfo->DeactivateGrab)(keybd); XaceHook(XACE_KEY_AVAIL, xE, keybd, count); } #ifdef XKB /* This function is used to set the key pressed or key released state - - this is only used when the pressing of keys does not cause + this is only used when the pressing of keys does not cause the device's processInputProc to be called, as in for example Mouse Keys. */ void @@ -3204,8 +3780,8 @@ FixKeyState (xEvent *xE, DeviceIntPtr keybd) } #endif -/** - * Main pointer event processing function for core pointer events. +/** + * Main pointer event processing function for core pointer events. * For motion events: update the sprite. * For all other events: Update the event fields based on the current sprite * state. @@ -3223,23 +3799,13 @@ CoreProcessPointerEvent (xEvent *xE, DeviceIntPtr mouse, int count) ProcessPointerEvent (xEvent *xE, DeviceIntPtr mouse, int count) #endif { - GrabPtr grab = mouse->grab; + GrabPtr grab = mouse->deviceGrab.grab; Bool deactivateGrab = FALSE; - ButtonClassPtr butc = mouse->button; + ButtonClassPtr butc = mouse->button; + SpritePtr pSprite = mouse->spriteInfo->sprite; + #ifdef XKB - XkbSrvInfoPtr xkbi= inputInfo.keyboard->key->xkbInfo; -#endif -#ifdef XEVIE - if(xevieFlag && clients[xevieClientIndex] && !xeviegrabState && - (xevieMask & xevieFilters[xE->u.u.type])) { - if(xevieEventSent) - xevieEventSent = 0; - else { - xeviemouse = mouse; - WriteToClient(clients[xevieClientIndex], sizeof(xEvent), (char *)xE); - return; - } - } + XkbSrvInfoPtr xkbi= GetPairedDevice(mouse)->key->xkbInfo; #endif if (!syncEvents.playingEvents) @@ -3261,69 +3827,59 @@ ProcessPointerEvent (xEvent *xE, DeviceIntPtr mouse, int count) /* see comment in EnqueueEvents regarding the next three lines */ if (xE->u.u.type == MotionNotify) XE_KBPTR.root = - WindowTable[sprite.hotPhys.pScreen->myNum]->drawable.id; + WindowTable[pSprite->hotPhys.pScreen->myNum]->drawable.id; eventinfo.events = xE; eventinfo.count = count; CallCallbacks(&DeviceEventCallback, (pointer)&eventinfo); } } + /* We need to call CheckMotion for each event. It doesn't really give us + any benefit for relative devices, but absolute devices may not send + button events to the right position otherwise. */ + if (!CheckMotion(xE, mouse) && xE->u.u.type == MotionNotify) + return; if (xE->u.u.type != MotionNotify) { int key; - BYTE *kptr; - int bit; - XE_KBPTR.rootX = sprite.hot.x; - XE_KBPTR.rootY = sprite.hot.y; + XE_KBPTR.rootX = pSprite->hot.x; + XE_KBPTR.rootY = pSprite->hot.y; key = xE->u.u.detail; - kptr = &butc->down[key >> 3]; - bit = 1 << (key & 7); switch (xE->u.u.type) { - case ButtonPress: - mouse->valuator->motionHintWindow = NullWindow; - if (!(*kptr & bit)) - butc->buttonsDown++; - butc->motionMask = ButtonMotionMask; - *kptr |= bit; + case ButtonPress: + /* + * We rely on the fact that ButtonMotionMask is the same as + * DeviceButtonMotionMask, so setting the motionMask + * to this value ensures correctness for both XI and core events. + */ if (xE->u.u.detail == 0) return; - if (xE->u.u.detail <= 5) - butc->state |= (Button1Mask >> 1) << xE->u.u.detail; - filters[MotionNotify] = Motion_Filter(butc); + filters[mouse->id][Motion_Filter(butc)] = MotionNotify; if (!grab) if (CheckDeviceGrabs(mouse, xE, 0, count)) return; break; - case ButtonRelease: - mouse->valuator->motionHintWindow = NullWindow; - if (*kptr & bit) - --butc->buttonsDown; - if (!butc->buttonsDown) - butc->motionMask = 0; - *kptr &= ~bit; + case ButtonRelease: if (xE->u.u.detail == 0) return; - if (xE->u.u.detail <= 5) - butc->state &= ~((Button1Mask >> 1) << xE->u.u.detail); - filters[MotionNotify] = Motion_Filter(butc); - if (!butc->state && mouse->fromPassiveGrab) + filters[mouse->id][Motion_Filter(butc)] = MotionNotify; + if (!butc->buttonsDown && mouse->deviceGrab.fromPassiveGrab) deactivateGrab = TRUE; break; - default: - FatalError("bogus pointer event from ddx: %d", xE->u.u.type); + default: + FatalError("bogus pointer event from ddx. Type %d\n", xE->u.u.type); } } - else if (!CheckMotion(xE)) - return; + if (grab) DeliverGrabbedEvent(xE, mouse, deactivateGrab, count); else - DeliverDeviceEvents(sprite.win, xE, NullGrab, NullWindow, + DeliverDeviceEvents(pSprite->win, xE, NullGrab, NullWindow, mouse, count); if (deactivateGrab) - (*mouse->DeactivateGrab)(mouse); + (*mouse->deviceGrab.DeactivateGrab)(mouse); } #define AtMostOneClient \ @@ -3418,6 +3974,7 @@ EventSelectForWindow(WindowPtr pWin, ClientPtr client, Mask mask) { Mask check; OtherClients * others; + DeviceIntPtr dev; int rc; if (mask & ~AllEventMasks) @@ -3483,18 +4040,21 @@ EventSelectForWindow(WindowPtr pWin, ClientPtr client, Mask mask) if (!AddResource(others->resource, RT_OTHERCLIENT, (pointer)pWin)) return BadAlloc; } -maskSet: - if ((inputInfo.pointer->valuator->motionHintWindow == pWin) && - (mask & PointerMotionHintMask) && - !(check & PointerMotionHintMask) && - !inputInfo.pointer->grab) - inputInfo.pointer->valuator->motionHintWindow = NullWindow; +maskSet: + if ((mask & PointerMotionHintMask) && !(check & PointerMotionHintMask)) + { + for (dev = inputInfo.devices; dev; dev = dev->next) + { + if (dev->valuator && dev->valuator->motionHintWindow == pWin) + dev->valuator->motionHintWindow = NullWindow; + } + } RecalculateDeliverableEvents(pWin); return Success; } int -EventSuppressForWindow(WindowPtr pWin, ClientPtr client, +EventSuppressForWindow(WindowPtr pWin, ClientPtr client, Mask mask, Bool *checkOptional) { int i, free; @@ -3550,37 +4110,26 @@ EventSuppressForWindow(WindowPtr pWin, ClientPtr client, } /** - * @return The window that is the first ancestor of both a and b. + * Assembles an EnterNotify or LeaveNotify and sends it event to the client. + * Uses the paired keyboard to get some additional information. */ -static WindowPtr -CommonAncestor( - WindowPtr a, - WindowPtr b) -{ - for (b = b->parent; b; b = b->parent) - if (IsParent(b, a)) return b; - return NullWindow; -} - -/** - * Assembles an EnterNotify or LeaveNotify and sends it event to the client. - * The core devices are used to fill in the event fields. - */ -static void -EnterLeaveEvent( +void +CoreEnterLeaveEvent( + DeviceIntPtr mouse, int type, int mode, int detail, WindowPtr pWin, Window child) { - xEvent event; - DeviceIntPtr keybd = inputInfo.keyboard; + xEvent event; WindowPtr focus; - DeviceIntPtr mouse = inputInfo.pointer; - GrabPtr grab = mouse->grab; + DeviceIntPtr keybd; + GrabPtr grab = mouse->deviceGrab.grab; Mask mask; + keybd = GetPairedDevice(mouse); + if ((pWin == mouse->valuator->motionHintWindow) && (detail != NotifyInferior)) mouse->valuator->motionHintWindow = NullWindow; @@ -3594,345 +4143,105 @@ EnterLeaveEvent( { mask = pWin->eventMask | wOtherEventMasks(pWin); } - if (mask & filters[type]) - { - event.u.u.type = type; - event.u.u.detail = detail; - event.u.enterLeave.time = currentTime.milliseconds; - event.u.enterLeave.rootX = sprite.hot.x; - event.u.enterLeave.rootY = sprite.hot.y; - /* Counts on the same initial structure of crossing & button events! */ - FixUpEventFromWindow(&event, pWin, None, FALSE); - /* Enter/Leave events always set child */ - event.u.enterLeave.child = child; - event.u.enterLeave.flags = event.u.keyButtonPointer.sameScreen ? - ELFlagSameScreen : 0; + + event.u.u.type = type; + event.u.u.detail = detail; + event.u.enterLeave.time = currentTime.milliseconds; + event.u.enterLeave.rootX = mouse->spriteInfo->sprite->hot.x; + event.u.enterLeave.rootY = mouse->spriteInfo->sprite->hot.y; + /* Counts on the same initial structure of crossing & button events! */ + FixUpEventFromWindow(mouse, &event, pWin, None, FALSE); + /* Enter/Leave events always set child */ + event.u.enterLeave.child = child; + event.u.enterLeave.flags = event.u.keyButtonPointer.sameScreen ? + ELFlagSameScreen : 0; #ifdef XKB - if (!noXkbExtension) { - event.u.enterLeave.state = mouse->button->state & 0x1f00; - event.u.enterLeave.state |= - XkbGrabStateFromRec(&keybd->key->xkbInfo->state); - } else + if (!noXkbExtension) { + event.u.enterLeave.state = mouse->button->state & 0x1f00; + if (keybd) + event.u.enterLeave.state |= + XkbGrabStateFromRec(&keybd->key->xkbInfo->state); + } else #endif - event.u.enterLeave.state = keybd->key->state | mouse->button->state; - event.u.enterLeave.mode = mode; - focus = keybd->focus->win; - if ((focus != NoneWin) && - ((pWin == focus) || (focus == PointerRootWin) || - IsParent(focus, pWin))) - event.u.enterLeave.flags |= ELFlagFocus; - if (grab) - (void)TryClientEvents(rClient(grab), &event, 1, mask, - filters[type], grab); - else - (void)DeliverEventsToWindow(pWin, &event, 1, filters[type], - NullGrab, 0); - } - if ((type == EnterNotify) && (mask & KeymapStateMask)) { - xKeymapEvent ke; - ClientPtr client = grab ? rClient(grab) - : clients[CLIENT_ID(pWin->drawable.id)]; - if (XaceHook(XACE_DEVICE_ACCESS, client, keybd, DixReadAccess)) - bzero((char *)&ke.map[0], 31); - else - memmove((char *)&ke.map[0], (char *)&keybd->key->down[1], 31); - - ke.type = KeymapNotify; - if (grab) - (void)TryClientEvents(rClient(grab), (xEvent *)&ke, 1, mask, - KeymapStateMask, grab); - else - (void)DeliverEventsToWindow(pWin, (xEvent *)&ke, 1, - KeymapStateMask, NullGrab, 0); + event.u.enterLeave.state = (keybd) ? keybd->key->state : 0; + event.u.enterLeave.state |= mouse->button->state; } -} - -/** - * Send enter notifies to all parent windows up to ancestor. - * This function recurses. - */ -static void -EnterNotifies(WindowPtr ancestor, WindowPtr child, int mode, int detail) -{ - WindowPtr parent = child->parent; - - if (ancestor == parent) - return; - EnterNotifies(ancestor, parent, mode, detail); - EnterLeaveEvent(EnterNotify, mode, detail, parent, child->drawable.id); -} - + event.u.enterLeave.mode = mode; + focus = (keybd) ? keybd->focus->win : None; + if ((focus != NoneWin) && + ((pWin == focus) || (focus == PointerRootWin) || + IsParent(focus, pWin))) + event.u.enterLeave.flags |= ELFlagFocus; -/** - * Send leave notifies to all parent windows up to ancestor. - * This function recurses. - */ -static void -LeaveNotifies(WindowPtr child, WindowPtr ancestor, int mode, int detail) -{ - WindowPtr pWin; - - if (ancestor == child) - return; - for (pWin = child->parent; pWin != ancestor; pWin = pWin->parent) + if ((mask & filters[mouse->id][type])) { - EnterLeaveEvent(LeaveNotify, mode, detail, pWin, child->drawable.id); - child = pWin; + if (grab) + TryClientEvents(rClient(grab), mouse, &event, 1, mask, + filters[mouse->id][type], grab); + else + DeliverEventsToWindow(mouse, pWin, &event, 1, + filters[mouse->id][type], NullGrab, 0); } -} -/** - * Figure out if enter/leave events are necessary and send them to the - * appropriate windows. - * - * @param fromWin Window the sprite moved out of. - * @param toWin Window the sprite moved into. - */ -static void -DoEnterLeaveEvents(WindowPtr fromWin, WindowPtr toWin, int mode) -{ - if (fromWin == toWin) - return; - if (IsParent(fromWin, toWin)) - { - EnterLeaveEvent(LeaveNotify, mode, NotifyInferior, fromWin, None); - EnterNotifies(fromWin, toWin, mode, NotifyVirtual); - EnterLeaveEvent(EnterNotify, mode, NotifyAncestor, toWin, None); - } - else if (IsParent(toWin, fromWin)) + if ((type == EnterNotify) && (mask & KeymapStateMask)) { - EnterLeaveEvent(LeaveNotify, mode, NotifyAncestor, fromWin, None); - LeaveNotifies(fromWin, toWin, mode, NotifyVirtual); - EnterLeaveEvent(EnterNotify, mode, NotifyInferior, toWin, None); - } - else - { /* neither fromWin nor toWin is descendent of the other */ - WindowPtr common = CommonAncestor(toWin, fromWin); - /* common == NullWindow ==> different screens */ - EnterLeaveEvent(LeaveNotify, mode, NotifyNonlinear, fromWin, None); - LeaveNotifies(fromWin, common, mode, NotifyNonlinearVirtual); - EnterNotifies(common, toWin, mode, NotifyNonlinearVirtual); - EnterLeaveEvent(EnterNotify, mode, NotifyNonlinear, toWin, None); + xKeymapEvent ke; + ClientPtr client = grab ? rClient(grab) + : clients[CLIENT_ID(pWin->drawable.id)]; + if (XaceHook(XACE_DEVICE_ACCESS, client, keybd, DixReadAccess)) + bzero((char *)&ke.map[0], 31); + else + memmove((char *)&ke.map[0], (char *)&keybd->key->down[1], 31); + + ke.type = KeymapNotify; + if (grab) + TryClientEvents(rClient(grab), keybd, (xEvent *)&ke, 1, + mask, KeymapStateMask, grab); + else + DeliverEventsToWindow(mouse, pWin, (xEvent *)&ke, 1, + KeymapStateMask, NullGrab, 0); } } -static void -FocusEvent(DeviceIntPtr dev, int type, int mode, int detail, WindowPtr pWin) +void +CoreFocusEvent(DeviceIntPtr dev, int type, int mode, int detail, WindowPtr pWin) { xEvent event; -#ifdef XINPUT - if (dev != inputInfo.keyboard) - { - DeviceFocusEvent(dev, type, mode, detail, pWin); - return; - } -#endif event.u.focus.mode = mode; event.u.u.type = type; event.u.u.detail = detail; event.u.focus.window = pWin->drawable.id; - (void)DeliverEventsToWindow(pWin, &event, 1, filters[type], NullGrab, - 0); + (void)DeliverEventsToWindow(dev, pWin, &event, 1, + filters[dev->id][type], NullGrab, 0); if ((type == FocusIn) && - ((pWin->eventMask | wOtherEventMasks(pWin)) & KeymapStateMask)) + ((pWin->eventMask | wOtherEventMasks(pWin)) & KeymapStateMask)) { - xKeymapEvent ke; - ClientPtr client = clients[CLIENT_ID(pWin->drawable.id)]; - if (XaceHook(XACE_DEVICE_ACCESS, client, dev, DixReadAccess)) - bzero((char *)&ke.map[0], 31); - else - memmove((char *)&ke.map[0], (char *)&dev->key->down[1], 31); + xKeymapEvent ke; + ClientPtr client = clients[CLIENT_ID(pWin->drawable.id)]; + if (XaceHook(XACE_DEVICE_ACCESS, client, dev, DixReadAccess)) + bzero((char *)&ke.map[0], 31); + else + memmove((char *)&ke.map[0], (char *)&dev->key->down[1], 31); - ke.type = KeymapNotify; - (void)DeliverEventsToWindow(pWin, (xEvent *)&ke, 1, - KeymapStateMask, NullGrab, 0); - } -} - - /* - * recursive because it is easier - * no-op if child not descended from ancestor - */ -static Bool -FocusInEvents( - DeviceIntPtr dev, - WindowPtr ancestor, WindowPtr child, WindowPtr skipChild, - int mode, int detail, - Bool doAncestor) -{ - if (child == NullWindow) - return ancestor == NullWindow; - if (ancestor == child) - { - if (doAncestor) - FocusEvent(dev, FocusIn, mode, detail, child); - return TRUE; - } - if (FocusInEvents(dev, ancestor, child->parent, skipChild, mode, detail, - doAncestor)) - { - if (child != skipChild) - FocusEvent(dev, FocusIn, mode, detail, child); - return TRUE; - } - return FALSE; -} - -/* dies horribly if ancestor is not an ancestor of child */ -static void -FocusOutEvents( - DeviceIntPtr dev, - WindowPtr child, WindowPtr ancestor, - int mode, int detail, - Bool doAncestor) -{ - WindowPtr pWin; - - for (pWin = child; pWin != ancestor; pWin = pWin->parent) - FocusEvent(dev, FocusOut, mode, detail, pWin); - if (doAncestor) - FocusEvent(dev, FocusOut, mode, detail, ancestor); -} - -void -DoFocusEvents(DeviceIntPtr dev, WindowPtr fromWin, WindowPtr toWin, int mode) -{ - int out, in; /* for holding details for to/from - PointerRoot/None */ - int i; - - if (fromWin == toWin) - return; - out = (fromWin == NoneWin) ? NotifyDetailNone : NotifyPointerRoot; - in = (toWin == NoneWin) ? NotifyDetailNone : NotifyPointerRoot; - /* wrong values if neither, but then not referenced */ - - if ((toWin == NullWindow) || (toWin == PointerRootWin)) - { - if ((fromWin == NullWindow) || (fromWin == PointerRootWin)) - { - if (fromWin == PointerRootWin) - FocusOutEvents(dev, sprite.win, ROOT, mode, NotifyPointer, - TRUE); - /* Notify all the roots */ -#ifdef PANORAMIX - if ( !noPanoramiXExtension ) - FocusEvent(dev, FocusOut, mode, out, WindowTable[0]); - else -#endif - for (i=0; i<screenInfo.numScreens; i++) - FocusEvent(dev, FocusOut, mode, out, WindowTable[i]); - } - else - { - if (IsParent(fromWin, sprite.win)) - FocusOutEvents(dev, sprite.win, fromWin, mode, NotifyPointer, - FALSE); - FocusEvent(dev, FocusOut, mode, NotifyNonlinear, fromWin); - /* next call catches the root too, if the screen changed */ - FocusOutEvents(dev, fromWin->parent, NullWindow, mode, - NotifyNonlinearVirtual, FALSE); - } - /* Notify all the roots */ -#ifdef PANORAMIX - if ( !noPanoramiXExtension ) - FocusEvent(dev, FocusIn, mode, in, WindowTable[0]); - else -#endif - for (i=0; i<screenInfo.numScreens; i++) - FocusEvent(dev, FocusIn, mode, in, WindowTable[i]); - if (toWin == PointerRootWin) - (void)FocusInEvents(dev, ROOT, sprite.win, NullWindow, mode, - NotifyPointer, TRUE); - } - else - { - if ((fromWin == NullWindow) || (fromWin == PointerRootWin)) - { - if (fromWin == PointerRootWin) - FocusOutEvents(dev, sprite.win, ROOT, mode, NotifyPointer, - TRUE); -#ifdef PANORAMIX - if ( !noPanoramiXExtension ) - FocusEvent(dev, FocusOut, mode, out, WindowTable[0]); - else -#endif - for (i=0; i<screenInfo.numScreens; i++) - FocusEvent(dev, FocusOut, mode, out, WindowTable[i]); - if (toWin->parent != NullWindow) - (void)FocusInEvents(dev, ROOT, toWin, toWin, mode, - NotifyNonlinearVirtual, TRUE); - FocusEvent(dev, FocusIn, mode, NotifyNonlinear, toWin); - if (IsParent(toWin, sprite.win)) - (void)FocusInEvents(dev, toWin, sprite.win, NullWindow, mode, - NotifyPointer, FALSE); - } - else - { - if (IsParent(toWin, fromWin)) - { - FocusEvent(dev, FocusOut, mode, NotifyAncestor, fromWin); - FocusOutEvents(dev, fromWin->parent, toWin, mode, - NotifyVirtual, FALSE); - FocusEvent(dev, FocusIn, mode, NotifyInferior, toWin); - if ((IsParent(toWin, sprite.win)) && - (sprite.win != fromWin) && - (!IsParent(fromWin, sprite.win)) && - (!IsParent(sprite.win, fromWin))) - (void)FocusInEvents(dev, toWin, sprite.win, NullWindow, - mode, NotifyPointer, FALSE); - } - else - if (IsParent(fromWin, toWin)) - { - if ((IsParent(fromWin, sprite.win)) && - (sprite.win != fromWin) && - (!IsParent(toWin, sprite.win)) && - (!IsParent(sprite.win, toWin))) - FocusOutEvents(dev, sprite.win, fromWin, mode, - NotifyPointer, FALSE); - FocusEvent(dev, FocusOut, mode, NotifyInferior, fromWin); - (void)FocusInEvents(dev, fromWin, toWin, toWin, mode, - NotifyVirtual, FALSE); - FocusEvent(dev, FocusIn, mode, NotifyAncestor, toWin); - } - else - { - /* neither fromWin or toWin is child of other */ - WindowPtr common = CommonAncestor(toWin, fromWin); - /* common == NullWindow ==> different screens */ - if (IsParent(fromWin, sprite.win)) - FocusOutEvents(dev, sprite.win, fromWin, mode, - NotifyPointer, FALSE); - FocusEvent(dev, FocusOut, mode, NotifyNonlinear, fromWin); - if (fromWin->parent != NullWindow) - FocusOutEvents(dev, fromWin->parent, common, mode, - NotifyNonlinearVirtual, FALSE); - if (toWin->parent != NullWindow) - (void)FocusInEvents(dev, common, toWin, toWin, mode, - NotifyNonlinearVirtual, FALSE); - FocusEvent(dev, FocusIn, mode, NotifyNonlinear, toWin); - if (IsParent(toWin, sprite.win)) - (void)FocusInEvents(dev, toWin, sprite.win, NullWindow, - mode, NotifyPointer, FALSE); - } - } + ke.type = KeymapNotify; + (void)DeliverEventsToWindow(dev, pWin, (xEvent *)&ke, 1, + KeymapStateMask, NullGrab, 0); } } /** * Set the input focus to the given window. Subsequent keyboard events will be * delivered to the given window. - * + * * Usually called from ProcSetInputFocus as result of a client request. If so, * the device is the inputInfo.keyboard. * If called from ProcXSetInputFocus as result of a client xinput request, the * device is set to the device specified by the client. * * @param client Client that requested input focus change. - * @param dev Focus device. + * @param dev Focus device. * @param focusID The window to obtain the focus. Can be PointerRoot or None. * @param revertTo Specifies where the focus reverts to when window becomes * unviewable. @@ -3952,6 +4261,8 @@ SetInputFocus( WindowPtr focusWin; int mode, rc; TimeStamp time; + DeviceIntPtr keybd; /* used for FollowKeyboard or FollowKeyboardWin */ + UpdateCurrentTime(); if ((revertTo != RevertToParent) && @@ -3963,15 +4274,23 @@ SetInputFocus( return BadValue; } time = ClientTimeToServerTime(ctime); + + if (IsKeyboardDevice(dev)) + keybd = dev; + else + keybd = GetPairedDevice(dev); + if ((focusID == None) || (focusID == PointerRoot)) focusWin = (WindowPtr)(long)focusID; else if ((focusID == FollowKeyboard) && followOK) - focusWin = inputInfo.keyboard->focus->win; + { + focusWin = keybd->focus->win; + } else { rc = dixLookupWindow(&focusWin, focusID, client, DixSetAttrAccess); if (rc != Success) return rc; - /* It is a match error to try to set the input focus to an + /* It is a match error to try to set the input focus to an unviewable window. */ if(!focusWin->realized) return(BadMatch); @@ -3984,9 +4303,9 @@ SetInputFocus( if ((CompareTimeStamps(time, currentTime) == LATER) || (CompareTimeStamps(time, focus->time) == EARLIER)) return Success; - mode = (dev->grab) ? NotifyWhileGrabbed : NotifyNormal; + mode = (dev->deviceGrab.grab) ? NotifyWhileGrabbed : NotifyNormal; if (focus->win == FollowKeyboardWin) - DoFocusEvents(dev, inputInfo.keyboard->focus->win, focusWin, mode); + DoFocusEvents(dev, keybd->focus->win, focusWin, mode); else DoFocusEvents(dev, focus->win, focusWin, mode); focus->time = time; @@ -4006,14 +4325,11 @@ SetInputFocus( if (depth > focus->traceSize) { focus->traceSize = depth+1; - Must_have_memory = TRUE; /* XXX */ - focus->trace = (WindowPtr *)xrealloc(focus->trace, - focus->traceSize * - sizeof(WindowPtr)); - Must_have_memory = FALSE; /* XXX */ + focus->trace = xrealloc(focus->trace, + focus->traceSize * sizeof(WindowPtr)); } focus->traceGood = depth; - for (pWin = focusWin, depth--; pWin; pWin = pWin->parent, depth--) + for (pWin = focusWin, depth--; pWin; pWin = pWin->parent, depth--) focus->trace[depth] = pWin; } return Success; @@ -4028,31 +4344,32 @@ int ProcSetInputFocus(client) ClientPtr client; { + DeviceIntPtr kbd = PickKeyboard(client); REQUEST(xSetInputFocusReq); REQUEST_SIZE_MATCH(xSetInputFocusReq); - return SetInputFocus(client, inputInfo.keyboard, stuff->focus, + return SetInputFocus(client, kbd, stuff->focus, stuff->revertTo, stuff->time, FALSE); } /** * Server-side protocol handling for GetInputFocus request. - * - * Sends the current input focus for the virtual core keyboard back to the + * + * Sends the current input focus for the client's keyboard back to the * client. */ int ProcGetInputFocus(ClientPtr client) { + DeviceIntPtr kbd = PickKeyboard(client); xGetInputFocusReply rep; - FocusClassPtr focus = inputInfo.keyboard->focus; + FocusClassPtr focus = kbd->focus; int rc; /* REQUEST(xReq); */ REQUEST_SIZE_MATCH(xReq); - rc = XaceHook(XACE_DEVICE_ACCESS, client, inputInfo.keyboard, - DixGetFocusAccess); + rc = XaceHook(XACE_DEVICE_ACCESS, client, kbd, DixGetFocusAccess); if (rc != Success) return rc; @@ -4070,16 +4387,16 @@ ProcGetInputFocus(ClientPtr client) } /** - * Server-side protocol handling for Grabpointer request. + * Server-side protocol handling for GrabPointer request. * - * Sets an active grab on the inputInfo.pointer and returns success status to - * client. + * Sets an active grab on the client's ClientPointer and returns success + * status to client. */ int ProcGrabPointer(ClientPtr client) { xGrabPointerReply rep; - DeviceIntPtr device = inputInfo.pointer; + DeviceIntPtr device = PickPointer(client); GrabPtr grab; WindowPtr pWin, confineTo; CursorPtr cursor, oldCursor; @@ -4117,7 +4434,7 @@ ProcGrabPointer(ClientPtr client) return rc; if (stuff->confineTo == None) confineTo = NullWindow; - else + else { rc = dixLookupWindow(&confineTo, stuff->confineTo, client, DixSetAttrAccess); @@ -4149,18 +4466,27 @@ ProcGrabPointer(ClientPtr client) rep.type = X_Reply; rep.sequenceNumber = client->sequence; rep.length = 0; - grab = device->grab; + + grab = device->deviceGrab.grab; + /* check for + 1. other client has a grab on the device already. + 2. window is viewable + 3. other client has this device as frozen "other" device + 4. times are screwed. + */ if ((grab) && !SameClient(grab, client)) rep.status = AlreadyGrabbed; else if ((!pWin->realized) || (confineTo && - !(confineTo->realized && BorderSizeNotEmpty(confineTo)))) + !(confineTo->realized + && BorderSizeNotEmpty(device, confineTo)))) rep.status = GrabNotViewable; - else if (device->sync.frozen && - device->sync.other && !SameClient(device->sync.other, client)) + else if (device->deviceGrab.sync.frozen && + device->deviceGrab.sync.other && + !SameClient(device->deviceGrab.sync.other, client)) rep.status = GrabFrozen; else if ((CompareTimeStamps(time, currentTime) == LATER) || - (CompareTimeStamps(time, device->grabTime) == EARLIER)) + (CompareTimeStamps(time, device->deviceGrab.grabTime) == EARLIER)) rep.status = GrabInvalidTime; else { @@ -4168,11 +4494,12 @@ ProcGrabPointer(ClientPtr client) oldCursor = NullCursor; if (grab) - { + { if (grab->confineTo && !confineTo) - ConfineCursorToWindow(ROOT, FALSE, FALSE); + ConfineCursorToWindow(device, RootWindow(device), FALSE, FALSE); oldCursor = grab->cursor; } + tempGrab.next = NULL; tempGrab.cursor = cursor; tempGrab.resource = client->clientAsMask; tempGrab.ownerEvents = stuff->ownerEvents; @@ -4182,7 +4509,9 @@ ProcGrabPointer(ClientPtr client) tempGrab.keyboardMode = stuff->keyboardMode; tempGrab.pointerMode = stuff->pointerMode; tempGrab.device = device; - (*device->ActivateGrab)(device, &tempGrab, time, FALSE); + tempGrab.coreGrab = True; + tempGrab.genericMasks = NULL; + (*device->deviceGrab.ActivateGrab)(device, &tempGrab, time, FALSE); if (oldCursor) FreeCursor (oldCursor, (Cursor)0); rep.status = GrabSuccess; @@ -4195,15 +4524,13 @@ ProcGrabPointer(ClientPtr client) * Server-side protocol handling for ChangeActivePointerGrab request. * * Changes properties of the grab hold by the client. If the client does not - * hold an active grab on the device, nothing happens. - * - * Works on the core pointer only. + * hold an active grab on the device, nothing happens. */ int ProcChangeActivePointerGrab(ClientPtr client) { - DeviceIntPtr device = inputInfo.pointer; - GrabPtr grab = device->grab; + DeviceIntPtr device; + GrabPtr grab; CursorPtr newCursor, oldCursor; REQUEST(xChangeActivePointerGrabReq); TimeStamp time; @@ -4226,19 +4553,23 @@ ProcChangeActivePointerGrab(ClientPtr client) return (rc == BadValue) ? BadCursor : rc; } } + + device = PickPointer(client); + grab = device->deviceGrab.grab; + if (!grab) return Success; if (!SameClient(grab, client)) return Success; time = ClientTimeToServerTime(stuff->time); if ((CompareTimeStamps(time, currentTime) == LATER) || - (CompareTimeStamps(time, device->grabTime) == EARLIER)) + (CompareTimeStamps(time, device->deviceGrab.grabTime) == EARLIER)) return Success; oldCursor = grab->cursor; grab->cursor = newCursor; if (newCursor) newCursor->refcnt++; - PostNewCursor(); + PostNewCursor(device); if (oldCursor) FreeCursor(oldCursor, (Cursor)0); grab->eventMask = stuff->eventMask; @@ -4248,55 +4579,58 @@ ProcChangeActivePointerGrab(ClientPtr client) /** * Server-side protocol handling for UngrabPointer request. * - * Deletes the pointer grab on the core pointer device. + * Deletes a pointer grab on a device the client has grabbed. */ int ProcUngrabPointer(ClientPtr client) { - DeviceIntPtr device = inputInfo.pointer; + DeviceIntPtr device = PickPointer(client); GrabPtr grab; TimeStamp time; REQUEST(xResourceReq); REQUEST_SIZE_MATCH(xResourceReq); UpdateCurrentTime(); - grab = device->grab; + grab = device->deviceGrab.grab; + time = ClientTimeToServerTime(stuff->id); if ((CompareTimeStamps(time, currentTime) != LATER) && - (CompareTimeStamps(time, device->grabTime) != EARLIER) && + (CompareTimeStamps(time, device->deviceGrab.grabTime) != EARLIER) && (grab) && SameClient(grab, client)) - (*device->DeactivateGrab)(device); + (*device->deviceGrab.DeactivateGrab)(device); return Success; } /** * Sets a grab on the given device. - * - * Called from ProcGrabKeyboard to work on the inputInfo.keyboard. + * + * Called from ProcGrabKeyboard to work on the client's keyboard. * Called from ProcXGrabDevice to work on the device specified by the client. - * + * * The parameters this_mode and other_mode represent the keyboard_mode and - * pointer_mode parameters of XGrabKeyboard(). + * pointer_mode parameters of XGrabKeyboard(). * See man page for details on all the parameters - * + * * @param client Client that owns the grab. - * @param dev The device to grab. + * @param dev The device to grab. * @param this_mode GrabModeSync or GrabModeAsync * @param other_mode GrabModeSync or GrabModeAsync * @param status Return code to be returned to the caller. - * + * * @returns Success or BadValue. */ int -GrabDevice(ClientPtr client, DeviceIntPtr dev, - unsigned this_mode, unsigned other_mode, Window grabWindow, - unsigned ownerEvents, Time ctime, Mask mask, CARD8 *status) +GrabDevice(ClientPtr client, DeviceIntPtr dev, + unsigned this_mode, unsigned other_mode, Window grabWindow, + unsigned ownerEvents, Time ctime, Mask mask, CARD8 *status, + Bool coreGrab) { WindowPtr pWin; GrabPtr grab; TimeStamp time; Mask access_mode = DixGrabAccess; int rc; + GrabInfoPtr grabInfo = &dev->deviceGrab; UpdateCurrentTime(); if ((this_mode != GrabModeSync) && (this_mode != GrabModeAsync)) @@ -4325,21 +4659,25 @@ GrabDevice(ClientPtr client, DeviceIntPtr dev, return rc; time = ClientTimeToServerTime(ctime); - grab = dev->grab; + grab = grabInfo->grab; if (grab && !SameClient(grab, client)) *status = AlreadyGrabbed; else if (!pWin->realized) *status = GrabNotViewable; else if ((CompareTimeStamps(time, currentTime) == LATER) || - (CompareTimeStamps(time, dev->grabTime) == EARLIER)) + (CompareTimeStamps(time, grabInfo->grabTime) == EARLIER)) *status = GrabInvalidTime; - else if (dev->sync.frozen && - dev->sync.other && !SameClient(dev->sync.other, client)) + else if (grabInfo->sync.frozen && + grabInfo->sync.other && !SameClient(grabInfo->sync.other, client)) *status = GrabFrozen; else { GrabRec tempGrab; + /* Otherwise segfaults happen on grabbed MPX devices */ + memset(&tempGrab, 0, sizeof(GrabRec)); + + tempGrab.next = NULL; tempGrab.window = pWin; tempGrab.resource = client->clientAsMask; tempGrab.ownerEvents = ownerEvents; @@ -4347,7 +4685,11 @@ GrabDevice(ClientPtr client, DeviceIntPtr dev, tempGrab.pointerMode = other_mode; tempGrab.eventMask = mask; tempGrab.device = dev; - (*dev->ActivateGrab)(dev, &tempGrab, time, FALSE); + tempGrab.cursor = NULL; + tempGrab.coreGrab = coreGrab; + tempGrab.genericMasks = NULL; + + (*grabInfo->ActivateGrab)(dev, &tempGrab, time, FALSE); *status = GrabSuccess; } return Success; @@ -4356,7 +4698,7 @@ GrabDevice(ClientPtr client, DeviceIntPtr dev, /** * Server-side protocol handling for GrabKeyboard request. * - * Grabs the inputInfo.keyboad and returns success status to client. + * Grabs the client's keyboard and returns success status to client. */ int ProcGrabKeyboard(ClientPtr client) @@ -4364,13 +4706,14 @@ ProcGrabKeyboard(ClientPtr client) xGrabKeyboardReply rep; REQUEST(xGrabKeyboardReq); int result; + DeviceIntPtr keyboard = PickKeyboard(client); REQUEST_SIZE_MATCH(xGrabKeyboardReq); - result = GrabDevice(client, inputInfo.keyboard, stuff->keyboardMode, - stuff->pointerMode, stuff->grabWindow, - stuff->ownerEvents, stuff->time, - KeyPressMask | KeyReleaseMask, &rep.status); + result = GrabDevice(client, keyboard, stuff->keyboardMode, + stuff->pointerMode, stuff->grabWindow, + stuff->ownerEvents, stuff->time, + KeyPressMask | KeyReleaseMask, &rep.status, TRUE); if (result != Success) return result; @@ -4384,38 +4727,42 @@ ProcGrabKeyboard(ClientPtr client) /** * Server-side protocol handling for UngrabKeyboard request. * - * Deletes a possible grab on the inputInfo.keyboard. + * Deletes a possible grab on the client's keyboard. */ int ProcUngrabKeyboard(ClientPtr client) { - DeviceIntPtr device = inputInfo.keyboard; + DeviceIntPtr device = PickKeyboard(client); GrabPtr grab; TimeStamp time; REQUEST(xResourceReq); REQUEST_SIZE_MATCH(xResourceReq); UpdateCurrentTime(); - grab = device->grab; + + grab = device->deviceGrab.grab; + time = ClientTimeToServerTime(stuff->id); if ((CompareTimeStamps(time, currentTime) != LATER) && - (CompareTimeStamps(time, device->grabTime) != EARLIER) && - (grab) && SameClient(grab, client)) - (*device->DeactivateGrab)(device); + (CompareTimeStamps(time, device->deviceGrab.grabTime) != EARLIER) && + (grab) && SameClient(grab, client) && grab->coreGrab) + (*device->deviceGrab.DeactivateGrab)(device); return Success; } /** * Server-side protocol handling for QueryPointer request. * - * Returns the current state and position of the core pointer to the client. + * Returns the current state and position of the client's ClientPointer to the + * client. */ int ProcQueryPointer(ClientPtr client) { xQueryPointerReply rep; WindowPtr pWin, t; - DeviceIntPtr mouse = inputInfo.pointer; + DeviceIntPtr mouse = PickPointer(client); + SpritePtr pSprite; int rc; REQUEST(xResourceReq); REQUEST_SIZE_MATCH(xResourceReq); @@ -4427,22 +4774,23 @@ ProcQueryPointer(ClientPtr client) if (rc != Success) return rc; + pSprite = mouse->spriteInfo->sprite; if (mouse->valuator->motionHintWindow) MaybeStopHint(mouse, client); rep.type = X_Reply; rep.sequenceNumber = client->sequence; rep.mask = mouse->button->state | inputInfo.keyboard->key->state; rep.length = 0; - rep.root = (ROOT)->drawable.id; - rep.rootX = sprite.hot.x; - rep.rootY = sprite.hot.y; + rep.root = (RootWindow(mouse))->drawable.id; + rep.rootX = pSprite->hot.x; + rep.rootY = pSprite->hot.y; rep.child = None; - if (sprite.hot.pScreen == pWin->drawable.pScreen) + if (pSprite->hot.pScreen == pWin->drawable.pScreen) { rep.sameScreen = xTrue; - rep.winX = sprite.hot.x - pWin->drawable.x; - rep.winY = sprite.hot.y - pWin->drawable.y; - for (t = sprite.win; t; t = t->parent) + rep.winX = pSprite->hot.x - pWin->drawable.x; + rep.winY = pSprite->hot.y - pWin->drawable.y; + for (t = pSprite->win; t; t = t->parent) if (t->parent == pWin) { rep.child = t->drawable.id; @@ -4469,7 +4817,7 @@ ProcQueryPointer(ClientPtr client) WriteReplyToClient(client, sizeof(xQueryPointerReply), &rep); - return(Success); + return(Success); } /** @@ -4481,32 +4829,18 @@ InitEvents(void) { int i; - sprite.hot.pScreen = sprite.hotPhys.pScreen = (ScreenPtr)NULL; inputInfo.numDevices = 0; inputInfo.devices = (DeviceIntPtr)NULL; inputInfo.off_devices = (DeviceIntPtr)NULL; inputInfo.keyboard = (DeviceIntPtr)NULL; inputInfo.pointer = (DeviceIntPtr)NULL; - if (spriteTraceSize == 0) + lastEventMask = OwnerGrabButtonMask; + filters[0][PointerMotionMask] = MotionNotify; + for (i = 1; i < MAXDEVICES; i++) { - spriteTraceSize = 32; - spriteTrace = (WindowPtr *)xalloc(32*sizeof(WindowPtr)); - if (!spriteTrace) - FatalError("failed to allocate spriteTrace"); + memcpy(&filters[i], filters[0], sizeof(filters[0])); } - spriteTraceGood = 0; - lastEventMask = OwnerGrabButtonMask; - filters[MotionNotify] = PointerMotionMask; -#ifdef XEVIE - xeviewin = -#endif - sprite.win = NullWindow; - sprite.current = NullCursor; - sprite.hotLimits.x1 = 0; - sprite.hotLimits.y1 = 0; - sprite.hotLimits.x2 = 0; - sprite.hotLimits.y2 = 0; - sprite.confined = FALSE; + syncEvents.replayDev = (DeviceIntPtr)NULL; syncEvents.replayWin = NullWindow; while (syncEvents.pending) @@ -4527,26 +4861,35 @@ InitEvents(void) DontPropagateMasks[i] = 0; DontPropagateRefCnts[i] = 0; } + + InputEventListLen = GetMaximumEventsNum(); + InputEventList = InitEventList(InputEventListLen); + if (!InputEventList) + FatalError("[dix] Failed to allocate input event list.\n"); } void CloseDownEvents(void) { - xfree(spriteTrace); - spriteTrace = NULL; - spriteTraceSize = 0; + int len; + EventListPtr list; + + len = GetEventList(&list); + while(len--) + xfree(list[len].event); } /** * Server-side protocol handling for SendEvent request. * - * Locates the window to send the event to and forwards the event. + * Locates the window to send the event to and forwards the event. */ int ProcSendEvent(ClientPtr client) { WindowPtr pWin; WindowPtr effectiveFocus = NullWindow; /* only set if dest==InputFocus */ + SpritePtr pSprite = PickPointer(client)->spriteInfo->sprite; REQUEST(xSendEventReq); REQUEST_SIZE_MATCH(xSendEventReq); @@ -4555,7 +4898,7 @@ ProcSendEvent(ClientPtr client) extension. */ if ( ! ((stuff->event.u.u.type > X_Reply && - stuff->event.u.u.type < LASTEvent) || + stuff->event.u.u.type < LASTEvent) || (stuff->event.u.u.type >= EXTENSION_EVENT_BASE && stuff->event.u.u.type < (unsigned)lastEvent))) { @@ -4577,7 +4920,7 @@ ProcSendEvent(ClientPtr client) } if (stuff->destination == PointerWindow) - pWin = sprite.win; + pWin = pSprite->win; else if (stuff->destination == InputFocus) { WindowPtr inputFocus = inputInfo.keyboard->focus->win; @@ -4587,13 +4930,13 @@ ProcSendEvent(ClientPtr client) /* If the input focus is PointerRootWin, send the event to where the pointer is if possible, then perhaps propogate up to root. */ - if (inputFocus == PointerRootWin) - inputFocus = ROOT; + if (inputFocus == PointerRootWin) + inputFocus = pSprite->spriteTrace[0]; /* Root window! */ - if (IsParent(inputFocus, sprite.win)) + if (IsParent(inputFocus, pSprite->win)) { effectiveFocus = inputFocus; - pWin = sprite.win; + pWin = pSprite->win; } else effectiveFocus = pWin = inputFocus; @@ -4616,8 +4959,8 @@ ProcSendEvent(ClientPtr client) if (XaceHook(XACE_SEND_ACCESS, client, NULL, pWin, &stuff->event, 1)) return Success; - if (DeliverEventsToWindow(pWin, &stuff->event, 1, stuff->eventMask, - NullGrab, 0)) + if (DeliverEventsToWindow(PickPointer(client), pWin, + &stuff->event, 1, stuff->eventMask, NullGrab, 0)) return Success; if (pWin == effectiveFocus) return Success; @@ -4627,16 +4970,16 @@ ProcSendEvent(ClientPtr client) } } else if (!XaceHook(XACE_SEND_ACCESS, client, NULL, pWin, &stuff->event, 1)) - (void)DeliverEventsToWindow(pWin, &stuff->event, 1, stuff->eventMask, - NullGrab, 0); + (void)DeliverEventsToWindow(PickPointer(client), pWin, &stuff->event, + 1, stuff->eventMask, NullGrab, 0); return Success; } /** * Server-side protocol handling for UngrabKey request. * - * Deletes a passive grab for the given key. Only works on the - * inputInfo.keyboard. + * Deletes a passive grab for the given key. Works on the + * client's keyboard. */ int ProcUngrabKey(ClientPtr client) @@ -4644,7 +4987,7 @@ ProcUngrabKey(ClientPtr client) REQUEST(xUngrabKeyReq); WindowPtr pWin; GrabRec tempGrab; - DeviceIntPtr keybd = inputInfo.keyboard; + DeviceIntPtr keybd = PickKeyboard(client); int rc; REQUEST_SIZE_MATCH(xUngrabKeyReq); @@ -4674,6 +5017,7 @@ ProcUngrabKey(ClientPtr client) tempGrab.type = KeyPress; tempGrab.detail.exact = stuff->key; tempGrab.detail.pMask = NULL; + tempGrab.next = NULL; if (!DeletePassiveGrabFromList(&tempGrab)) return(BadAlloc); @@ -4683,8 +5027,8 @@ ProcUngrabKey(ClientPtr client) /** * Server-side protocol handling for GrabKey request. * - * Creates a grab for the inputInfo.keyboard and adds it to the list of - * passive grabs. + * Creates a grab for the client's keyboard and adds it to the list of passive + * grabs. */ int ProcGrabKey(ClientPtr client) @@ -4692,7 +5036,7 @@ ProcGrabKey(ClientPtr client) WindowPtr pWin; REQUEST(xGrabKeyReq); GrabPtr grab; - DeviceIntPtr keybd = inputInfo.keyboard; + DeviceIntPtr keybd = PickKeyboard(client); int rc; REQUEST_SIZE_MATCH(xGrabKeyReq); @@ -4730,10 +5074,10 @@ ProcGrabKey(ClientPtr client) if (rc != Success) return rc; - grab = CreateGrab(client->index, keybd, pWin, + grab = CreateGrab(client->index, keybd, pWin, (Mask)(KeyPressMask | KeyReleaseMask), (Bool)stuff->ownerEvents, (Bool)stuff->keyboardMode, (Bool)stuff->pointerMode, - keybd, stuff->modifiers, KeyPress, stuff->key, + keybd, stuff->modifiers, KeyPress, stuff->key, NullWindow, NullCursor); if (!grab) return BadAlloc; @@ -4744,8 +5088,8 @@ ProcGrabKey(ClientPtr client) /** * Server-side protocol handling for GrabButton request. * - * Creates a grab for the inputInfo.pointer and adds it as a passive grab to - * the list. + * Creates a grab for the client's ClientPointer and adds it as a passive grab + * to the list. */ int ProcGrabButton(ClientPtr client) @@ -4754,6 +5098,7 @@ ProcGrabButton(ClientPtr client) REQUEST(xGrabButtonReq); CursorPtr cursor; GrabPtr grab; + DeviceIntPtr ptr, modifierDevice; Mask access_mode = DixGrabAccess; int rc; @@ -4811,17 +5156,20 @@ ProcGrabButton(ClientPtr client) } access_mode |= DixForceAccess; } + + ptr = PickPointer(client); + modifierDevice = GetPairedDevice(ptr); if (stuff->pointerMode == GrabModeSync || stuff->keyboardMode == GrabModeSync) access_mode |= DixFreezeAccess; - rc = XaceHook(XACE_DEVICE_ACCESS, client, inputInfo.pointer, access_mode); + rc = XaceHook(XACE_DEVICE_ACCESS, client, ptr, access_mode); if (rc != Success) return rc; - grab = CreateGrab(client->index, inputInfo.pointer, pWin, + grab = CreateGrab(client->index, ptr, pWin, (Mask)stuff->eventMask, (Bool)stuff->ownerEvents, (Bool) stuff->keyboardMode, (Bool)stuff->pointerMode, - inputInfo.keyboard, stuff->modifiers, ButtonPress, + modifierDevice, stuff->modifiers, ButtonPress, stuff->button, confineTo, cursor); if (!grab) return BadAlloc; @@ -4831,7 +5179,7 @@ ProcGrabButton(ClientPtr client) /** * Server-side protocol handling for UngrabButton request. * - * Deletes a passive grab on the inputInfo.pointer from the list. + * Deletes a passive grab on the client's ClientPointer from the list. */ int ProcUngrabButton(ClientPtr client) @@ -4852,7 +5200,7 @@ ProcUngrabButton(ClientPtr client) if (rc != Success) return rc; tempGrab.resource = client->clientAsMask; - tempGrab.device = inputInfo.pointer; + tempGrab.device = PickPointer(client); tempGrab.window = pWin; tempGrab.modifiersDetail.exact = stuff->modifiers; tempGrab.modifiersDetail.pMask = NULL; @@ -4860,6 +5208,7 @@ ProcUngrabButton(ClientPtr client) tempGrab.type = ButtonPress; tempGrab.detail.exact = stuff->button; tempGrab.detail.pMask = NULL; + tempGrab.next = NULL; if (!DeletePassiveGrabFromList(&tempGrab)) return(BadAlloc); @@ -4883,73 +5232,95 @@ DeleteWindowFromAnyEvents(WindowPtr pWin, Bool freeResources) WindowPtr parent; DeviceIntPtr mouse = inputInfo.pointer; DeviceIntPtr keybd = inputInfo.keyboard; - FocusClassPtr focus = keybd->focus; + FocusClassPtr focus; OtherClientsPtr oc; GrabPtr passive; + GrabPtr grab; /* Deactivate any grabs performed on this window, before making any input focus changes. */ + grab = mouse->deviceGrab.grab; + if (grab && + ((grab->window == pWin) || (grab->confineTo == pWin))) + (*mouse->deviceGrab.DeactivateGrab)(mouse); - if (mouse->grab && - ((mouse->grab->window == pWin) || (mouse->grab->confineTo == pWin))) - (*mouse->DeactivateGrab)(mouse); /* Deactivating a keyboard grab should cause focus events. */ + grab = keybd->deviceGrab.grab; + if (grab && (grab->window == pWin)) + (*keybd->deviceGrab.DeactivateGrab)(keybd); - if (keybd->grab && (keybd->grab->window == pWin)) - (*keybd->DeactivateGrab)(keybd); - - /* If the focus window is a root window (ie. has no parent) then don't - delete the focus from it. */ - - if ((pWin == focus->win) && (pWin->parent != NullWindow)) + /* And now the real devices */ + for (mouse = inputInfo.devices; mouse; mouse = mouse->next) { - int focusEventMode = NotifyNormal; - - /* If a grab is in progress, then alter the mode of focus events. */ + grab = mouse->deviceGrab.grab; + if (grab && ((grab->window == pWin) || (grab->confineTo == pWin))) + (*mouse->deviceGrab.DeactivateGrab)(mouse); + } - if (keybd->grab) - focusEventMode = NotifyWhileGrabbed; - switch (focus->revert) - { - case RevertToNone: - DoFocusEvents(keybd, pWin, NoneWin, focusEventMode); - focus->win = NoneWin; - focus->traceGood = 0; - break; - case RevertToParent: - parent = pWin; - do - { - parent = parent->parent; - focus->traceGood--; - } while (!parent->realized -/* This would be a good protocol change -- windows being reparented - during SaveSet processing would cause the focus to revert to the - nearest enclosing window which will survive the death of the exiting - client, instead of ending up reverting to a dying window and thence - to None - */ + for (keybd = inputInfo.devices; keybd; keybd = keybd->next) + { + if (IsKeyboardDevice(keybd)) + { + focus = keybd->focus; + + /* If the focus window is a root window (ie. has no parent) then don't + delete the focus from it. */ + + if ((pWin == focus->win) && (pWin->parent != NullWindow)) + { + int focusEventMode = NotifyNormal; + + /* If a grab is in progress, then alter the mode of focus events. */ + + if (keybd->deviceGrab.grab) + focusEventMode = NotifyWhileGrabbed; + + switch (focus->revert) + { + case RevertToNone: + DoFocusEvents(keybd, pWin, NoneWin, focusEventMode); + focus->win = NoneWin; + focus->traceGood = 0; + break; + case RevertToParent: + parent = pWin; + do + { + parent = parent->parent; + focus->traceGood--; + } while (!parent->realized + /* This would be a good protocol change -- windows being reparented + during SaveSet processing would cause the focus to revert to the + nearest enclosing window which will survive the death of the exiting + client, instead of ending up reverting to a dying window and thence + to None + */ #ifdef NOTDEF - || clients[CLIENT_ID(parent->drawable.id)]->clientGone + || clients[CLIENT_ID(parent->drawable.id)]->clientGone #endif - ); - DoFocusEvents(keybd, pWin, parent, focusEventMode); - focus->win = parent; - focus->revert = RevertToNone; - break; - case RevertToPointerRoot: - DoFocusEvents(keybd, pWin, PointerRootWin, focusEventMode); - focus->win = PointerRootWin; - focus->traceGood = 0; - break; - } - } + ); + DoFocusEvents(keybd, pWin, parent, focusEventMode); + focus->win = parent; + focus->revert = RevertToNone; + break; + case RevertToPointerRoot: + DoFocusEvents(keybd, pWin, PointerRootWin, focusEventMode); + focus->win = PointerRootWin; + focus->traceGood = 0; + break; + } + } + } - if (mouse->valuator->motionHintWindow == pWin) - mouse->valuator->motionHintWindow = NullWindow; + if (IsPointerDevice(keybd)) + { + if (keybd->valuator->motionHintWindow == pWin) + keybd->valuator->motionHintWindow = NullWindow; + } + } if (freeResources) { @@ -4960,9 +5331,8 @@ DeleteWindowFromAnyEvents(WindowPtr pWin, Bool freeResources) while ( (passive = wPassiveGrabs(pWin)) ) FreeResource(passive->resource, RT_NONE); } -#ifdef XINPUT + DeleteWindowFromAnyExtEvents(pWin, freeResources); -#endif } /** @@ -4973,19 +5343,27 @@ DeleteWindowFromAnyEvents(WindowPtr pWin, Bool freeResources) _X_EXPORT void CheckCursorConfinement(WindowPtr pWin) { - GrabPtr grab = inputInfo.pointer->grab; + GrabPtr grab; WindowPtr confineTo; + DeviceIntPtr pDev; #ifdef PANORAMIX if(!noPanoramiXExtension && pWin->drawable.pScreen->myNum) return; #endif - if (grab && (confineTo = grab->confineTo)) + for (pDev = inputInfo.devices; pDev; pDev = pDev->next) { - if (!BorderSizeNotEmpty(confineTo)) - (*inputInfo.pointer->DeactivateGrab)(inputInfo.pointer); - else if ((pWin == confineTo) || IsParent(pWin, confineTo)) - ConfineCursorToWindow(confineTo, TRUE, TRUE); + if (DevHasCursor(pDev)) + { + grab = pDev->deviceGrab.grab; + if (grab && (confineTo = grab->confineTo)) + { + if (!BorderSizeNotEmpty(pDev, confineTo)) + (*inputInfo.pointer->deviceGrab.DeactivateGrab)(pDev); + else if ((pWin == confineTo) || IsParent(pWin, confineTo)) + ConfineCursorToWindow(pDev, confineTo, TRUE, TRUE); + } + } } } @@ -5013,7 +5391,8 @@ ProcRecolorCursor(ClientPtr client) CursorPtr pCursor; int rc, nscr; ScreenPtr pscr; - Bool displayed; + Bool displayed; + SpritePtr pSprite = PickPointer(client)->spriteInfo->sprite; REQUEST(xRecolorCursorReq); REQUEST_SIZE_MATCH(xRecolorCursorReq); @@ -5038,12 +5417,12 @@ ProcRecolorCursor(ClientPtr client) pscr = screenInfo.screens[nscr]; #ifdef PANORAMIX if(!noPanoramiXExtension) - displayed = (pscr == sprite.screen); + displayed = (pscr == pSprite->screen); else #endif - displayed = (pscr == sprite.hotPhys.pScreen); - ( *pscr->RecolorCursor)(pscr, pCursor, - (pCursor == sprite.current) && displayed); + displayed = (pscr == pSprite->hotPhys.pScreen); + ( *pscr->RecolorCursor)(PickPointer(client), pscr, pCursor, + (pCursor == pSprite->current) && displayed); } return (Success); } @@ -5054,10 +5433,10 @@ ProcRecolorCursor(ClientPtr client) * the given event type. * * In the case of DeviceMotionNotify trailed by DeviceValuators, the events - * can be more than one. Usually it's just one event. + * can be more than one. Usually it's just one event. * * Do not modify the event structure passed in. See comment below. - * + * * @param pClient Client to send events to. * @param count Number of events. * @param events The event list. @@ -5068,8 +5447,9 @@ WriteEventsToClient(ClientPtr pClient, int count, xEvent *events) #ifdef PANORAMIX xEvent eventCopy; #endif - xEvent eventTo, *eventFrom; - int i; + xEvent *eventTo, *eventFrom; + int i, + eventlength = sizeof(xEvent); #ifdef XKB if ((!noXkbExtension)&&(!XkbFilterEvents(pClient, count, events))) @@ -5077,8 +5457,8 @@ WriteEventsToClient(ClientPtr pClient, int count, xEvent *events) #endif #ifdef PANORAMIX - if(!noPanoramiXExtension && - (panoramiXdataPtr[0].x || panoramiXdataPtr[0].y)) + if(!noPanoramiXExtension && + (panoramiXdataPtr[0].x || panoramiXdataPtr[0].y)) { switch(events->u.u.type) { case MotionNotify: @@ -5088,17 +5468,17 @@ WriteEventsToClient(ClientPtr pClient, int count, xEvent *events) case KeyRelease: case EnterNotify: case LeaveNotify: - /* + /* When multiple clients want the same event DeliverEventsToWindow - passes the same event structure multiple times so we can't - modify the one passed to us + passes the same event structure multiple times so we can't + modify the one passed to us */ count = 1; /* should always be 1 */ memcpy(&eventCopy, events, sizeof(xEvent)); eventCopy.u.keyButtonPointer.rootX += panoramiXdataPtr[0].x; eventCopy.u.keyButtonPointer.rootY += panoramiXdataPtr[0].y; - if(eventCopy.u.keyButtonPointer.event == - eventCopy.u.keyButtonPointer.root) + if(eventCopy.u.keyButtonPointer.event == + eventCopy.u.keyButtonPointer.root) { eventCopy.u.keyButtonPointer.eventX += panoramiXdataPtr[0].x; eventCopy.u.keyButtonPointer.eventY += panoramiXdataPtr[0].y; @@ -5125,21 +5505,273 @@ WriteEventsToClient(ClientPtr pClient, int count, xEvent *events) XSERVER_SEND_EVENT(pClient->index, events[i].u.u.type, &events[i]); } } -#endif +#endif + /* Just a safety check to make sure we only have one GenericEvent, it just + * makes things easier for me right now. (whot) */ + for (i = 1; i < count; i++) + { + if (events[i].u.u.type == GenericEvent) + { + ErrorF("[dix] TryClientEvents: Only one GenericEvent at a time.\n"); + return; + } + } + + if (events->u.u.type == GenericEvent) + { + eventlength += ((xGenericEvent*)events)->length * 4; + } + if(pClient->swapped) { + if (eventlength > swapEventLen) + { + swapEventLen = eventlength; + swapEvent = Xrealloc(swapEvent, swapEventLen); + if (!swapEvent) + { + FatalError("WriteEventsToClient: Out of memory.\n"); + return; + } + } + for(i = 0; i < count; i++) { eventFrom = &events[i]; + eventTo = swapEvent; + /* Remember to strip off the leading bit of type in case this event was sent with "SendEvent." */ (*EventSwapVector[eventFrom->u.u.type & 0177]) - (eventFrom, &eventTo); - (void)WriteToClient(pClient, sizeof(xEvent), (char *)&eventTo); + (eventFrom, eventTo); + + (void)WriteToClient(pClient, eventlength, (char *)eventTo); } } else { - (void)WriteToClient(pClient, count * sizeof(xEvent), (char *) events); + /* only one GenericEvent, remember? that means either count is 1 and + * eventlength is arbitrary or eventlength is 32 and count doesn't + * matter. And we're all set. Woohoo. */ + (void)WriteToClient(pClient, count * eventlength, (char *) events); + } +} + +/* + * Set the client pointer for the given client. Second parameter setter could + * be used in the future to determine access rights. Unused for now. + * + * A client can have exactly one ClientPointer. Each time a + * request/reply/event is processed and the choice of devices is ambiguous + * (e.g. QueryPointer request), the server will pick the ClientPointer (see + * PickPointer()). + * If a keyboard is needed, the first keyboard paired with the CP is used. + */ +_X_EXPORT Bool +SetClientPointer(ClientPtr client, ClientPtr setter, DeviceIntPtr device) +{ + if (!device->isMaster) + { + ErrorF("[dix] Need master device for ClientPointer. This is a bug.\n"); + return FALSE; + } else if (!device->spriteInfo->spriteOwner) + { + ErrorF("[dix] Device %d does not have a sprite. " + "Cannot be ClientPointer\n", device->id); + return FALSE; } + client->clientPtr = device; + return TRUE; } + +/* PickPointer will pick an appropriate pointer for the given client. + * + * An "appropriate device" is (in order of priority): + * 1) A device the given client has a core grab on. + * 2) A device set as ClientPointer for the given client. + * 3) The first master device. + */ +_X_EXPORT DeviceIntPtr +PickPointer(ClientPtr client) +{ + DeviceIntPtr it = inputInfo.devices; + + /* First, check if the client currently has a grab on a device. Even + * keyboards count. */ + for(it = inputInfo.devices; it; it = it->next) + { + GrabPtr grab = it->deviceGrab.grab; + if (grab && grab->coreGrab && SameClient(grab, client)) + { + if (!IsPointerDevice(it)) + it = GetPairedDevice(it); + return it; /* Always return a core grabbed device */ + } + } + + if (!client->clientPtr) + { + DeviceIntPtr it = inputInfo.devices; + while (it) + { + if (it->isMaster && it->spriteInfo->spriteOwner) + { + client->clientPtr = it; + break; + } + it = it->next; + } + } + return client->clientPtr; +} + +/* PickKeyboard will pick an appropriate keyboard for the given client by + * searching the list of devices for the keyboard device that is paired with + * the client's pointer. + */ +_X_EXPORT DeviceIntPtr +PickKeyboard(ClientPtr client) +{ + DeviceIntPtr ptr = PickPointer(client); + DeviceIntPtr kbd = ptr->spriteInfo->paired; + + if (!kbd) + { + ErrorF("[dix] ClientPointer not paired with a keyboard. This " + "is a bug.\n"); + } + + return kbd; +} + +/* A client that has one or more core grabs does not get core events from + * devices it does not have a grab on. Legacy applications behave bad + * otherwise because they are not used to it and the events interfere. + * Only applies for core events. + * + * Return true if a core event from the device would interfere and should not + * be delivered. + */ +Bool +IsInterferingGrab(ClientPtr client, DeviceIntPtr dev, xEvent* event) +{ + DeviceIntPtr it = inputInfo.devices; + + if (dev->deviceGrab.grab && SameClient(dev->deviceGrab.grab, client)) + return FALSE; + + switch(event->u.u.type) + { + case KeyPress: + case KeyRelease: + case ButtonPress: + case ButtonRelease: + case MotionNotify: + case EnterNotify: + case LeaveNotify: + break; + default: + return FALSE; + } + + while(it) + { + if (it != dev) + { + if (it->deviceGrab.grab && SameClient(it->deviceGrab.grab, client) + && !it->deviceGrab.fromPassiveGrab) + { + if ((IsPointerDevice(it) && IsPointerDevice(dev)) || + (IsKeyboardDevice(it) && IsKeyboardDevice(dev))) + return TRUE; + } + } + it = it->next; + } + + return FALSE; +} + +/** + * Set the filters for a extension. + * The filters array needs to contain the Masks that are applicable for each + * event type for the given extension. + * e.g. if generic event type 2 should be let through for windows with + * MyExampleMask set, make sure that filters[2] == MyExampleMask. + */ +_X_EXPORT void +SetGenericFilter(int extension, Mask* filters) +{ + generic_filters[extension & 0x7f] = filters; +} + + +/** + * Grab a device for XI events and XGE events. + * grabmode is used to ungrab a device. + */ +_X_EXPORT int +ExtGrabDevice(ClientPtr client, + DeviceIntPtr dev, + int device_mode, + WindowPtr grabWindow, + WindowPtr confineTo, + TimeStamp ctime, + Bool ownerEvents, + CursorPtr cursor, + Mask xi_mask, + GenericMaskPtr ge_masks) +{ + GrabInfoPtr grabinfo; + GrabRec newGrab; + + UpdateCurrentTime(); + + grabinfo = &dev->deviceGrab; + + if (grabinfo->grab && !SameClient(grabinfo->grab, client)) + return AlreadyGrabbed; + + if (!grabWindow->realized) + return GrabNotViewable; + + if ((CompareTimeStamps(ctime, currentTime) == LATER) || + (CompareTimeStamps(ctime, grabinfo->grabTime) == EARLIER)) + return GrabInvalidTime; + + if (grabinfo->sync.frozen && grabinfo->sync.other && + !SameClient(grabinfo->sync.other, client)) + return GrabFrozen; + + memset(&newGrab, 0, sizeof(GrabRec)); + newGrab.window = grabWindow; + newGrab.resource = client->clientAsMask; + newGrab.ownerEvents = ownerEvents; + newGrab.device = dev; + newGrab.cursor = cursor; + newGrab.confineTo = confineTo; + newGrab.eventMask = xi_mask; + newGrab.genericMasks = NULL; + newGrab.next = NULL; + + if (ge_masks) + { + newGrab.genericMasks = xcalloc(1, sizeof(GenericMaskRec)); + *newGrab.genericMasks = *ge_masks; + newGrab.genericMasks->next = NULL; + } + + if (IsPointerDevice(dev)) + { + newGrab.keyboardMode = GrabModeAsync; + newGrab.pointerMode = device_mode; + } else + { + newGrab.keyboardMode = device_mode; + newGrab.pointerMode = GrabModeAsync; + } + + (*grabinfo->ActivateGrab)(dev, &newGrab, ctime, FALSE); + return GrabSuccess; +} + diff --git a/xorg-server/dix/extension.c b/xorg-server/dix/extension.c index 9740c1b50..3070f4da1 100644 --- a/xorg-server/dix/extension.c +++ b/xorg-server/dix/extension.c @@ -63,8 +63,6 @@ SOFTWARE. #include "registry.h" #include "xace.h" -#define EXTENSION_BASE 128 -#define EXTENSION_EVENT_BASE 64 #define LAST_EVENT 128 #define LAST_ERROR 255 @@ -84,7 +82,7 @@ AddExtension(char *name, int NumEvents, int NumErrors, int i; ExtensionEntry *ext, **newexts; - if (!MainProc || !SwappedMainProc || !CloseDownProc || !MinorOpcodeProc) + if (!MainProc || !SwappedMainProc || !MinorOpcodeProc) return((ExtensionEntry *) NULL); if ((lastEvent + NumEvents > LAST_EVENT) || (unsigned)(lastError + NumErrors > LAST_ERROR)) @@ -247,7 +245,8 @@ CloseDownExtensions(void) for (i = NumExtensions - 1; i >= 0; i--) { - (* extensions[i]->CloseDown)(extensions[i]); + if (extensions[i]->CloseDown) + extensions[i]->CloseDown(extensions[i]); NumExtensions = i; xfree(extensions[i]->name); for (j = extensions[i]->num_aliases; --j >= 0;) diff --git a/xorg-server/dix/ffs.c b/xorg-server/dix/ffs.c index b75657d29..d0bd3e507 100644 --- a/xorg-server/dix/ffs.c +++ b/xorg-server/dix/ffs.c @@ -30,6 +30,8 @@ The Open Group. #include <dix-config.h> #endif +#ifndef HAVE_FFS + #include "dix.h" int @@ -42,3 +44,5 @@ ffs(int i) i >>= 1; return j; } + +#endif diff --git a/xorg-server/dix/gc.c b/xorg-server/dix/gc.c index 83f48d4e3..b9256940d 100644 --- a/xorg-server/dix/gc.c +++ b/xorg-server/dix/gc.c @@ -1049,7 +1049,7 @@ FreeDefaultStipple(int screenNum) (*pScreen->DestroyPixmap)(pScreen->PixmapPerDepth[0]); } -_X_EXPORT int +int SetDashes(GCPtr pGC, unsigned offset, unsigned ndash, unsigned char *pdash) { long i; @@ -1155,7 +1155,7 @@ VerifyRectOrder(int nrects, xRectangle *prects, int ordering) return -1; } -_X_EXPORT int +int SetClipRects(GCPtr pGC, int xOrigin, int yOrigin, int nrects, xRectangle *prects, int ordering) { diff --git a/xorg-server/dix/getevents.c b/xorg-server/dix/getevents.c index 1e0edbf00..9747b35a6 100644 --- a/xorg-server/dix/getevents.c +++ b/xorg-server/dix/getevents.c @@ -47,7 +47,6 @@ #ifdef XKB #include <X11/extensions/XKBproto.h> #include <xkbsrv.h> -extern Bool XkbCopyKeymap(XkbDescPtr src, XkbDescPtr dst, Bool sendNotifies); #endif #ifdef PANORAMIX @@ -62,14 +61,22 @@ extern Bool XkbCopyKeymap(XkbDescPtr src, XkbDescPtr dst, Bool sendNotifies); #include "exglobals.h" #include "extnsionst.h" - -/* Maximum number of valuators, divided by six, rounded up, to get number - * of events. */ -#define MAX_VALUATOR_EVENTS 6 - /* Number of motion history events to store. */ #define MOTION_HISTORY_SIZE 256 +/* InputEventList is the container list for all input events generated by the + * DDX. The DDX is expected to call GetEventList() and then pass the list into + * Get{Pointer|Keyboard}Events. + */ +EventListPtr InputEventList = NULL; +int InputEventListLen = 0; + +_X_EXPORT int +GetEventList(EventListPtr* list) +{ + *list = InputEventList; + return InputEventListLen; +} /** * Pick some arbitrary size for Xi motion history. @@ -106,43 +113,151 @@ key_autorepeats(DeviceIntPtr pDev, int key_code) } /** + * Rescale the coord between the two axis ranges. + */ +static int +rescaleValuatorAxis(int coord, AxisInfoPtr from, AxisInfoPtr to, + int defmax) +{ + int fmin = 0, tmin = 0, fmax = defmax, tmax = defmax; + + if(from && from->min_value < from->max_value) { + fmin = from->min_value; + fmax = from->max_value; + } + if(to && to->min_value < to->max_value) { + tmin = to->min_value; + tmax = to->max_value; + } + + if(fmin == tmin && fmax == tmax) + return coord; + + if(fmax == fmin) /* avoid division by 0 */ + return 0; + + return roundf(((float)(coord - fmin)) * (tmax - tmin) / + (fmax - fmin)) + tmin; +} + +/** + * Update all coordinates when changing to a different SD + * to ensure that relative reporting will work as expected + * without loss of precision. + * + * pDev->last.valuators will be in absolute device coordinates after this + * function. + */ +static void +updateSlaveDeviceCoords(DeviceIntPtr master, DeviceIntPtr pDev) +{ + ScreenPtr scr = miPointerGetScreen(pDev); + int i; + DeviceIntPtr lastSlave; + + /* master->last.valuators[0]/[1] is in screen coords and the actual + * position of the pointer */ + pDev->last.valuators[0] = master->last.valuators[0]; + pDev->last.valuators[1] = master->last.valuators[1]; + + if (!pDev->valuator) + return; + + /* scale back to device coordinates */ + if(pDev->valuator->numAxes > 0) + pDev->last.valuators[0] = rescaleValuatorAxis(pDev->last.valuators[0], NULL, pDev->valuator->axes + 0, scr->width); + if(pDev->valuator->numAxes > 1) + pDev->last.valuators[1] = rescaleValuatorAxis(pDev->last.valuators[1], NULL, pDev->valuator->axes + 1, scr->height); + + /* calculate the other axis as well based on info from the old + * slave-device. If the old slave had less axes than this one, + * last.valuators is reset to 0. + */ + if ((lastSlave = master->u.lastSlave) && lastSlave->valuator) { + for (i = 2; i < pDev->valuator->numAxes; i++) { + if (i >= lastSlave->valuator->numAxes) + pDev->last.valuators[i] = 0; + else + pDev->last.valuators[i] = + rescaleValuatorAxis(pDev->last.valuators[i], + lastSlave->valuator->axes + i, + pDev->valuator->axes + i, 0); + } + } + +} + +/** * Allocate the motion history buffer. */ _X_EXPORT void AllocateMotionHistory(DeviceIntPtr pDev) { + int size; if (pDev->valuator->motion) xfree(pDev->valuator->motion); if (pDev->valuator->numMotionEvents < 1) return; - pDev->valuator->motion = xalloc(((sizeof(INT32) * pDev->valuator->numAxes) + - sizeof(Time)) * - pDev->valuator->numMotionEvents); + /* An MD must have a motion history size large enough to keep all + * potential valuators, plus the respective range of the valuators. + * 3 * INT32 for (min_val, max_val, curr_val)) + */ + if (pDev->isMaster) + size = sizeof(INT32) * 3 * MAX_VALUATORS; + else + size = sizeof(INT32) * pDev->valuator->numAxes; + + size += sizeof(Time); + + pDev->valuator->motion = xcalloc(pDev->valuator->numMotionEvents, size); pDev->valuator->first_motion = 0; pDev->valuator->last_motion = 0; + if (!pDev->valuator->motion) + ErrorF("[dix] %s: Failed to alloc motion history (%d bytes).\n", + pDev->name, size * pDev->valuator->numMotionEvents); } - /** * Dump the motion history between start and stop into the supplied buffer. * Only records the event for a given screen in theory, but in practice, we * sort of ignore this. + * + * If core is set, we only generate x/y, in INT16, scaled to screen coords. */ _X_EXPORT int -GetMotionHistory(DeviceIntPtr pDev, xTimecoord *buff, unsigned long start, - unsigned long stop, ScreenPtr pScreen) +GetMotionHistory(DeviceIntPtr pDev, xTimecoord **buff, unsigned long start, + unsigned long stop, ScreenPtr pScreen, BOOL core) { - char *ibuff = NULL, *obuff = (char *) buff; + char *ibuff = NULL, *obuff; int i = 0, ret = 0; + int j, coord; Time current; /* The size of a single motion event. */ - int size = (sizeof(INT32) * pDev->valuator->numAxes) + sizeof(Time); + int size; + int dflt; + AxisInfo from, *to; /* for scaling */ + INT32 *ocbuf, *icbuf; /* pointer to coordinates for copying */ + INT16 *corebuf; + AxisInfo core_axis = {0}; if (!pDev->valuator || !pDev->valuator->numMotionEvents) return 0; + if (core && !pScreen) + return 0; + + if (pDev->isMaster) + size = (sizeof(INT32) * 3 * MAX_VALUATORS) + sizeof(Time); + else + size = (sizeof(INT32) * pDev->valuator->numAxes) + sizeof(Time); + + *buff = xalloc(size * pDev->valuator->numMotionEvents); + if (!(*buff)) + return 0; + obuff = (char *)*buff; + for (i = pDev->valuator->first_motion; i != pDev->valuator->last_motion; i = (i + 1) % pDev->valuator->numMotionEvents) { @@ -156,8 +271,80 @@ GetMotionHistory(DeviceIntPtr pDev, xTimecoord *buff, unsigned long start, return ret; } else if (current >= start) { - memcpy(obuff, ibuff, size); - obuff += size; + if (core) + { + memcpy(obuff, ibuff, sizeof(Time)); /* copy timestamp */ + + icbuf = (INT32*)(ibuff + sizeof(Time)); + corebuf = (INT16*)(obuff + sizeof(Time)); + + /* fetch x coordinate + range */ + memcpy(&from.min_value, icbuf++, sizeof(INT32)); + memcpy(&from.max_value, icbuf++, sizeof(INT32)); + memcpy(&coord, icbuf++, sizeof(INT32)); + + /* scale to screen coords */ + to = &core_axis; + to->max_value = pScreen->width; + coord = rescaleValuatorAxis(coord, &from, to, pScreen->width); + + memcpy(corebuf, &coord, sizeof(INT16)); + corebuf++; + + /* fetch y coordinate + range */ + memcpy(&from.min_value, icbuf++, sizeof(INT32)); + memcpy(&from.max_value, icbuf++, sizeof(INT32)); + memcpy(&coord, icbuf++, sizeof(INT32)); + + to->max_value = pScreen->height; + coord = rescaleValuatorAxis(coord, &from, to, pScreen->height); + memcpy(corebuf, &coord, sizeof(INT16)); + + } else if (pDev->isMaster) + { + memcpy(obuff, ibuff, sizeof(Time)); /* copy timestamp */ + + ocbuf = (INT32*)(obuff + sizeof(Time)); + icbuf = (INT32*)(ibuff + sizeof(Time)); + for (j = 0; j < MAX_VALUATORS; j++) + { + if (j >= pDev->valuator->numAxes) + break; + + /* fetch min/max/coordinate */ + memcpy(&from.min_value, icbuf++, sizeof(INT32)); + memcpy(&from.max_value, icbuf++, sizeof(INT32)); + memcpy(&coord, icbuf++, sizeof(INT32)); + + to = (j < pDev->valuator->numAxes) ? &pDev->valuator->axes[j] : NULL; + + /* x/y scaled to screen if no range is present */ + if (j == 0 && (from.max_value < from.min_value)) + from.max_value = pScreen->width; + else if (j == 1 && (from.max_value < from.min_value)) + from.max_value = pScreen->height; + + if (j == 0 && (to->max_value < to->min_value)) + dflt = pScreen->width; + else if (j == 1 && (to->max_value < to->min_value)) + dflt = pScreen->height; + else + dflt = 0; + + /* scale from stored range into current range */ + coord = rescaleValuatorAxis(coord, &from, to, 0); + memcpy(ocbuf, &coord, sizeof(INT32)); + ocbuf++; + } + } else + memcpy(obuff, ibuff, size); + + /* don't advance by size here. size may be different to the + * actually written size if the MD has less valuators than MAX */ + if (core) + obuff += sizeof(INT32) + sizeof(Time); + else + obuff += (sizeof(INT32) * pDev->valuator->numAxes) + sizeof(Time); ret++; } } @@ -169,29 +356,65 @@ GetMotionHistory(DeviceIntPtr pDev, xTimecoord *buff, unsigned long start, /** * Update the motion history for a specific device, with the list of * valuators. + * + * Layout of the history buffer: + * for SDs: [time] [val0] [val1] ... [valn] + * for MDs: [time] [min_val0] [max_val0] [val0] [min_val1] ... [valn] + * + * For events that have some valuators unset (first_valuator > 0): + * min_val == max_val == val == 0. */ static void updateMotionHistory(DeviceIntPtr pDev, CARD32 ms, int first_valuator, int num_valuators, int *valuators) { char *buff = (char *) pDev->valuator->motion; + ValuatorClassPtr v; + int i; if (!pDev->valuator->numMotionEvents) return; - buff += ((sizeof(INT32) * pDev->valuator->numAxes) + sizeof(CARD32)) * + v = pDev->valuator; + if (pDev->isMaster) + { + buff += ((sizeof(INT32) * 3 * MAX_VALUATORS) + sizeof(CARD32)) * + v->last_motion; + + memcpy(buff, &ms, sizeof(Time)); + buff += sizeof(Time); + + memset(buff, 0, sizeof(INT32) * 3 * MAX_VALUATORS); + buff += 3 * sizeof(INT32) * first_valuator; + + for (i = first_valuator; i < first_valuator + num_valuators; i++) + { + if (i >= v->numAxes) + break; + memcpy(buff, &v->axes[i].min_value, sizeof(INT32)); + buff += sizeof(INT32); + memcpy(buff, &v->axes[i].max_value, sizeof(INT32)); + buff += sizeof(INT32); + memcpy(buff, &valuators[i - first_valuator], sizeof(INT32)); + buff += sizeof(INT32); + } + } else + { + + buff += ((sizeof(INT32) * pDev->valuator->numAxes) + sizeof(CARD32)) * pDev->valuator->last_motion; - memcpy(buff, &ms, sizeof(Time)); - buff += sizeof(Time); - bzero(buff, sizeof(INT32) * pDev->valuator->numAxes); + memcpy(buff, &ms, sizeof(Time)); + buff += sizeof(Time); - buff += sizeof(INT32) * first_valuator; - memcpy(buff, valuators, sizeof(INT32) * num_valuators); + memset(buff, 0, sizeof(INT32) * pDev->valuator->numAxes); + buff += sizeof(INT32) * first_valuator; - pDev->valuator->last_motion = (pDev->valuator->last_motion + 1) % - pDev->valuator->numMotionEvents; + memcpy(buff, valuators, sizeof(INT32) * num_valuators); + } + pDev->valuator->last_motion = (pDev->valuator->last_motion + 1) % + pDev->valuator->numMotionEvents; /* If we're wrapping around, just keep the circular buffer going. */ if (pDev->valuator->first_motion == pDev->valuator->last_motion) pDev->valuator->first_motion = (pDev->valuator->first_motion + 1) % @@ -212,9 +435,9 @@ updateMotionHistory(DeviceIntPtr pDev, CARD32 ms, int first_valuator, */ _X_EXPORT int GetMaximumEventsNum(void) { - /* Two base events -- core and device, plus valuator events. Multiply - * by two if we're doing non-XKB key repeats. */ - int ret = 2 + MAX_VALUATOR_EVENTS; + /* One base event -- device, plus valuator events. + * Multiply by two if we're doing non-XKB key repeats. */ + int ret = 1 + MAX_VALUATOR_EVENTS; #ifdef XKB if (noXkbExtension) @@ -225,80 +448,6 @@ GetMaximumEventsNum(void) { } -/* Originally a part of xf86PostMotionEvent; modifies valuators - * in-place. */ -static void -acceleratePointer(DeviceIntPtr pDev, int first_valuator, int num_valuators, - int *valuators) -{ - 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 (pDev->ptrfeed && pDev->ptrfeed->ctrl.num) { - /* modeled from xf86Events.c */ - if (pDev->ptrfeed->ctrl.threshold) { - if ((abs(dx) + abs(dy)) >= pDev->ptrfeed->ctrl.threshold) { - pDev->valuator->dxremaind = ((float)dx * - (float)(pDev->ptrfeed->ctrl.num)) / - (float)(pDev->ptrfeed->ctrl.den) + - pDev->valuator->dxremaind; - if (px) { - *px = (int)pDev->valuator->dxremaind; - pDev->valuator->dxremaind = pDev->valuator->dxremaind - - (float)(*px); - } - - pDev->valuator->dyremaind = ((float)dy * - (float)(pDev->ptrfeed->ctrl.num)) / - (float)(pDev->ptrfeed->ctrl.den) + - pDev->valuator->dyremaind; - if (py) { - *py = (int)pDev->valuator->dyremaind; - pDev->valuator->dyremaind = pDev->valuator->dyremaind - - (float)(*py); - } - } - } - else { - mult = pow((float)dx * (float)dx + (float)dy * (float)dy, - ((float)(pDev->ptrfeed->ctrl.num) / - (float)(pDev->ptrfeed->ctrl.den) - 1.0) / - 2.0) / 2.0; - if (dx) { - pDev->valuator->dxremaind = mult * (float)dx + - pDev->valuator->dxremaind; - *px = (int)pDev->valuator->dxremaind; - pDev->valuator->dxremaind = pDev->valuator->dxremaind - - (float)(*px); - } - if (dy) { - pDev->valuator->dyremaind = mult * (float)dy + - pDev->valuator->dyremaind; - *py = (int)pDev->valuator->dyremaind; - pDev->valuator->dyremaind = pDev->valuator->dyremaind - - (float)(*py); - } - } - } -} - - /** * Clip an axis to its bounds, which are declared in the call to * InitValuatorAxisClassStruct. @@ -306,15 +455,17 @@ acceleratePointer(DeviceIntPtr pDev, int first_valuator, int num_valuators, static void clipAxis(DeviceIntPtr pDev, int axisNum, int *val) { - AxisInfoPtr axes = pDev->valuator->axes + axisNum; - - /* No clipping if the value-range <= 0 */ - if(axes->min_value < axes->min_value) { - if (*val < axes->min_value) - *val = axes->min_value; - if (*val > axes->max_value) - *val = axes->max_value; - } + AxisInfoPtr axis = pDev->valuator->axes + axisNum; + /* InitValuatoraAxisStruct ensures that (min < max). */ + + /* If a value range is defined, clip. If not, do nothing */ + if (axis->max_value <= axis->min_value) + return; + + if (*val < axis->min_value) + *val = axis->min_value; + if (*val > axis->max_value) + *val = axis->max_value; } /** @@ -335,23 +486,20 @@ clipValuators(DeviceIntPtr pDev, int first_valuator, int num_valuators, /** * Fills events with valuator events for pDev, as given by the other * parameters. - * - * FIXME: Need to fix ValuatorClassRec to store all the valuators as - * last posted, not just x and y; otherwise relative non-x/y - * valuators, though a very narrow use case, will be broken. */ -static xEvent * -getValuatorEvents(xEvent *events, DeviceIntPtr pDev, int first_valuator, - int num_valuators, int *valuators) { - deviceValuator *xv = (deviceValuator *) events; - int i = 0, final_valuator = first_valuator + num_valuators; +static EventList * +getValuatorEvents(EventList *events, DeviceIntPtr pDev, + int first_valuator, int num_valuators, int *valuators) { + deviceValuator *xv; + int i; - for (i = first_valuator; i < final_valuator; i += 6, xv++, events++) { + for (i = 0; i < num_valuators; i += 6, events++) { + xv = (deviceValuator*)events->event; xv->type = DeviceValuator; - xv->first_valuator = i; - xv->num_valuators = ((final_valuator - i) > 6) ? 6 : (final_valuator - i); + xv->first_valuator = first_valuator + i; + xv->num_valuators = ((num_valuators - i) > 6) ? 6 : (num_valuators - i); xv->deviceid = pDev->id; - switch (final_valuator - i) { + switch (num_valuators - i) { case 6: xv->valuator5 = valuators[i + 5]; case 5: @@ -363,23 +511,235 @@ getValuatorEvents(xEvent *events, DeviceIntPtr pDev, int first_valuator, case 2: xv->valuator1 = valuators[i + 1]; case 1: - xv->valuator0 = valuators[i]; + xv->valuator0 = valuators[i + 0]; } - if (i + 6 < final_valuator) + if (i + 6 < num_valuators) xv->deviceid |= MORE_EVENTS; } return events; } +/** + * Create the DCCE event (does not update the master's device state yet, this + * is done in the event processing). + * Pull in the coordinates from the MD if necessary. + * + * @param events Pointer to a pre-allocated event list. + * @param dev The slave device that generated an event. + * @param num_events The current number of events, returns the number of + * events if a DCCE was generated. + * @return The updated @events pointer. + */ +static EventListPtr +updateFromMaster(EventListPtr events, DeviceIntPtr dev, int *num_events) +{ + DeviceIntPtr master = dev->u.master; + if (master && master->u.lastSlave != dev) + { + updateSlaveDeviceCoords(master, dev); + master->u.lastSlave = dev; + master->last.numValuators = dev->last.numValuators; + } + return events; +} + +/** + * Move the device's pointer to the position given in the valuators. + * + * @param dev The device which's pointer is to be moved. + * @param x Returns the x position of the pointer after the move. + * @param y Returns the y position of the pointer after the move. + * @param first The first valuator in @valuators + * @param num Total number of valuators in @valuators. + * @param valuators Valuator data for each axis between @first and + * @first+@num. + */ +static void +moveAbsolute(DeviceIntPtr dev, int *x, int *y, + int first, int num, int *valuators) +{ + int i; + + + if (num >= 1 && first == 0) + *x = *(valuators + 0); + else + *x = dev->last.valuators[0]; + + if (first <= 1 && num >= (2 - first)) + *y = *(valuators + 1 - first); + else + *y = dev->last.valuators[1]; + + clipAxis(dev, 0, x); + clipAxis(dev, 1, y); + + i = (first > 2) ? 0 : 2; + for (; i < num; i++) + { + dev->last.valuators[i + first] = valuators[i]; + clipAxis(dev, i, &dev->last.valuators[i + first]); + } +} + +/** + * Move the device's pointer by the values given in @valuators. + * + * @param dev The device which's pointer is to be moved. + * @param x Returns the x position of the pointer after the move. + * @param y Returns the y position of the pointer after the move. + * @param first The first valuator in @valuators + * @param num Total number of valuators in @valuators. + * @param valuators Valuator data for each axis between @first and + * @first+@num. + */ +static void +moveRelative(DeviceIntPtr dev, int *x, int *y, + int first, int num, int *valuators) +{ + int i; + + *x = dev->last.valuators[0]; + *y = dev->last.valuators[1]; + + if (num >= 1 && first == 0) + *x += *(valuators +0); + + if (first <= 1 && num >= (2 - first)) + *y += *(valuators + 1 - first); + + /* 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) { + clipAxis(dev, 0, x); + clipAxis(dev, 1, y); + } + + /* calc other axes, clip, drop back into valuators */ + i = (first > 2) ? 0 : 2; + for (; i < num; i++) + { + dev->last.valuators[i + first] += valuators[i]; + clipAxis(dev, i, &dev->last.valuators[i + first]); + valuators[i] = dev->last.valuators[i + first]; + } +} + +/** + * Accelerate the data in valuators based on the device's acceleration scheme. + * + * @param dev The device which's pointer is to be moved. + * @param first The first valuator in @valuators + * @param num Total number of valuators in @valuators. + * @param valuators Valuator data for each axis between @first and + * @first+@num. + * @param ms Current time. + */ +static void +accelPointer(DeviceIntPtr dev, int first, int num, int *valuators, CARD32 ms) +{ + if (dev->valuator->accelScheme.AccelSchemeProc) + dev->valuator->accelScheme.AccelSchemeProc(dev, first, num, valuators, ms); +} + +/** + * If we have HW cursors, this actually moves the visible sprite. If not, we + * just do all the screen crossing, etc. + * + * We scale from device to screen coordinates here, call + * miPointerSetPosition() and then scale back into device coordinates (if + * needed). miPSP will change x/y if the screen was crossed. + * + * @param dev The device to be moved. + * @param x Pointer to current x-axis value, may be modified. + * @param y Pointer to current y-axis value, may be modified. + * @param scr Screen the device's sprite is currently on. + * @param screenx Screen x coordinate the sprite is on after the update. + * @param screeny Screen y coordinate the sprite is on after the update. + */ +static void +positionSprite(DeviceIntPtr dev, int *x, int *y, + ScreenPtr scr, int *screenx, int *screeny) +{ + /* scale x&y to screen */ + *screenx = rescaleValuatorAxis(*x, dev->valuator->axes + 0, NULL, scr->width); + *screeny = rescaleValuatorAxis(*y, dev->valuator->axes + 1, NULL, scr->height); + dev->last.valuators[0] = *screenx; + dev->last.valuators[1] = *screeny; + + /* This takes care of crossing screens for us, as well as clipping + * to the current screen. */ + miPointerSetPosition(dev, &dev->last.valuators[0], &dev->last.valuators[1]); + + if (dev->u.master) { + dev->u.master->last.valuators[0] = dev->last.valuators[0]; + dev->u.master->last.valuators[1] = dev->last.valuators[1]; + } + + /* Crossed screen? Scale back to device coordiantes */ + if(*screenx != dev->last.valuators[0]) + { + scr = miPointerGetScreen(dev); + *x = rescaleValuatorAxis(dev->last.valuators[0], NULL, + dev->valuator->axes + 0, scr->width); + *screenx = dev->last.valuators[0]; + } + if(*screeny != dev->last.valuators[1]) + { + scr = miPointerGetScreen(dev); + *screeny = dev->last.valuators[1]; + *y = rescaleValuatorAxis(dev->last.valuators[1], NULL, + dev->valuator->axes + 1, scr->height); + } + + /* dropy x/y (device coordinates) back into valuators for next event */ + dev->last.valuators[0] = *x; + dev->last.valuators[1] = *y; +} + +/** + * Update the motion history for the device and (if appropriate) for its + * master device. + * @param dev Slave device to update. + * @param first First valuator to append to history. + * @param num Total number of valuators to append to history. + * @param ms Current time + */ +static void +updateHistory(DeviceIntPtr dev, int first, int num, CARD32 ms) +{ + updateMotionHistory(dev, ms, first, num, &dev->last.valuators[first]); + if (dev->u.master) + updateMotionHistory(dev->u.master, ms, first, num, + &dev->last.valuators[first]); +} + +/** + * Calculate how many DeviceValuator events are needed given a number of + * valuators. + * @param num_valuators Number of valuators to attach to event. + * @return the number of DeviceValuator events needed. + */ +static int +countValuatorEvents(int num_valuators) +{ + if (num_valuators) { + if (((num_valuators - 1) / 6) + 1 > MAX_VALUATOR_EVENTS) + num_valuators = MAX_VALUATOR_EVENTS * 6; + return ((num_valuators - 1)/ 6) + 1; + } else + return 0; +} /** * Convenience wrapper around GetKeyboardValuatorEvents, that takes no * valuators. */ _X_EXPORT int -GetKeyboardEvents(xEvent *events, DeviceIntPtr pDev, int type, int key_code) { +GetKeyboardEvents(EventList *events, DeviceIntPtr pDev, int type, int key_code) { return GetKeyboardValuatorEvents(events, pDev, type, key_code, 0, 0, NULL); } @@ -388,6 +748,9 @@ GetKeyboardEvents(xEvent *events, DeviceIntPtr pDev, int type, int key_code) { * Returns a set of keyboard events for KeyPress/KeyRelease, optionally * also with valuator events. Handles Xi and XKB. * + * DOES NOT GENERATE CORE EVENTS! Core events are created when processing the + * event (ProcessOtherEvent). + * * events is not NULL-terminated; the return value is the number of events. * The DDX is responsible for allocating the event structure in the first * place via GetMaximumEventsNum(), and for freeing it. @@ -402,42 +765,29 @@ GetKeyboardEvents(xEvent *events, DeviceIntPtr pDev, int type, int key_code) { * KeyPresses. */ _X_EXPORT int -GetKeyboardValuatorEvents(xEvent *events, DeviceIntPtr pDev, int type, +GetKeyboardValuatorEvents(EventList *events, DeviceIntPtr pDev, int type, int key_code, int first_valuator, int num_valuators, int *valuators) { int numEvents = 0; CARD32 ms = 0; - KeySym *map = pDev->key->curKeySyms.map; + KeySym *map; KeySym sym; deviceKeyButtonPointer *kbp = NULL; - if (!events) - return 0; - - /* DO NOT WANT */ - if (type != KeyPress && type != KeyRelease) + if (!events ||!pDev->key || !pDev->focus || !pDev->kbdfeed || + (type != KeyPress && type != KeyRelease) || + (key_code < 8 || key_code > 255)) return 0; - if (!pDev->key || !pDev->focus || !pDev->kbdfeed || - (pDev->coreEvents && !inputInfo.keyboard->key)) - return 0; - - if (key_code < 8 || key_code > 255) - return 0; + numEvents = 1; + map = pDev->key->curKeySyms.map; sym = map[(key_code - pDev->key->curKeySyms.minKeyCode) * pDev->key->curKeySyms.mapWidth]; - if (pDev->coreEvents) - numEvents = 2; - else - numEvents = 1; + events = updateFromMaster(events, pDev, &numEvents); - if (num_valuators) { - if ((num_valuators / 6) + 1 > MAX_VALUATOR_EVENTS) - num_valuators = MAX_VALUATOR_EVENTS; - numEvents += (num_valuators / 6) + 1; - } + numEvents += countValuatorEvents(num_valuators); #ifdef XKB if (noXkbExtension) @@ -470,28 +820,21 @@ GetKeyboardValuatorEvents(xEvent *events, DeviceIntPtr pDev, int type, if (noXkbExtension) #endif { - numEvents += GetKeyboardValuatorEvents(events, pDev, - KeyRelease, key_code, - first_valuator, num_valuators, - valuators); - events += numEvents; + int numReleaseEvents; + + numReleaseEvents = GetKeyboardValuatorEvents(events, pDev, + KeyRelease, key_code, + first_valuator, + num_valuators, + valuators); + numEvents += numReleaseEvents; + events += numReleaseEvents; } } ms = GetTimeInMillis(); - if (pDev->coreEvents) { - events->u.keyButtonPointer.time = ms; - events->u.u.type = type; - events->u.u.detail = key_code; - if (type == KeyPress) - set_key_down(inputInfo.keyboard, key_code); - else if (type == KeyRelease) - set_key_up(inputInfo.keyboard, key_code); - events++; - } - - kbp = (deviceKeyButtonPointer *) events; + kbp = (deviceKeyButtonPointer *) events->event; kbp->time = ms; kbp->deviceid = pDev->id; kbp->detail = key_code; @@ -515,261 +858,179 @@ GetKeyboardValuatorEvents(xEvent *events, DeviceIntPtr pDev, int type, return numEvents; } +/** + * Initialize an event list and fill with 32 byte sized events. + * This event list is to be passed into GetPointerEvents() and + * GetKeyboardEvents(). + * + * @param num_events Number of elements in list. + */ +EventListPtr +InitEventList(int num_events) +{ + EventListPtr events; + int i; + + events = (EventListPtr)xcalloc(num_events, sizeof(EventList)); + if (!events) + return NULL; + + for (i = 0; i < num_events; i++) + { + events[i].evlen = sizeof(xEvent); + events[i].event = xcalloc(1, sizeof(xEvent)); + if (!events[i].event) + { + /* rollback */ + while(i--) + xfree(events[i].event); + xfree(events); + events = NULL; + break; + } + } + + return events; +} + +/** + * Allocs min_size memory for each event in the list. + */ +_X_EXPORT void +SetMinimumEventSize(EventListPtr list, int num_events, int min_size) +{ + if (!list) + return; + + while(num_events--) + { + if (list[num_events].evlen < min_size) + { + list[num_events].evlen = min_size; + list[num_events].event = realloc(list[num_events].event, min_size); + if (!list[num_events].event) + { + FatalError("[dix] Failed to set event list's " + "min_size to %d.\n", min_size); + } + } + } +} + +/** + * Free an event list. + * + * @param list The list to be freed. + * @param num_events Number of elements in list. + */ +_X_EXPORT void +FreeEventList(EventListPtr list, int num_events) +{ + if (!list) + return; + while(num_events--) + xfree(list[num_events].event); + xfree(list); +} /** - * Generate a series of xEvents (returned in xE) representing pointer - * motion, or button presses. Xi and XKB-aware. + * Generate a series of xEvents (filled into the EventList) representing + * pointer motion, or button presses. Xi and XKB-aware. + * + * DOES NOT GENERATE CORE EVENTS! Core events are created when processing the + * event (ProcessOtherEvent). * * events is not NULL-terminated; the return value is the number of events. * The DDX is responsible for allocating the event structure in the first - * place via GetMaximumEventsNum(), and for freeing it. + * place via InitEventList() and GetMaximumEventsNum(), and for freeing it. + * + * In the generated events rootX/Y will be in absolute screen coords and + * the valuator information in the absolute or relative device coords. + * + * last.valuators[x] of the device is always in absolute device coords. + * last.valuators[x] of the master device is in absolute screen coords. + * + * master->last.valuators[x] for x > 2 is undefined. */ _X_EXPORT int -GetPointerEvents(xEvent *events, DeviceIntPtr pDev, int type, int buttons, +GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons, int flags, int first_valuator, int num_valuators, int *valuators) { - int num_events = 0, final_valuator = 0; - CARD32 ms = 0; + int num_events = 1; + CARD32 ms; deviceKeyButtonPointer *kbp = NULL; - DeviceIntPtr cp = inputInfo.pointer; - int x = 0, y = 0; - Bool coreOnly = (pDev == inputInfo.pointer); + int x, y, /* switches between device and screen coords */ + cx, cy; /* only screen coordinates */ ScreenPtr scr = miPointerGetScreen(pDev); - /* Sanity checks. */ - if (type != MotionNotify && type != ButtonPress && type != ButtonRelease) - return 0; - - if ((type == ButtonPress || type == ButtonRelease) && !pDev->button) - return 0; - - /* FIXME: I guess it should, in theory, be possible to post button events - * from devices without valuators. */ - if (!pDev->valuator) - return 0; - - if (!coreOnly && pDev->coreEvents) - num_events = 2; - else - num_events = 1; + ms = GetTimeInMillis(); /* before pointer update to help precision */ - if (type == MotionNotify && num_valuators <= 0) + if (!scr || !pDev->valuator || first_valuator < 0 || + ((num_valuators + first_valuator) > pDev->valuator->numAxes) || + (type != MotionNotify && type != ButtonPress && type != ButtonRelease) || + (type != MotionNotify && !pDev->button) || + (type == MotionNotify && num_valuators <= 0)) return 0; - /* Do we need to send a DeviceValuator event? */ - if (!coreOnly && num_valuators) { - if ((((num_valuators - 1) / 6) + 1) > MAX_VALUATOR_EVENTS) - num_valuators = MAX_VALUATOR_EVENTS * 6; - num_events += ((num_valuators - 1) / 6) + 1; - } - - final_valuator = num_valuators + first_valuator; - - /* You fail. */ - if (first_valuator < 0 || final_valuator > pDev->valuator->numAxes) - return 0; + num_events += countValuatorEvents(num_valuators); - ms = GetTimeInMillis(); + events = updateFromMaster(events, pDev, &num_events); - /* Set x and y based on whether this is absolute or relative, and - * accelerate if we need to. */ - if (flags & POINTER_ABSOLUTE) { - if (num_valuators >= 1 && first_valuator == 0) { - x = valuators[0]; - } - else { - /* If we're sending core events but didn't provide a value, - * translate the core value (but use the device coord if - * it translates to the same coord to preserve sub-pixel - * coord information). If we're not sending core events use - * whatever value we have */ - x = pDev->valuator->lastx; - if(pDev->coreEvents) { - int min = pDev->valuator->axes[0].min_value; - int max = pDev->valuator->axes[0].max_value; - if(min < max) { - if((int)((float)(x-min)*scr->width/(max-min+1)) != cp->valuator->lastx) - x = (int)((float)(cp->valuator->lastx)*(max-min+1)/scr->width)+min; - } - else - x = cp->valuator->lastx; - } - } + if (flags & POINTER_ABSOLUTE) + { + if (flags & POINTER_SCREEN) /* valuators are in screen coords */ + { - if (first_valuator <= 1 && num_valuators >= (2 - first_valuator)) { - y = valuators[1 - first_valuator]; - } - else { - y = pDev->valuator->lasty; - if(pDev->coreEvents) { - int min = pDev->valuator->axes[1].min_value; - int max = pDev->valuator->axes[1].max_value; - if(min < max) { - if((int)((float)(y-min)*scr->height/(max-min+1)) != cp->valuator->lasty) - y = (int)((float)(cp->valuator->lasty)*(max-min+1)/scr->height)+min; - } - else - y = cp->valuator->lasty; - } + valuators[0] = rescaleValuatorAxis(valuators[0], NULL, + pDev->valuator->axes + 0, + scr->width); + valuators[1] = rescaleValuatorAxis(valuators[1], NULL, + pDev->valuator->axes + 1, + scr->height); } - /* Clip both x and y to the defined limits (usually co-ord space limit). */ - clipAxis(pDev, 0, &x); - clipAxis(pDev, 1, &y); - } - else { + moveAbsolute(pDev, &x, &y, first_valuator, num_valuators, valuators); + } else { if (flags & POINTER_ACCELERATE) - acceleratePointer(pDev, first_valuator, num_valuators, - valuators); - - if (pDev->coreEvents) { - /* Get and convert the core pointer coordinate space into - * device coordinates. Use the device coords if it translates - * into the same position as the core to preserve relative sub- - * pixel movements from the device. */ - int min = pDev->valuator->axes[0].min_value; - int max = pDev->valuator->axes[0].max_value; - if(min < max) { - x = pDev->valuator->lastx; - if((int)((float)(x-min)*scr->width/(max-min+1)) != cp->valuator->lastx) - x = (int)((float)(cp->valuator->lastx)*(max-min+1)/scr->width)+min; - } - else - x = cp->valuator->lastx; - - min = pDev->valuator->axes[1].min_value; - max = pDev->valuator->axes[1].max_value; - if(min < max) { - y = pDev->valuator->lasty; - if((int)((float)(y-min)*scr->height/(max-min+1)) != cp->valuator->lasty) - y = (int)((float)(cp->valuator->lasty)*(max-min+1)/scr->height)+min; - } - else - y = cp->valuator->lasty; - - /* Add relative movement */ - if (first_valuator == 0 && num_valuators >= 1) - x += valuators[0]; - if (first_valuator <= 1 && num_valuators >= (2 - first_valuator)) - y += valuators[1 - first_valuator]; - } - else { - x = pDev->valuator->lastx; - y = pDev->valuator->lasty; - if (first_valuator == 0 && num_valuators >= 1) - x += valuators[0]; - if (first_valuator <= 1 && num_valuators >= (2 - first_valuator)) - y += valuators[1 - first_valuator]; - - if(!coreOnly) { - /* Since we're not sending core-events we must clip both x and y - * to the defined limits so we don't run outside the box. */ - clipAxis(pDev, 0, &x); - clipAxis(pDev, 1, &y); - } - } + accelPointer(pDev, first_valuator, num_valuators, valuators, ms); + moveRelative(pDev, &x, &y, first_valuator, num_valuators, valuators); } - pDev->valuator->lastx = x; - pDev->valuator->lasty = y; - /* Convert the dev coord back to screen coord if we're - * sending core events */ - if (pDev->coreEvents) { - int min = pDev->valuator->axes[0].min_value; - int max = pDev->valuator->axes[0].max_value; - if(min < max) - x = (int)((float)(x-min)*scr->width/(max-min+1)); - cp->valuator->lastx = x; - min = pDev->valuator->axes[1].min_value; - max = pDev->valuator->axes[1].max_value; - if(min < max) - y = (int)((float)(y-min)*scr->height/(max-min+1)); - cp->valuator->lasty = y; - } + positionSprite(pDev, &x, &y, scr, &cx, &cy); + updateHistory(pDev, first_valuator, num_valuators, ms); - /* This takes care of crossing screens for us, as well as clipping - * to the current screen. Right now, we only have one history buffer, - * so we don't set this for both the device and core.*/ - miPointerSetPosition(pDev, &x, &y, ms); - - if (pDev->coreEvents) { - /* miPointerSetPosition may have changed screen */ - scr = miPointerGetScreen(pDev); - if(x != cp->valuator->lastx) { - int min = pDev->valuator->axes[0].min_value; - int max = pDev->valuator->axes[0].max_value; - cp->valuator->lastx = pDev->valuator->lastx = x; - if(min < max) - pDev->valuator->lastx = (int)((float)(x)*(max-min+1)/scr->width)+min; - } - if(y != cp->valuator->lasty) { - int min = pDev->valuator->axes[1].min_value; - int max = pDev->valuator->axes[1].max_value; - cp->valuator->lasty = pDev->valuator->lasty = y; - if(min < max) - pDev->valuator->lasty = (int)((float)(y)*(max-min+1)/scr->height)+min; - } - } - else if (coreOnly) { - cp->valuator->lastx = x; - cp->valuator->lasty = y; - } - /* Drop x and y back into the valuators list, if they were originally - * present. */ - if (first_valuator == 0 && num_valuators >= 1) - valuators[0] = pDev->valuator->lastx; + /* Update the valuators with the true value sent to the client*/ + if (num_valuators >= 1 && first_valuator == 0) + valuators[0] = x; if (first_valuator <= 1 && num_valuators >= (2 - first_valuator)) - valuators[1 - first_valuator] = pDev->valuator->lasty; - - updateMotionHistory(pDev, ms, first_valuator, num_valuators, valuators); - - /* for some reason inputInfo.pointer does not have coreEvents set */ - if (coreOnly || pDev->coreEvents) { - events->u.u.type = type; - events->u.keyButtonPointer.time = ms; - events->u.keyButtonPointer.rootX = x; - events->u.keyButtonPointer.rootY = y; - - if (type == ButtonPress || type == ButtonRelease) { - /* We hijack SetPointerMapping to work on all core-sending - * devices, so we use the device-specific map here instead of - * the core one. */ - events->u.u.detail = pDev->button->map[buttons]; - } - else { - events->u.u.detail = 0; - } + valuators[1 - first_valuator] = y; - events++; - } - - if (!coreOnly) { - kbp = (deviceKeyButtonPointer *) events; - kbp->time = ms; - kbp->deviceid = pDev->id; + kbp = (deviceKeyButtonPointer *) events->event; + kbp->time = ms; + kbp->deviceid = pDev->id; - if (type == MotionNotify) { - kbp->type = DeviceMotionNotify; - } - else { - if (type == ButtonPress) - kbp->type = DeviceButtonPress; - else if (type == ButtonRelease) - kbp->type = DeviceButtonRelease; - kbp->detail = pDev->button->map[buttons]; - } + if (type == MotionNotify) { + kbp->type = DeviceMotionNotify; + } + else { + if (type == ButtonPress) + kbp->type = DeviceButtonPress; + else if (type == ButtonRelease) + kbp->type = DeviceButtonRelease; + kbp->detail = buttons; + } - kbp->root_x = pDev->valuator->lastx; - kbp->root_y = pDev->valuator->lasty; + kbp->root_x = cx; /* root_x/y always in screen coords */ + kbp->root_y = cy; - events++; - if (num_valuators) { - kbp->deviceid |= MORE_EVENTS; + events++; + if (num_valuators) { + kbp->deviceid |= MORE_EVENTS; + if (flags & POINTER_ABSOLUTE) clipValuators(pDev, first_valuator, num_valuators, valuators); - events = getValuatorEvents(events, pDev, first_valuator, - num_valuators, valuators); - } + events = getValuatorEvents(events, pDev, first_valuator, + num_valuators, valuators); } return num_events; @@ -784,19 +1045,18 @@ GetPointerEvents(xEvent *events, DeviceIntPtr pDev, int type, int buttons, * place via GetMaximumEventsNum(), and for freeing it. */ _X_EXPORT int -GetProximityEvents(xEvent *events, DeviceIntPtr pDev, int type, +GetProximityEvents(EventList *events, DeviceIntPtr pDev, int type, int first_valuator, int num_valuators, int *valuators) { int num_events = 1; - deviceKeyButtonPointer *kbp = (deviceKeyButtonPointer *) events; + deviceKeyButtonPointer *kbp; + DeviceIntPtr master; /* Sanity checks. */ if (type != ProximityIn && type != ProximityOut) return 0; - if (!pDev->valuator) return 0; - /* Do we need to send a DeviceValuator event? */ if ((pDev->valuator->mode & 1) == Relative) num_valuators = 0; @@ -812,6 +1072,15 @@ GetProximityEvents(xEvent *events, DeviceIntPtr pDev, int type, (num_valuators + first_valuator) > pDev->valuator->numAxes) return 0; + master = pDev->u.master; + if (master && master->u.lastSlave != pDev) + { + updateSlaveDeviceCoords(master, pDev); + master->u.lastSlave = pDev; + master->last.numValuators = pDev->last.numValuators; + } + + kbp = (deviceKeyButtonPointer *) events->event; kbp->type = type; kbp->deviceid = pDev->id; kbp->detail = 0; @@ -828,87 +1097,6 @@ GetProximityEvents(xEvent *events, DeviceIntPtr pDev, int type, return num_events; } - -/** - * Note that pDev was the last device to send a core event. This function - * copies the complete keymap from the originating device to the core - * device, and makes sure the appropriate notifications are generated. - * - * Call this just before processInputProc. - */ -_X_EXPORT void -SwitchCoreKeyboard(DeviceIntPtr pDev) -{ - KeyClassPtr ckeyc = inputInfo.keyboard->key; - int i = 0; - - if (pDev != dixLookupPrivate(&inputInfo.keyboard->devPrivates, - CoreDevicePrivateKey)) { - memcpy(ckeyc->modifierMap, pDev->key->modifierMap, MAP_LENGTH); - if (ckeyc->modifierKeyMap) - xfree(ckeyc->modifierKeyMap); - ckeyc->modifierKeyMap = xalloc(8 * pDev->key->maxKeysPerModifier); - memcpy(ckeyc->modifierKeyMap, pDev->key->modifierKeyMap, - (8 * pDev->key->maxKeysPerModifier)); - - ckeyc->maxKeysPerModifier = pDev->key->maxKeysPerModifier; - ckeyc->curKeySyms.minKeyCode = pDev->key->curKeySyms.minKeyCode; - ckeyc->curKeySyms.maxKeyCode = pDev->key->curKeySyms.maxKeyCode; - SetKeySymsMap(&ckeyc->curKeySyms, &pDev->key->curKeySyms); - - /* - * Copy state from the extended keyboard to core. If you omit this, - * holding Ctrl on keyboard one, and pressing Q on keyboard two, will - * cause your app to quit. This feels wrong to me, hence the below - * code. - * - * XXX: If you synthesise core modifier events, the state will get - * clobbered here. You'll have to work out something sensible - * to fix that. Good luck. - */ - -#define KEYBOARD_MASK (ShiftMask | LockMask | ControlMask | Mod1Mask | \ - Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask) - ckeyc->state &= ~(KEYBOARD_MASK); - ckeyc->state |= (pDev->key->state & KEYBOARD_MASK); -#undef KEYBOARD_MASK - for (i = 0; i < 8; i++) - ckeyc->modifierKeyCount[i] = pDev->key->modifierKeyCount[i]; - -#ifdef XKB - if (!noXkbExtension && pDev->key->xkbInfo && pDev->key->xkbInfo->desc) { - if (!XkbCopyKeymap(pDev->key->xkbInfo->desc, ckeyc->xkbInfo->desc, - True)) - FatalError("Couldn't pivot keymap from device to core!\n"); - } -#endif - - SendMappingNotify(MappingKeyboard, ckeyc->curKeySyms.minKeyCode, - (ckeyc->curKeySyms.maxKeyCode - - ckeyc->curKeySyms.minKeyCode), - serverClient); - dixSetPrivate(&inputInfo.keyboard->devPrivates, CoreDevicePrivateKey, - pDev); - } -} - - -/** - * Note that pDev was the last function to send a core pointer event. - * Currently a no-op. - * - * Call this just before processInputProc. - */ -_X_EXPORT void -SwitchCorePointer(DeviceIntPtr pDev) -{ - if (pDev != dixLookupPrivate(&inputInfo.pointer->devPrivates, - CoreDevicePrivateKey)) - dixSetPrivate(&inputInfo.pointer->devPrivates, - CoreDevicePrivateKey, pDev); -} - - /** * Synthesize a single motion event for the core pointer. * @@ -916,7 +1104,11 @@ SwitchCorePointer(DeviceIntPtr pDev) * to shift the pointer to get it inside the new bounds. */ void -PostSyntheticMotion(int x, int y, int screen, unsigned long time) +PostSyntheticMotion(DeviceIntPtr pDev, + int x, + int y, + int screen, + unsigned long time) { xEvent xE; @@ -936,5 +1128,5 @@ PostSyntheticMotion(int x, int y, int screen, unsigned long time) xE.u.keyButtonPointer.rootY = y; xE.u.keyButtonPointer.time = time; - (*inputInfo.pointer->public.processInputProc)(&xE, inputInfo.pointer, 1); + (*pDev->public.processInputProc)(&xE, pDev, 1); } diff --git a/xorg-server/dix/globals.c b/xorg-server/dix/globals.c index 7f95eabd5..973dc43c3 100644 --- a/xorg-server/dix/globals.c +++ b/xorg-server/dix/globals.c @@ -78,12 +78,12 @@ PtrCtrl defaultPointerControl = { DEFAULT_PTR_THRESHOLD, 0}; -_X_EXPORT ClientPtr *clients; +_X_EXPORT ClientPtr clients[MAXCLIENTS]; _X_EXPORT ClientPtr serverClient; _X_EXPORT int currentMaxClients; /* current size of clients array */ _X_EXPORT long maxBigRequestSize = MAX_BIG_REQUEST_SIZE; -_X_EXPORT WindowPtr *WindowTable; +_X_EXPORT WindowPtr WindowTable[MAXSCREENS]; _X_EXPORT unsigned long globalSerialNumber = 0; _X_EXPORT unsigned long serverGeneration = 0; @@ -111,7 +111,7 @@ CARD32 defaultDPMSStandbyTime = DEFAULT_STANDBY_TIME; CARD32 defaultDPMSSuspendTime = DEFAULT_SUSPEND_TIME; CARD32 defaultDPMSOffTime = DEFAULT_OFF_TIME; _X_EXPORT CARD16 DPMSPowerLevel = 0; -_X_EXPORT Bool defaultDPMSEnabled = DEFAULT_DPMS_ENABLED; +Bool defaultDPMSEnabled = DEFAULT_DPMS_ENABLED; _X_EXPORT Bool DPMSEnabledSwitch = FALSE; /* these denote the DPMS command */ _X_EXPORT Bool DPMSDisabledSwitch = FALSE; /* lind switch states */ _X_EXPORT Bool DPMSCapableFlag = FALSE; @@ -136,16 +136,13 @@ Bool screenSaverSuspended = FALSE; char *defaultFontPath = COMPILEDDEFAULTFONTPATH; char *defaultTextFont = COMPILEDDEFAULTFONT; char *defaultCursorFont = COMPILEDCURSORFONT; -char *defaultDisplayClass = COMPILEDDISPLAYCLASS; FontPtr defaultFont; /* not declared in dix.h to avoid including font.h in every compilation of dix code */ -Bool loadableFonts = FALSE; CursorPtr rootCursor; -Bool blackRoot=FALSE; -Bool whiteRoot=FALSE; -#ifdef XPRINT -ClientPtr requestingClient; /* XXX this should be obsolete now, remove? */ -#endif +Bool party_like_its_1989 = FALSE; +Bool whiteRoot = FALSE; + +int cursorScreenDevPriv[MAXSCREENS]; _X_EXPORT TimeStamp currentTime; _X_EXPORT TimeStamp lastDeviceEventTime; @@ -154,9 +151,8 @@ _X_EXPORT int defaultColorVisualClass = -1; _X_EXPORT int monitorResolution = 0; _X_EXPORT char *display; +char *ConnectionInfo; CARD32 TimeOutValue = DEFAULT_TIMEOUT * MILLI_PER_SECOND; -int argcGlobal; -char **argvGlobal; DDXPointRec dixScreenOrigins[MAXSCREENS]; diff --git a/xorg-server/dix/glyphcurs.c b/xorg-server/dix/glyphcurs.c index 905b5fb13..f74b13730 100644 --- a/xorg-server/dix/glyphcurs.c +++ b/xorg-server/dix/glyphcurs.c @@ -91,11 +91,9 @@ ServerBitsFromGlyph(FontPtr pfont, unsigned ch, CursorMetricPtr cm, unsigned cha pScreen = screenInfo.screens[0]; nby = BitmapBytePad(cm->width) * (long)cm->height; - pbits = (char *)xalloc(nby); + pbits = xcalloc(1, nby); if (!pbits) return BadAlloc; - /* zeroing the (pad) bits seems to help some ddx cursor handling */ - bzero(pbits, nby); ppix = (PixmapPtr)(*pScreen->CreatePixmap)(pScreen, cm->width, cm->height, 1, diff --git a/xorg-server/dix/grabs.c b/xorg-server/dix/grabs.c index 85e101c6a..b372d8f1b 100644 --- a/xorg-server/dix/grabs.c +++ b/xorg-server/dix/grabs.c @@ -88,10 +88,10 @@ CreateGrab( return (GrabPtr)NULL; grab->resource = FakeClientID(client); grab->device = device; - grab->coreGrab = ((device == inputInfo.keyboard) || - (device == inputInfo.pointer)); + grab->coreGrab = (type < LASTEvent); grab->window = window; grab->eventMask = eventMask; + grab->deviceMask = 0; grab->ownerEvents = ownerEvents; grab->keyboardMode = keyboardMode; grab->pointerMode = pointerMode; @@ -105,6 +105,8 @@ CreateGrab( grab->detail.pMask = NULL; grab->confineTo = confineTo; grab->cursor = cursor; + grab->genericMasks = NULL; + grab->next = NULL; if (cursor) cursor->refcnt++; return grab; @@ -239,12 +241,28 @@ GrabSupersedesSecond(GrabPtr pFirstGrab, GrabPtr pSecondGrab) return FALSE; } +/** + * Compares two grabs and returns TRUE if the first grab matches the second + * grab. + * + * A match is when + * - the devices set for the grab are equal (this is optional). + * - the event types for both grabs are equal. + * - XXX + * + * @param ignoreDevice TRUE if the device settings on the grabs are to be + * ignored. + * @return TRUE if the grabs match or FALSE otherwise. + */ Bool -GrabMatchesSecond(GrabPtr pFirstGrab, GrabPtr pSecondGrab) +GrabMatchesSecond(GrabPtr pFirstGrab, GrabPtr pSecondGrab, Bool ignoreDevice) { - if ((pFirstGrab->device != pSecondGrab->device) || - (pFirstGrab->modifierDevice != pSecondGrab->modifierDevice) || - (pFirstGrab->type != pSecondGrab->type)) + if (!ignoreDevice && + ((pFirstGrab->device != pSecondGrab->device) || + (pFirstGrab->modifierDevice != pSecondGrab->modifierDevice))) + return FALSE; + + if (pFirstGrab->type != pSecondGrab->type) return FALSE; if (GrabSupersedesSecond(pFirstGrab, pSecondGrab) || @@ -315,7 +333,7 @@ AddPassiveGrabToList(ClientPtr client, GrabPtr pGrab) for (grab = wPassiveGrabs(pGrab->window); grab; grab = grab->next) { - if (GrabMatchesSecond(pGrab, grab)) + if (GrabMatchesSecond(pGrab, grab, FALSE)) { if (CLIENT_BITS(pGrab->resource) != CLIENT_BITS(grab->resource)) { @@ -397,7 +415,7 @@ DeletePassiveGrabFromList(GrabPtr pMinuendGrab) grab = grab->next) { if ((CLIENT_BITS(grab->resource) != CLIENT_BITS(pMinuendGrab->resource)) || - !GrabMatchesSecond(grab, pMinuendGrab)) + !GrabMatchesSecond(grab, pMinuendGrab, (grab->coreGrab))) continue; if (GrabSupersedesSecond(pMinuendGrab, grab)) { diff --git a/xorg-server/dix/main.c b/xorg-server/dix/main.c index fa1a934a3..90ddb6dd4 100644 --- a/xorg-server/dix/main.c +++ b/xorg-server/dix/main.c @@ -103,9 +103,6 @@ Equipment Corporation. #include "extnsionst.h" #include "privates.h" #include "registry.h" -#ifdef XPRINT -#include "DiPrint.h" -#endif #ifdef PANORAMIX #include "panoramiXsrv.h" #else @@ -121,7 +118,6 @@ Equipment Corporation. extern void Dispatch(void); -char *ConnectionInfo; xConnSetupPrefix connSetupPrefix; extern FontPtr defaultFont; @@ -237,52 +233,32 @@ static int indexForScanlinePad[ 65 ] = { #define MIN(a,b) (((a) < (b)) ? (a) : (b)) #endif -#ifdef __APPLE__ -void DarwinHandleGUI(int argc, char **argv, char **envp); -#endif +#ifdef XQUARTZ +#include <pthread.h> -int -main(int argc, char *argv[], char *envp[]) +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[]) +#else +int main(int argc, char *argv[], char *envp[]) +#endif { - int i, j, k, error; - char *xauthfile; + int i; HWEventQueueType alwaysCheckForInput[2]; ptw32_processInitialize(); display = "0"; - InitGlobals(); InitRegions(); -#ifdef XPRINT - PrinterInitGlobals(); -#endif - -#ifdef XQUARTZ - /* Quartz support on Mac OS X requires that the Cocoa event loop be in - * the main thread. This allows the X server main to be called again - * from another thread. */ - DarwinHandleGUI(argc, argv, envp); -#endif CheckUserParameters(argc, argv, envp); CheckUserAuthorization(); -#ifdef COMMANDLINE_CHALLENGED_OPERATING_SYSTEMS - ExpandCommandLine(&argc, &argv); -#endif - InitConnectionLimits(); - /* These are needed by some routines which are called from interrupt - * handlers, thus have no direct calling path back to main and thus - * can't be passed argc, argv as parameters */ - argcGlobal = argc; - argvGlobal = argv; - /* prep X authority file from environment; this can be overriden by a - * command line option */ - xauthfile = getenv("XAUTHORITY"); - if (xauthfile) InitAuthorization (xauthfile); ProcessCommandLine(argc, argv); alwaysCheckForInput[0] = 0; @@ -309,10 +285,7 @@ main(int argc, char *argv[], char *envp[]) { CreateWellKnownSockets(); InitProcVectors(); - clients = (ClientPtr *)xalloc(MAXCLIENTS * sizeof(ClientPtr)); - if (!clients) - FatalError("couldn't create client array"); - for (i=1; i<MAXCLIENTS; i++) + for (i=1; i<MAXCLIENTS; i++) clients[i] = NullClient; serverClient = (ClientPtr)xalloc(sizeof(ClientRec)); if (!serverClient) @@ -330,21 +303,6 @@ main(int argc, char *argv[], char *envp[]) SetInputCheck(&alwaysCheckForInput[0], &alwaysCheckForInput[1]); screenInfo.arraySize = MAXSCREENS; screenInfo.numScreens = 0; - screenInfo.numVideoScreens = -1; - WindowTable = (WindowPtr *)xalloc(MAXSCREENS * sizeof(WindowPtr)); - if (!WindowTable) - FatalError("couldn't create root window table"); - - /* - * Just in case the ddx doesnt supply a format for depth 1 (like qvss). - */ - j = indexForBitsPerPixel[ 1 ]; - k = indexForScanlinePad[ BITMAP_SCANLINE_PAD ]; - PixmapWidthPaddingInfo[1].padRoundUp = BITMAP_SCANLINE_PAD-1; - PixmapWidthPaddingInfo[1].padPixelsLog2 = answer[j][k]; - j = indexForBitsPerPixel[8]; /* bits per byte */ - PixmapWidthPaddingInfo[1].padBytesLog2 = answer[j][k]; - PixmapWidthPaddingInfo[1].bitsPerPixel = 1; InitAtoms(); InitEvents(); @@ -355,16 +313,10 @@ main(int argc, char *argv[], char *envp[]) dixResetRegistry(); ResetFontPrivateIndex(); InitCallbackManager(); - InitVisualWrap(); InitOutput(&screenInfo, argc, argv); -#ifdef XPRINT - PrinterInitOutput(&screenInfo, argc, argv); -#endif if (screenInfo.numScreens < 1) FatalError("no screens found"); - if (screenInfo.numVideoScreens < 0) - screenInfo.numVideoScreens = screenInfo.numScreens; InitExtensions(argc, argv); for (i = 0; i < screenInfo.numScreens; i++) { @@ -381,19 +333,10 @@ main(int argc, char *argv[], char *envp[]) if (!CreateRootWindow(pScreen)) FatalError("failed to create root window"); } - InitCoreDevices(); - InitInput(argc, argv); - if (InitAndStartDevices() != Success) - FatalError("failed to initialize core devices"); InitFonts(); - if (loadableFonts) - SetFontPath(serverClient, 0, (unsigned char *)defaultFontPath, - &error); - else { - if (SetDefaultFontPath(defaultFontPath) != Success) - ErrorF("failed to set default font path '%s'", - defaultFontPath); + 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); @@ -422,6 +365,11 @@ main(int argc, char *argv[], char *envp[]) for (i = 0; i < screenInfo.numScreens; i++) InitRootWindow(WindowTable[i]); DefineInitialRootWindow(WindowTable[0]); + + InitCoreDevices(); + InitInput(argc, argv); + InitAndStartDevices(); + dixSaveScreens(serverClient, SCREEN_SAVER_FORCER, ScreenSaverReset); #ifdef PANORAMIX @@ -437,10 +385,20 @@ main(int argc, char *argv[], char *envp[]) } } +#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); @@ -460,8 +418,9 @@ main(int argc, char *argv[], char *envp[]) config_fini(); - memset(WindowTable, 0, MAXSCREENS * sizeof(WindowPtr)); + memset(WindowTable, 0, sizeof(WindowTable)); CloseDownDevices(); + CloseDownEvents(); for (i = screenInfo.numScreens - 1; i >= 0; i--) { @@ -473,9 +432,6 @@ main(int argc, char *argv[], char *envp[]) xfree(screenInfo.screens[i]); screenInfo.numScreens = i; } - CloseDownEvents(); - xfree(WindowTable); - WindowTable = NULL; FreeFonts(); FreeAuditTimer(); @@ -517,7 +473,7 @@ SetVendorString(char *string) VendorString = string; } -static int padlength[4] = {0, 3, 2, 1}; +static const int padlength[4] = {0, 3, 2, 1}; #ifndef PANORAMIX static @@ -608,7 +564,7 @@ CreateConnectionBlock(void) root.maxInstalledMaps = pScreen->maxInstalledCmaps; root.rootVisualID = pScreen->rootVisual; root.backingStore = pScreen->backingStoreSupport; - root.saveUnders = pScreen->saveUnderSupport != NotUseful; + root.saveUnders = FALSE; root.rootDepth = pScreen->rootDepth; root.nDepths = pScreen->numDepths; memmove(pBuf, (char *)&root, sizeof(xWindowRoot)); diff --git a/xorg-server/dix/privates.c b/xorg-server/dix/privates.c index efb320463..ca03317bf 100644 --- a/xorg-server/dix/privates.c +++ b/xorg-server/dix/privates.c @@ -40,9 +40,8 @@ from The Open Group. #include "inputstr.h" struct _Private { - DevPrivateKey key; - pointer value; - struct _Private *next; + int state; + pointer value; }; typedef struct _PrivateDesc { @@ -50,22 +49,36 @@ typedef struct _PrivateDesc { unsigned size; CallbackListPtr initfuncs; CallbackListPtr deletefuncs; - struct _PrivateDesc *next; } PrivateDescRec; +#define PRIV_MAX 256 +#define PRIV_STEP 16 + /* list of all allocated privates */ -static PrivateDescRec *items = NULL; +static PrivateDescRec items[PRIV_MAX]; +static int nextPriv; -static _X_INLINE PrivateDescRec * +static PrivateDescRec * findItem(const DevPrivateKey key) { - PrivateDescRec *item = items; - while (item) { - if (item->key == key) - return item; - item = item->next; + if (!*key) { + if (nextPriv >= PRIV_MAX) + return NULL; + + items[nextPriv].key = key; + *key = nextPriv; + nextPriv++; } - return NULL; + + return items + *key; +} + +static _X_INLINE int +privateExists(PrivateRec **privates, const DevPrivateKey key) +{ + return *key && *privates && + (*privates)[0].state > *key && + (*privates)[*key].state; } /* @@ -75,21 +88,10 @@ _X_EXPORT int dixRequestPrivate(const DevPrivateKey key, unsigned size) { PrivateDescRec *item = findItem(key); - if (item) { - if (size > item->size) - item->size = size; - } else { - item = (PrivateDescRec *)xalloc(sizeof(PrivateDescRec)); - if (!item) - return FALSE; - memset(item, 0, sizeof(PrivateDescRec)); - - /* add privates descriptor */ - item->key = key; + if (!item) + return FALSE; + if (size > item->size) item->size = size; - item->next = items; - items = item; - } return TRUE; } @@ -100,25 +102,52 @@ _X_EXPORT pointer * dixAllocatePrivate(PrivateRec **privates, const DevPrivateKey key) { PrivateDescRec *item = findItem(key); + PrivateCallbackRec calldata; PrivateRec *ptr; - unsigned size = sizeof(PrivateRec); - - if (item) - size += item->size; + pointer value; + int oldsize, newsize; + + newsize = (*key / PRIV_STEP + 1) * PRIV_STEP; - ptr = (PrivateRec *)xcalloc(size, 1); - if (!ptr) + /* resize or init privates array */ + if (!item) return NULL; - ptr->key = key; - ptr->value = (size > sizeof(PrivateRec)) ? (ptr + 1) : NULL; - ptr->next = *privates; - *privates = ptr; - - /* call any init funcs and return */ - if (item) { - PrivateCallbackRec calldata = { key, &ptr->value }; - CallCallbacks(&item->initfuncs, &calldata); + + /* initialize privates array if necessary */ + if (!*privates) { + ptr = xcalloc(newsize, sizeof(*ptr)); + if (!ptr) + return NULL; + *privates = ptr; + (*privates)[0].state = newsize; + } + + oldsize = (*privates)[0].state; + + /* resize privates array if necessary */ + if (*key >= oldsize) { + ptr = xrealloc(*privates, newsize * sizeof(*ptr)); + if (!ptr) + return NULL; + memset(ptr + oldsize, 0, (newsize - oldsize) * sizeof(*ptr)); + *privates = ptr; + (*privates)[0].state = newsize; + } + + /* initialize slot */ + ptr = *privates + *key; + ptr->state = 1; + if (item->size) { + value = xcalloc(item->size, 1); + if (!value) + return NULL; + ptr->value = value; } + + calldata.key = key; + calldata.value = &ptr->value; + CallCallbacks(&item->initfuncs, &calldata); + return &ptr->value; } @@ -128,14 +157,10 @@ dixAllocatePrivate(PrivateRec **privates, const DevPrivateKey key) _X_EXPORT pointer dixLookupPrivate(PrivateRec **privates, const DevPrivateKey key) { - PrivateRec *rec = *privates; pointer *ptr; - while (rec) { - if (rec->key == key) - return rec->value; - rec = rec->next; - } + if (privateExists(privates, key)) + return (*privates)[*key].value; ptr = dixAllocatePrivate(privates, key); return ptr ? *ptr : NULL; @@ -147,13 +172,8 @@ dixLookupPrivate(PrivateRec **privates, const DevPrivateKey key) _X_EXPORT pointer * dixLookupPrivateAddr(PrivateRec **privates, const DevPrivateKey key) { - PrivateRec *rec = *privates; - - while (rec) { - if (rec->key == key) - return &rec->value; - rec = rec->next; - } + if (privateExists(privates, key)) + return &(*privates)[*key].value; return dixAllocatePrivate(privates, key); } @@ -164,16 +184,10 @@ dixLookupPrivateAddr(PrivateRec **privates, const DevPrivateKey key) _X_EXPORT int dixSetPrivate(PrivateRec **privates, const DevPrivateKey key, pointer val) { - PrivateRec *rec; - top: - rec = *privates; - while (rec) { - if (rec->key == key) { - rec->value = val; - return TRUE; - } - rec = rec->next; + if (privateExists(privates, key)) { + (*privates)[*key].value = val; + return TRUE; } if (!dixAllocatePrivate(privates, key)) @@ -187,27 +201,23 @@ dixSetPrivate(PrivateRec **privates, const DevPrivateKey key, pointer val) _X_EXPORT void dixFreePrivates(PrivateRec *privates) { - PrivateRec *ptr, *next; - PrivateDescRec *item; + int i; PrivateCallbackRec calldata; - /* first pass calls the delete callbacks */ - for (ptr = privates; ptr; ptr = ptr->next) { - item = findItem(ptr->key); - if (item) { - calldata.key = ptr->key; - calldata.value = &ptr->value; - CallCallbacks(&item->deletefuncs, &calldata); - } - } - - /* second pass frees the memory */ - ptr = privates; - while (ptr) { - next = ptr->next; - xfree(ptr); - ptr = next; - } + if (privates) + for (i = 1; i < privates->state; i++) + if (privates[i].state) { + /* call the delete callbacks */ + calldata.key = items[i].key; + calldata.value = &privates[i].value; + CallCallbacks(&items[i].deletefuncs, &calldata); + + /* free pre-allocated memory */ + if (items[i].size) + xfree(privates[i].value); + } + + xfree(privates); } /* @@ -218,11 +228,9 @@ dixRegisterPrivateInitFunc(const DevPrivateKey key, CallbackProcPtr callback, pointer data) { PrivateDescRec *item = findItem(key); - if (!item) { - if (!dixRequestPrivate(key, 0)) - return FALSE; - item = findItem(key); - } + if (!item) + return FALSE; + return AddCallback(&item->initfuncs, callback, data); } @@ -231,11 +239,9 @@ dixRegisterPrivateDeleteFunc(const DevPrivateKey key, CallbackProcPtr callback, pointer data) { PrivateDescRec *item = findItem(key); - if (!item) { - if (!dixRequestPrivate(key, 0)) - return FALSE; - item = findItem(key); - } + if (!item) + return FALSE; + return AddCallback(&item->deletefuncs, callback, data); } @@ -292,16 +298,17 @@ dixLookupPrivateOffset(RESTYPE type) int dixResetPrivates(void) { - PrivateDescRec *next; - - /* reset internal structures */ - while (items) { - next = items->next; - DeleteCallbackList(&items->initfuncs); - DeleteCallbackList(&items->deletefuncs); - xfree(items); - items = next; + int i; + + /* reset private descriptors */ + for (i = 1; i < nextPriv; i++) { + *items[i].key = 0; + DeleteCallbackList(&items[i].initfuncs); + DeleteCallbackList(&items[i].deletefuncs); } + nextPriv = 1; + + /* reset offsets */ if (offsets) xfree(offsets); offsetsSize = sizeof(offsetDefaults); diff --git a/xorg-server/dix/property.c b/xorg-server/dix/property.c index 8b66ad6a2..7149f7c8c 100644 --- a/xorg-server/dix/property.c +++ b/xorg-server/dix/property.c @@ -80,11 +80,11 @@ PrintPropertys(WindowPtr pWin) pProp = pWin->userProps; while (pProp) { - ErrorF( "%x %x\n", pProp->propertyName, pProp->type); - ErrorF("property format: %d\n", pProp->format); - ErrorF("property data: \n"); + ErrorF("[dix] %x %x\n", pProp->propertyName, pProp->type); + ErrorF("[dix] property format: %d\n", pProp->format); + ErrorF("[dix] property data: \n"); for (j=0; j<(pProp->format/8)*pProp->size; j++) - ErrorF("%c\n", pProp->data[j]); + ErrorF("[dix] %c\n", pProp->data[j]); pProp = pProp->next; } } diff --git a/xorg-server/dix/protocol.txt b/xorg-server/dix/protocol.txt index 0a85ca872..364f13e31 100644 --- a/xorg-server/dix/protocol.txt +++ b/xorg-server/dix/protocol.txt @@ -296,6 +296,13 @@ R021 RANDR:SetCrtcConfig R022 RANDR:GetCrtcGammaSize R023 RANDR:GetCrtcGamma R024 RANDR:SetCrtcGamma +R025 RANDR:GetScreenResourcesCurrent +R026 RANDR:SetCrtcTransform +R027 RANDR:GetCrtcTransform +R028 RANDR:GetPanning +R029 RANDR:SetPanning +R030 RANDR:SetOutputPrimary +R031 RANDR:GetOutputPrimary V000 RANDR:ScreenChangeNotify V001 RANDR:Notify E000 RANDR:BadRROutput @@ -731,11 +738,6 @@ E000 XC-APPGROUP:BadAppGroup R000 XC-MISC:GetVersion R001 XC-MISC:GetXIDRange R002 XC-MISC:GetXIDList -R000 XEVIE:QueryVersion -R001 XEVIE:Start -R002 XEVIE:End -R003 XEVIE:Send -R004 XEVIE:SelectInput R000 XFIXES:QueryVersion R001 XFIXES:ChangeSaveSet R002 XFIXES:SelectSelectionInput @@ -942,6 +944,10 @@ R032 XInputExtension:DeviceBell R033 XInputExtension:SetDeviceValuators R034 XInputExtension:GetDeviceControl R035 XInputExtension:ChangeDeviceControl +R036 XInputExtension:ListDeviceProperties +R037 XInputExtension:ChangeDeviceProperty +R038 XInputExtension:DeleteDeviceProperty +R039 XInputExtension:GetDeviceProperty V000 XInputExtension:DeviceValuator V001 XInputExtension:DeviceKeyPress V002 XInputExtension:DeviceKeyRelease @@ -958,6 +964,7 @@ V012 XInputExtension:ChangeDeviceNotify V013 XInputExtension:DeviceKeystateNotify V014 XInputExtension:DeviceButtonstateNotify V015 XInputExtension:DevicePresenceNotify +V016 XInputExtension:DevicePropertyNotify E000 XInputExtension:BadDevice E001 XInputExtension:BadEvent E002 XInputExtension:BadMode diff --git a/xorg-server/dix/ptrveloc.c b/xorg-server/dix/ptrveloc.c new file mode 100644 index 000000000..e9d4e882f --- /dev/null +++ b/xorg-server/dix/ptrveloc.c @@ -0,0 +1,939 @@ +/* + * + * Copyright © 2006-2008 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 <inputstr.h> +#include <assert.h> +#include <os.h> + +/***************************************************************************** + * Predictable pointer acceleration + * + * 2006-2008 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 (potentially at runtime). + * the classic profile is intended to cleanly perform old-style + * function selection (threshold =/!= 0) + * + ****************************************************************************/ + +/* fwds */ +static inline void +FeedFilterStage(FilterStagePtr s, float value, int tdiff); +extern void +InitFilterStage(FilterStagePtr s, float rdecay, int lutsize); +void +CleanupFilterChain(DeviceVelocityPtr s); +int +SetAccelerationProfile(DeviceVelocityPtr s, int profile_num); +void +InitFilterChain(DeviceVelocityPtr s, float rdecay, float degression, + int stages, int lutsize); +void +CleanupFilterChain(DeviceVelocityPtr s); +static float +SimpleSmoothProfile(DeviceVelocityPtr pVel, float velocity, + float threshold, float acc); + + + +/*#define PTRACCEL_DEBUGGING*/ + +#ifdef PTRACCEL_DEBUGGING +#define DebugAccelF ErrorF +#else +#define DebugAccelF(...) /* */ +#endif + +/******************************** + * Init/Uninit etc + *******************************/ + +/** + * Init struct so it should match the average case + */ +void +InitVelocityData(DeviceVelocityPtr s) +{ + memset(s, 0, sizeof(DeviceVelocityRec)); + + s->corr_mul = 10.0; /* dots per 10 milisecond should be usable */ + s->const_acceleration = 1.0; /* no acceleration/deceleration */ + s->reset_time = 300; + s->use_softening = 1; + s->min_acceleration = 1.0; /* don't decelerate */ + s->coupling = 0.25; + s->average_accel = TRUE; + SetAccelerationProfile(s, AccelProfileClassic); + InitFilterChain(s, (float)1.0/20.0, 1, 1, 40); +} + + +/** + * Clean up + */ +static void +FreeVelocityData(DeviceVelocityPtr s){ + CleanupFilterChain(s); + SetAccelerationProfile(s, -1); +} + + +/* + * dix uninit helper, called through scheme + */ +void +AccelerationDefaultCleanup(DeviceIntPtr pDev) +{ + /*sanity check*/ + if( pDev->valuator->accelScheme.AccelSchemeProc == acceleratePointerPredictable + && pDev->valuator->accelScheme.accelData != NULL){ + pDev->valuator->accelScheme.AccelSchemeProc = NULL; + FreeVelocityData(pDev->valuator->accelScheme.accelData); + xfree(pDev->valuator->accelScheme.accelData); + pDev->valuator->accelScheme.accelData = NULL; + } +} + +/********************* + * Filtering logic + ********************/ + +/** +Initialize a filter chain. +Expected result is a series of filters, each progressively more integrating. + +This allows for two strategies: Either you have one filter which is reasonable +and is being coupled to account for fast-changing input, or you have 'one for +every situation'. You might want to have tighter coupling then, e.g. 0.1. +In the filter stats, you can see if a reasonable filter useage emerges. +*/ +void +InitFilterChain(DeviceVelocityPtr s, float rdecay, float progression, int stages, int lutsize) +{ + int fn; + if((stages > 1 && progression < 1.0f) || 0 == progression){ + ErrorF("(dix ptracc) invalid filter chain progression specified\n"); + return; + } + /* Block here to support runtime filter adjustment */ + OsBlockSignals(); + for(fn = 0; fn < MAX_VELOCITY_FILTERS; fn++){ + if(fn < stages){ + InitFilterStage(&s->filters[fn], rdecay, lutsize); + }else{ + InitFilterStage(&s->filters[fn], 0, 0); + } + rdecay /= progression; + } + /* release again. Should the input loop be threaded, we also need + * memory release here (in principle). + */ + OsReleaseSignals(); +} + + +void +CleanupFilterChain(DeviceVelocityPtr s) +{ + int fn; + + for(fn = 0; fn < MAX_VELOCITY_FILTERS; fn++) + InitFilterStage(&s->filters[fn], 0, 0); +} + +static inline void +StuffFilterChain(DeviceVelocityPtr s, float value) +{ + int fn; + + for(fn = 0; fn < MAX_VELOCITY_FILTERS; fn++){ + if(s->filters[fn].rdecay != 0) + s->filters[fn].current = value; + else break; + } +} + + +/** + * Adjust weighting decay and lut for a stage + * The weight fn is designed so its integral 0->inf is unity, so we end + * up with a stable (basically IIR) filter. It always draws + * towards its more current input values, which have more weight the older + * the last input value is. + */ +void +InitFilterStage(FilterStagePtr s, float rdecay, int lutsize) +{ + int x; + float *newlut; + float *oldlut; + + s->fading_lut_size = 0; /* prevent access */ + + if(lutsize > 0){ + newlut = xalloc (sizeof(float)* lutsize); + if(!newlut) + return; + for(x = 0; x < lutsize; x++) + newlut[x] = pow(0.5, ((float)x) * rdecay); + }else{ + newlut = NULL; + } + oldlut = s->fading_lut; + s->fading_lut = newlut; + s->rdecay = rdecay; + s->fading_lut_size = lutsize; + s->current = 0; + if(oldlut != NULL) + xfree(oldlut); +} + + +static inline void +FeedFilterChain(DeviceVelocityPtr s, float value, int tdiff) +{ + int fn; + + for(fn = 0; fn < MAX_VELOCITY_FILTERS; fn++){ + if(s->filters[fn].rdecay != 0) + FeedFilterStage(&s->filters[fn], value, tdiff); + else break; + } +} + + +static inline void +FeedFilterStage(FilterStagePtr s, float value, int tdiff){ + float fade; + if(tdiff < s->fading_lut_size) + fade = s->fading_lut[tdiff]; + else + fade = pow(0.5, ((float)tdiff) * s->rdecay); + s->current *= fade; /* fade out old velocity */ + s->current += value * (1.0f - fade); /* and add up current */ +} + +/** + * Select the most filtered matching result. Also, the first + * mismatching filter may be set to value (coupling). + */ +static inline float +QueryFilterChain( + DeviceVelocityPtr s, + float value) +{ + int fn, rfn = 0, cfn = -1; + float cur, result = value; + + /* try to retrieve most integrated result 'within range' + * Assumption: filter are in order least to most integrating */ + for(fn = 0; fn < MAX_VELOCITY_FILTERS; fn++){ + if(0.0f == s->filters[fn].rdecay) + break; + cur = s->filters[fn].current; + + if (fabs(value - cur) <= (s->coupling * (value + cur))){ + result = cur; + rfn = fn + 1; /*remember result determining filter */ + } else if(cfn == -1){ + cfn = fn; /* remember first mismatching filter */ + } + } + + s->statistics.filter_usecount[rfn]++; + DebugAccelF("(dix ptracc) result from stage %i, input %.2f, output %.2f\n", + rfn, value, result); + + /* override first mismatching current (coupling) so the filter + * catches up quickly. */ + if(cfn != -1) + s->filters[cfn].current = result; + + return result; +} + +/******************************** + * velocity computation + *******************************/ + +/** + * return the axis if mickey is insignificant and axis-aligned, + * -1 otherwise + * 1 for x-axis + * 2 for y-axis + */ +static inline short +GetAxis(int dx, int dy){ + if(dx == 0 || dy == 0){ + if(dx == 1 || dx == -1) + return 1; + if(dy == 1 || dy == -1) + return 2; + return -1; + }else{ + return -1; + } +} + + +/** + * Perform velocity approximation + * return true if non-visible state reset is suggested + */ +static short +ProcessVelocityData( + DeviceVelocityPtr s, + int dx, + int dy, + int time) +{ + float cvelocity; + + int diff = time - s->lrm_time; + int cur_ax, last_ax; + short reset = (diff >= s->reset_time); + + /* remember last round's result */ + s->last_velocity = s->velocity; + cur_ax = GetAxis(dx, dy); + last_ax = GetAxis(s->last_dx, s->last_dy); + + if(cur_ax != last_ax && cur_ax != -1 && last_ax != -1 && !reset){ + /* correct for the error induced when diagonal movements are + reported as alternating axis mickeys */ + dx += s->last_dx; + dy += s->last_dy; + diff += s->last_diff; + s->last_diff = time - s->lrm_time; /* prevent repeating add-up */ + DebugAccelF("(dix ptracc) axial correction\n"); + }else{ + s->last_diff = diff; + } + + /* + * cvelocity is not a real velocity yet, more a motion delta. constant + * acceleration is multiplied here to make the velocity an on-screen + * velocity (pix/t as opposed to [insert unit]/t). This is intended to + * make multiple devices with widely varying ConstantDecelerations respond + * similar to acceleration controls. + */ + cvelocity = (float)sqrt(dx*dx + dy*dy) * s->const_acceleration; + + s->lrm_time = time; + + if (s->reset_time < 0 || diff < 0) { /* reset disabled or timer overrun? */ + /* simply set velocity from current movement, no reset. */ + s->velocity = cvelocity; + return FALSE; + } + + if (diff == 0) + diff = 1; /* prevent div-by-zero, though it shouldn't happen anyway*/ + + /* translate velocity to dots/ms (somewhat intractable in integers, + so we multiply by some per-device adjustable factor) */ + cvelocity = cvelocity * s->corr_mul / (float)diff; + + /* short-circuit: when nv-reset the rest can be skipped */ + if(reset == TRUE){ + /* + * we don't really have a velocity here, since diff includes inactive + * time. This is dealt with in ComputeAcceleration. + */ + StuffFilterChain(s, cvelocity); + s->velocity = s->last_velocity = cvelocity; + s->last_reset = TRUE; + DebugAccelF("(dix ptracc) non-visible state reset\n"); + return TRUE; + } + + if(s->last_reset == TRUE){ + /* + * when here, we're probably processing the second mickey of a starting + * stroke. This happens to be the first time we can reasonably pretend + * that cvelocity is an actual velocity. Thus, to opt precision, we + * stuff that into the filter chain. + */ + s->last_reset = FALSE; + DebugAccelF("(dix ptracc) after-reset vel:%.3f\n", cvelocity); + StuffFilterChain(s, cvelocity); + s->velocity = cvelocity; + return FALSE; + } + + /* feed into filter chain */ + FeedFilterChain(s, cvelocity, diff); + + /* perform coupling and decide final value */ + s->velocity = QueryFilterChain(s, cvelocity); + + DebugAccelF("(dix ptracc) guess: vel=%.3f diff=%d %i|%i|%i|%i|%i|%i|%i|%i|%i\n", + s->velocity, diff, + s->statistics.filter_usecount[0], s->statistics.filter_usecount[1], + s->statistics.filter_usecount[2], s->statistics.filter_usecount[3], + s->statistics.filter_usecount[4], s->statistics.filter_usecount[5], + s->statistics.filter_usecount[6], s->statistics.filter_usecount[7], + s->statistics.filter_usecount[8]); + return FALSE; +} + + +/** + * 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 s, + int dx, + int dy, + float* fdx, + float* fdy, + short do_soften) +{ + if (do_soften && s->use_softening) { + *fdx = ApplySimpleSoftening(s->last_dx, dx); + *fdy = ApplySimpleSoftening(s->last_dy, dy); + } else { + *fdx = dx; + *fdy = dy; + } + + *fdx *= s->const_acceleration; + *fdy *= s->const_acceleration; +} + +/* + * compute the acceleration for given velocity and enforce min_acceleartion + */ +static float +BasicComputeAcceleration( + DeviceVelocityPtr pVel, + float velocity, + float threshold, + float acc){ + + float result; + result = pVel->Profile(pVel, velocity, threshold, acc); + + /* enforce min_acceleration */ + if (result < pVel->min_acceleration) + result = pVel->min_acceleration; + return result; +} + +/** + * Compute acceleration. Takes into account averaging, nv-reset, etc. + */ +static float +ComputeAcceleration( + DeviceVelocityPtr vel, + float threshold, + float acc){ + float res; + + if(vel->last_reset){ + DebugAccelF("(dix ptracc) profile skipped\n"); + /* + * This is intended to override the first estimate of a stroke, + * which is too low (see ProcessVelocityData). 1 should make sure + * the mickey is seen on screen. + */ + 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(vel, vel->velocity, threshold, acc); + res += BasicComputeAcceleration(vel, vel->last_velocity, threshold, acc); + res += 4.0f * BasicComputeAcceleration(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(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( + DeviceVelocityPtr pVel, + 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( + DeviceVelocityPtr pVel, + float velocity, + float threshold, + float acc) +{ + if (threshold) { + return SimpleSmoothProfile (pVel, + velocity, + threshold, + acc); + } else { + return PolynomialAccelerationProfile (pVel, + 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( + DeviceVelocityPtr pVel, + 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 pVel->min_acceleration; + vel_dist = velocity - threshold; + return (pow(acc, vel_dist)) * pVel->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( + DeviceVelocityPtr pVel, + 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( + DeviceVelocityPtr pVel, + 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 += pVel->min_acceleration; + return res; +} + + +static float +LinearProfile( + DeviceVelocityPtr pVel, + float velocity, + float threshold, + float acc) +{ + return acc * velocity; +} + + +/** + * 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 -1. + * returns FALSE (0) if profile number is unavailable. + */ +_X_EXPORT int +SetAccelerationProfile( + DeviceVelocityPtr s, + int profile_num) +{ + PointerAccelerationProfileFunc profile; + switch(profile_num){ + case -1: + profile = NULL; /* Special case to uninit properly */ + break; + case AccelProfileClassic: + profile = ClassicProfile; + break; + case AccelProfileDeviceSpecific: + if(NULL == s->deviceSpecificProfile) + return FALSE; + profile = s->deviceSpecificProfile; + break; + case AccelProfilePolynomial: + profile = PolynomialAccelerationProfile; + break; + case AccelProfileSmoothLinear: + profile = SmoothLinearProfile; + break; + case AccelProfileSimple: + profile = SimpleSmoothProfile; + break; + case AccelProfilePower: + profile = PowerProfile; + break; + case AccelProfileLinear: + profile = LinearProfile; + break; + case AccelProfileReserved: + /* reserved for future use, e.g. a user-defined profile */ + default: + return FALSE; + } + if(s->profile_private != NULL){ + /* Here one could free old profile-private data */ + xfree(s->profile_private); + s->profile_private = NULL; + } + /* Here one could init profile-private data */ + s->Profile = profile; + s->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. + */ +_X_EXPORT void +SetDeviceSpecificAccelerationProfile( + DeviceVelocityPtr s, + PointerAccelerationProfileFunc profile) +{ + if(s) + s->deviceSpecificProfile = profile; +} + +/** + * Use this function to obtain a DeviceVelocityPtr for a device. Will return NULL if + * the predictable acceleration scheme is not in effect. + */ +_X_EXPORT DeviceVelocityPtr +GetDevicePredictableAccelData( + DeviceIntPtr pDev) +{ + /*sanity check*/ + if(!pDev){ + ErrorF("[dix] accel: DeviceIntPtr was NULL"); + return NULL; + } + if( pDev->valuator && + pDev->valuator->accelScheme.AccelSchemeProc == + acceleratePointerPredictable && + pDev->valuator->accelScheme.accelData != NULL){ + + return (DeviceVelocityPtr)pDev->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 pDev, + 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) pDev->valuator->accelScheme.accelData; + float fdx, fdy; /* no need to init */ + + if (!num_valuators || !valuators || !velocitydata) + 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){ + /* reset nonvisible state? */ + if (ProcessVelocityData(velocitydata, dx , dy, evtime)) { + /* set to center of pixel. makes sense as long as there are no + * means of passing on sub-pixel values. + */ + pDev->last.remainder[0] = pDev->last.remainder[1] = 0.5f; + /* prevent softening (somewhat quirky solution, + as it depends on the algorithm) */ + velocitydata->last_dx = dx; + velocitydata->last_dy = dy; + } + + if (pDev->ptrfeed && pDev->ptrfeed->ctrl.num) { + /* invoke acceleration profile to determine acceleration */ + mult = ComputeAcceleration (velocitydata, + pDev->ptrfeed->ctrl.threshold, + (float)pDev->ptrfeed->ctrl.num / + (float)pDev->ptrfeed->ctrl.den); + + if(mult != 1.0 || velocitydata->const_acceleration != 1.0) { + ApplySofteningAndConstantDeceleration( velocitydata, + dx, dy, + &fdx, &fdy, + mult > 1.0); + if (dx) { + pDev->last.remainder[0] = mult * fdx + pDev->last.remainder[0]; + *px = (int)pDev->last.remainder[0]; + pDev->last.remainder[0] = pDev->last.remainder[0] - (float)*px; + } + if (dy) { + pDev->last.remainder[1] = mult * fdy + pDev->last.remainder[1]; + *py = (int)pDev->last.remainder[1]; + pDev->last.remainder[1] = pDev->last.remainder[1] - (float)*py; + } + } + } + } + /* 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 pDev, + 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 (pDev->ptrfeed && pDev->ptrfeed->ctrl.num) { + /* modeled from xf86Events.c */ + if (pDev->ptrfeed->ctrl.threshold) { + if ((abs(dx) + abs(dy)) >= pDev->ptrfeed->ctrl.threshold) { + pDev->last.remainder[0] = ((float)dx * + (float)(pDev->ptrfeed->ctrl.num)) / + (float)(pDev->ptrfeed->ctrl.den) + + pDev->last.remainder[0]; + if (px) { + *px = (int)pDev->last.remainder[0]; + pDev->last.remainder[0] = pDev->last.remainder[0] - + (float)(*px); + } + + pDev->last.remainder[1] = ((float)dy * + (float)(pDev->ptrfeed->ctrl.num)) / + (float)(pDev->ptrfeed->ctrl.den) + + pDev->last.remainder[1]; + if (py) { + *py = (int)pDev->last.remainder[1]; + pDev->last.remainder[1] = pDev->last.remainder[1] - + (float)(*py); + } + } + } + else { + mult = pow((float)dx * (float)dx + (float)dy * (float)dy, + ((float)(pDev->ptrfeed->ctrl.num) / + (float)(pDev->ptrfeed->ctrl.den) - 1.0) / + 2.0) / 2.0; + if (dx) { + pDev->last.remainder[0] = mult * (float)dx + + pDev->last.remainder[0]; + *px = (int)pDev->last.remainder[0]; + pDev->last.remainder[0] = pDev->last.remainder[0] - + (float)(*px); + } + if (dy) { + pDev->last.remainder[1] = mult * (float)dy + + pDev->last.remainder[1]; + *py = (int)pDev->last.remainder[1]; + pDev->last.remainder[1] = pDev->last.remainder[1] - + (float)(*py); + } + } + } +} diff --git a/xorg-server/dix/resource.c b/xorg-server/dix/resource.c index f318de3c0..7b0441ee9 100644 --- a/xorg-server/dix/resource.c +++ b/xorg-server/dix/resource.c @@ -339,7 +339,7 @@ AvailableID( return 0; } -_X_EXPORT void +void GetXIDRange(int client, Bool server, XID *minp, XID *maxp) { XID id, maxid; @@ -390,7 +390,7 @@ GetXIDRange(int client, Bool server, XID *minp, XID *maxp) * invented, but this will be used so rarely that this should suffice. */ -_X_EXPORT unsigned int +unsigned int GetXIDList(ClientPtr pClient, unsigned count, XID *pids) { unsigned int found = 0; @@ -452,7 +452,7 @@ AddResource(XID id, RESTYPE type, pointer value) rrec = &clientTable[client]; if (!rrec->buckets) { - ErrorF("AddResource(%lx, %lx, %lx), client=%d \n", + ErrorF("[dix] AddResource(%lx, %lx, %lx), client=%d \n", (unsigned long)id, type, (unsigned long)value, client); FatalError("client not in use\n"); } diff --git a/xorg-server/dix/selection.c b/xorg-server/dix/selection.c index 6a9198e96..c5427e004 100644 --- a/xorg-server/dix/selection.c +++ b/xorg-server/dix/selection.c @@ -189,7 +189,7 @@ ProcSetSelectionOwner(ClientPtr client) event.u.selectionClear.time = time.milliseconds; event.u.selectionClear.window = pSel->window; event.u.selectionClear.atom = pSel->selection; - TryClientEvents(pSel->client, &event, 1, NoEventMask, + TryClientEvents(pSel->client, NULL, &event, 1, NoEventMask, NoEventMask /* CantBeFiltered */, NullGrab); } } @@ -294,7 +294,7 @@ ProcConvertSelection(ClientPtr client) event.u.selectionRequest.selection = stuff->selection; event.u.selectionRequest.target = stuff->target; event.u.selectionRequest.property = stuff->property; - if (TryClientEvents(pSel->client, &event, 1, NoEventMask, + if (TryClientEvents(pSel->client, NULL, &event, 1, NoEventMask, NoEventMask /* CantBeFiltered */, NullGrab)) return client->noClientException; } @@ -305,7 +305,7 @@ ProcConvertSelection(ClientPtr client) event.u.selectionNotify.selection = stuff->selection; event.u.selectionNotify.target = stuff->target; event.u.selectionNotify.property = None; - TryClientEvents(client, &event, 1, NoEventMask, + TryClientEvents(client, NULL, &event, 1, NoEventMask, NoEventMask /* CantBeFiltered */, NullGrab); return client->noClientException; } diff --git a/xorg-server/dix/strcasecmp.c b/xorg-server/dix/strcasecmp.c deleted file mode 100644 index ca1051dc1..000000000 --- a/xorg-server/dix/strcasecmp.c +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (c) 1987, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifdef HAVE_DIX_CONFIG_H -#include <dix-config.h> -#endif - -#include <ctype.h> -#include "dix.h" - -#ifdef NEED_STRCASECMP -int -xstrcasecmp(const char *str1, const char *str2) -{ - const u_char *us1 = (const u_char *)str1, *us2 = (const u_char *)str2; - - while (tolower(*us1) == tolower(*us2)) { - if (*us1++ == '\0') - return (0); - us2++; - } - - return (tolower(*us1) - tolower(*us2)); -} -#endif - -#ifdef NEED_STRNCASECMP -int -xstrncasecmp(const char *s1, const char *s2, size_t n) -{ - if (n != 0) { - const u_char *us1 = (const u_char *)s1, *us2 = (const u_char *)s2; - - do { - if (tolower(*us1) != tolower(*us2++)) - return (tolower(*us1) - tolower(*--us2)); - if (*us1++ == '\0') - break; - } while (--n != 0); - } - - return 0; -} -#endif diff --git a/xorg-server/dix/strcasestr.c b/xorg-server/dix/strcasestr.c deleted file mode 100644 index b3d45495c..000000000 --- a/xorg-server/dix/strcasestr.c +++ /dev/null @@ -1,64 +0,0 @@ -/*- - * Copyright (c) 1990, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Chris Torek. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifdef HAVE_DIX_CONFIG_H -#include <dix-config.h> -#endif - -#include <ctype.h> -#include <string.h> -#include "dix.h" - -/* - * Find the first occurrence of find in s, ignore case. - */ -#ifdef NEED_STRCASESTR -char * -xstrcasestr(const char *s, const char *find) -{ - char c, sc; - size_t len; - - if ((c = *find++) != 0) { - c = tolower((unsigned char)c); - len = strlen(find); - do { - do { - if ((sc = *s++) == 0) - return (NULL); - } while ((char)tolower((unsigned char)sc) != c); - } while (strncasecmp(s, find, len) != 0); - s--; - } - return ((char *)s); -} -#endif diff --git a/xorg-server/dix/tables.c b/xorg-server/dix/tables.c index 2200e3ceb..e4f93661c 100644 --- a/xorg-server/dix/tables.c +++ b/xorg-server/dix/tables.c @@ -70,7 +70,7 @@ int (* InitialVector[3]) ( ProcEstablishConnection }; -_X_EXPORT int (* ProcVector[256]) ( +int (* ProcVector[256]) ( ClientPtr /* client */ ) = { @@ -378,7 +378,7 @@ _X_EXPORT EventSwapPtr EventSwapVector[128] = }; -_X_EXPORT ReplySwapPtr ReplySwapVector[256] = +ReplySwapPtr ReplySwapVector[256] = { ReplyNotSwappd, ReplyNotSwappd, diff --git a/xorg-server/dix/window.c b/xorg-server/dix/window.c index 834c26b12..c19990ac1 100644 --- a/xorg-server/dix/window.c +++ b/xorg-server/dix/window.c @@ -110,6 +110,7 @@ Equipment Corporation. #include "validate.h" #include "windowstr.h" #include "input.h" +#include "inputstr.h" #include "resource.h" #include "colormapst.h" #include "cursorstr.h" @@ -122,10 +123,8 @@ Equipment Corporation. #endif #include "dixevents.h" #include "globals.h" +#include "mi.h" /* miPaintWindow */ -#ifdef XAPPGROUP -#include "appgroup.h" -#endif #include "privates.h" #include "xace.h" @@ -136,16 +135,28 @@ Equipment Corporation. * GetWindowAttributes, DeleteWindow, DestroySubWindows, * HandleSaveSet, ReparentWindow, MapWindow, MapSubWindows, * UnmapWindow, UnmapSubWindows, ConfigureWindow, CirculateWindow, - * + * ChangeWindowDeviceCursor ******/ static unsigned char _back_lsb[4] = {0x88, 0x22, 0x44, 0x11}; static unsigned char _back_msb[4] = {0x11, 0x44, 0x22, 0x88}; +static Bool WindowParentHasDeviceCursor(WindowPtr pWin, + DeviceIntPtr pDev, + CursorPtr pCurs); +static Bool +WindowSeekDeviceCursor(WindowPtr pWin, + DeviceIntPtr pDev, + DevCursNodePtr* pNode, + DevCursNodePtr* pPrev); + _X_EXPORT int screenIsSaved = SCREEN_SAVER_OFF; _X_EXPORT ScreenSaverStuffRec savedScreenInfo[MAXSCREENS]; +static int FocusPrivatesKeyIndex; +_X_EXPORT DevPrivateKey FocusPrivatesKey = &FocusPrivatesKeyIndex; + static Bool TileScreenSaver(int i, int kind); @@ -169,9 +180,6 @@ static Bool TileScreenSaver(int i, int kind); #define SubStrSend(pWin,pParent) (StrSend(pWin) || SubSend(pParent)) -_X_EXPORT int numSaveUndersViewable = 0; -_X_EXPORT int deltaSaveUndersViewable = 0; - #ifdef DEBUG /****** * PrintWindowTree @@ -187,8 +195,9 @@ PrintChildren(WindowPtr p1, int indent) while (p1) { p2 = p1->firstChild; - for (i=0; i<indent; i++) ErrorF( " "); - ErrorF( "%lx\n", p1->drawable.id); + ErrorF("[dix] "); + for (i=0; i<indent; i++) ErrorF(" "); + ErrorF("%lx\n", p1->drawable.id); miPrintRegion(&p1->clipList); PrintChildren(p2, indent+4); p1 = p1->nextSib; @@ -203,7 +212,7 @@ PrintWindowTree(void) for (i=0; i<screenInfo.numScreens; i++) { - ErrorF( "WINDOW %d\n", i); + ErrorF("[dix] WINDOW %d\n", i); pWin = WindowTable[i]; miPrintRegion(&pWin->clipList); p1 = pWin->firstChild; @@ -258,8 +267,6 @@ int defaultBackingStore = NotUseful; /* hack to force no backing store */ Bool disableBackingStore = FALSE; Bool enableBackingStore = FALSE; -/* hack to force no save unders */ -Bool disableSaveUnders = FALSE; static void SetWindowToDefaults(WindowPtr pWin) @@ -292,6 +299,10 @@ SetWindowToDefaults(WindowPtr pWin) pWin->forcedBS = FALSE; pWin->redirectDraw = RedirectDrawNone; pWin->forcedBG = FALSE; + +#ifdef ROOTLESS + pWin->rootlessUnhittable = FALSE; +#endif } static void @@ -387,14 +398,24 @@ CreateRootWindow(ScreenPtr pScreen) pWin->optional->userProps = NULL; pWin->optional->backingBitPlanes = ~0L; pWin->optional->backingPixel = 0; -#ifdef SHAPE pWin->optional->boundingShape = NULL; pWin->optional->clipShape = NULL; pWin->optional->inputShape = NULL; -#endif -#ifdef XINPUT pWin->optional->inputMasks = NULL; -#endif + pWin->optional->deviceCursors = NULL; + pWin->optional->geMasks = (GenericClientMasksPtr)xcalloc(1, sizeof(GenericClientMasksRec)); + if (!pWin->optional->geMasks) + { + xfree(pWin->optional); + return FALSE; + } + + pWin->optional->access.perm = NULL; + pWin->optional->access.deny = NULL; + pWin->optional->access.nperm = 0; + pWin->optional->access.ndeny = 0; + pWin->optional->access.defaultRule = 0; + pWin->optional->colormap = pScreen->defColormap; pWin->optional->visual = pScreen->rootVisual; @@ -440,20 +461,7 @@ CreateRootWindow(ScreenPtr pScreen) if (enableBackingStore) pScreen->backingStoreSupport = Always; -#ifdef DO_SAVE_UNDERS - if ((pScreen->backingStoreSupport != NotUseful) && - (pScreen->saveUnderSupport == NotUseful)) - { - /* - * If the screen has backing-store but no save-unders, let the - * clients know we can support save-unders using backing-store. - */ - pScreen->saveUnderSupport = USE_DIX_SAVE_UNDERS; - } -#endif /* DO_SAVE_UNDERS */ - - if (disableSaveUnders) - pScreen->saveUnderSupport = NotUseful; + pScreen->saveUnderSupport = NotUseful; return TRUE; } @@ -472,15 +480,15 @@ InitRootWindow(WindowPtr pWin) pWin->optional->cursor = rootCursor; rootCursor->refcnt++; - if (!blackRoot && !whiteRoot) { + + if (party_like_its_1989) { MakeRootTile(pWin); backFlag |= CWBackPixmap; - } - else { - if (blackRoot) - pWin->background.pixel = pScreen->blackPixel; - else + } else { + if (whiteRoot) pWin->background.pixel = pScreen->whitePixel; + else + pWin->background.pixel = pScreen->blackPixel; backFlag |= CWBackPixel; } @@ -600,14 +608,6 @@ CreateWindow(Window wid, WindowPtr pParent, int x, int y, unsigned w, if (!ancwopt) ancwopt = FindWindowWithOptional(pParent)->optional; if (visual == CopyFromParent) { -#ifdef XAPPGROUP - VisualID ag_visual; - - if (client->appgroup && !pParent->parent && - (ag_visual = XagRootVisual (client))) - visual = ag_visual; - else -#endif visual = ancwopt->visual; } @@ -797,6 +797,8 @@ CreateWindow(Window wid, WindowPtr pParent, int x, int y, unsigned w, static void DisposeWindowOptional (WindowPtr pWin) { + GenericMaskPtr gmask = NULL, next = NULL; + if (!pWin->optional) return; /* @@ -810,6 +812,37 @@ DisposeWindowOptional (WindowPtr pWin) } else pWin->cursorIsNone = TRUE; + + if (pWin->optional->deviceCursors) + { + DevCursorList pList; + DevCursorList pPrev; + pList = pWin->optional->deviceCursors; + while(pList) + { + if (pList->cursor) + FreeCursor(pList->cursor, (XID)0); + pPrev = pList; + pList = pList->next; + xfree(pPrev); + } + pWin->optional->deviceCursors = NULL; + } + + xfree(pWin->optional->access.perm); + xfree(pWin->optional->access.deny); + + /* Remove generic event mask allocations */ + if (pWin->optional->geMasks) + gmask = pWin->optional->geMasks->geClients; + while(gmask) + { + next = gmask->next; + xfree(gmask); + gmask = next; + } + xfree (pWin->optional->geMasks); + xfree (pWin->optional); pWin->optional = NULL; } @@ -826,14 +859,12 @@ FreeWindowResources(WindowPtr pWin) REGION_UNINIT(pScreen, &pWin->winSize); REGION_UNINIT(pScreen, &pWin->borderClip); REGION_UNINIT(pScreen, &pWin->borderSize); -#ifdef SHAPE if (wBoundingShape (pWin)) REGION_DESTROY(pScreen, wBoundingShape (pWin)); if (wClipShape (pWin)) REGION_DESTROY(pScreen, wClipShape (pWin)); if (wInputShape (pWin)) REGION_DESTROY(pScreen, wInputShape (pWin)); -#endif if (pWin->borderIsPixel == FALSE) (*pScreen->DestroyPixmap)(pWin->border.pixmap); if (pWin->backgroundState == BackgroundPixmap) @@ -873,10 +904,6 @@ CrushTree(WindowPtr pWin) } FreeResource(pChild->drawable.id, RT_WINDOW); pSib = pChild->nextSib; -#ifdef DO_SAVE_UNDERS - if (pChild->saveUnder && pChild->viewable) - deltaSaveUndersViewable--; -#endif pChild->viewable = FALSE; if (pChild->realized) { @@ -934,6 +961,7 @@ DeleteWindow(pointer value, XID wid) if (pWin->prevSib) pWin->prevSib->nextSib = pWin->nextSib; } + xfree(dixLookupPrivate(&pWin->devPrivates, FocusPrivatesKey)); dixFreePrivates(pWin->devPrivates); xfree(pWin); return Success; @@ -981,7 +1009,7 @@ ChangeWindowAttributes(WindowPtr pWin, Mask vmask, XID *vlist, ClientPtr client) Pixmap pixID; CursorPtr pCursor, pOldCursor; Cursor cursorID; - WindowPtr pChild, pLayerWin; + WindowPtr pChild; Colormap cmap; ColormapPtr pCmap; xEvent xE; @@ -1202,47 +1230,7 @@ ChangeWindowAttributes(WindowPtr pWin, Mask vmask, XID *vlist, ClientPtr client) client->errorValue = val; goto PatchUp; } -#ifdef DO_SAVE_UNDERS - if (pWin->parent && (pWin->saveUnder != val) && (pWin->viewable) && - DO_SAVE_UNDERS(pWin)) - { - /* - * Re-check all siblings and inferiors for obscurity or - * exposition (hee hee). - */ - if (pWin->saveUnder) - deltaSaveUndersViewable--; - else - deltaSaveUndersViewable++; - pWin->saveUnder = val; - - if (pWin->firstChild) - { - pLayerWin = (*pScreen->GetLayerWindow)(pWin); - if ((*pScreen->ChangeSaveUnder)(pLayerWin->parent, pWin->nextSib)) - (*pScreen->PostChangeSaveUnder)(pLayerWin->parent, - pWin->nextSib); - } - else - { - if ((*pScreen->ChangeSaveUnder)(pWin, pWin->nextSib)) - (*pScreen->PostChangeSaveUnder)(pWin, - pWin->nextSib); - } - } - else - { - /* If we're changing the saveUnder attribute of the root - * window, all we do is set pWin->saveUnder so that - * GetWindowAttributes returns the right value. We don't - * do the "normal" save-under processing (as above). - * Hope that doesn't cause any problems. - */ - pWin->saveUnder = val; - } -#else pWin->saveUnder = val; -#endif /* DO_SAVE_UNDERS */ break; case CWEventMask: rc = EventSelectForWindow(pWin, client, (Mask )*pVlist); @@ -1288,22 +1276,6 @@ ChangeWindowAttributes(WindowPtr pWin, Mask vmask, XID *vlist, ClientPtr client) pVlist++; if (cmap == CopyFromParent) { -#ifdef XAPPGROUP - Colormap ag_colormap; - ClientPtr win_owner; - - /* - * win_owner == client for CreateWindow, other clients - * can ChangeWindowAttributes - */ - win_owner = clients[CLIENT_ID(pWin->drawable.id)]; - - if ( win_owner && win_owner->appgroup && - !pWin->parent->parent && - (ag_colormap = XagDefaultColormap (win_owner))) - cmap = ag_colormap; - else -#endif if (pWin->parent && (!pWin->optional || pWin->optional->visual == wVisual (pWin->parent))) @@ -1541,7 +1513,7 @@ GetWindowAttributes(WindowPtr pWin, ClientPtr client, xGetWindowAttributesReply } -_X_EXPORT WindowPtr +WindowPtr MoveWindowInStack(WindowPtr pWin, WindowPtr pNextSib) { WindowPtr pParent = pWin->parent; @@ -1636,7 +1608,6 @@ CreateUnclippedWinSize (WindowPtr pWin) box.x2 = pWin->drawable.x + (int) pWin->drawable.width; box.y2 = pWin->drawable.y + (int) pWin->drawable.height; pRgn = REGION_CREATE(pWin->drawable.pScreen, &box, 1); -#ifdef SHAPE if (wBoundingShape (pWin) || wClipShape (pWin)) { ScreenPtr pScreen; pScreen = pWin->drawable.pScreen; @@ -1649,11 +1620,10 @@ CreateUnclippedWinSize (WindowPtr pWin) REGION_INTERSECT(pScreen, pRgn, pRgn, wClipShape (pWin)); REGION_TRANSLATE(pScreen, pRgn, pWin->drawable.x, pWin->drawable.y); } -#endif return pRgn; } -_X_EXPORT void +void SetWinSize (WindowPtr pWin) { #ifdef COMPOSITE @@ -1677,7 +1647,6 @@ SetWinSize (WindowPtr pWin) pWin->drawable.x, pWin->drawable.y, (int)pWin->drawable.width, (int)pWin->drawable.height); -#ifdef SHAPE if (wBoundingShape (pWin) || wClipShape (pWin)) { ScreenPtr pScreen; pScreen = pWin->drawable.pScreen; @@ -1693,10 +1662,9 @@ SetWinSize (WindowPtr pWin) REGION_TRANSLATE(pScreen, &pWin->winSize, pWin->drawable.x, pWin->drawable.y); } -#endif } -_X_EXPORT void +void SetBorderSize (WindowPtr pWin) { int bw; @@ -1724,7 +1692,6 @@ SetBorderSize (WindowPtr pWin) pWin->drawable.x - bw, pWin->drawable.y - bw, (int)(pWin->drawable.width + (bw<<1)), (int)(pWin->drawable.height + (bw<<1))); -#ifdef SHAPE if (wBoundingShape (pWin)) { ScreenPtr pScreen; pScreen = pWin->drawable.pScreen; @@ -1738,7 +1705,6 @@ SetBorderSize (WindowPtr pWin) REGION_UNION(pScreen, &pWin->borderSize, &pWin->borderSize, &pWin->winSize); } -#endif } else { REGION_COPY(pWin->drawable.pScreen, &pWin->borderSize, &pWin->winSize); @@ -1802,7 +1768,7 @@ GravityTranslate (int x, int y, int oldx, int oldy, } /* XXX need to retile border on each window with ParentRelative origin */ -_X_EXPORT void +void ResizeChildrenWinSize(WindowPtr pWin, int dx, int dy, int dw, int dh) { ScreenPtr pScreen; @@ -1929,7 +1895,6 @@ WindowExtents( return(pBox); } -#ifdef SHAPE #define IS_SHAPED(pWin) (wBoundingShape (pWin) != (RegionPtr) NULL) static RegionPtr @@ -1974,7 +1939,6 @@ ShapeOverlap ( REGION_DESTROY(pScreen, pSibRgn); return ret; } -#endif static Bool AnyWindowOverlapsMe( @@ -1992,9 +1956,7 @@ AnyWindowOverlapsMe( { sbox = WindowExtents(pSib, &sboxrec); if (BOXES_OVERLAP(sbox, box) -#ifdef SHAPE && ShapeOverlap (pWin, box, pSib, sbox) -#endif ) return(TRUE); } @@ -2017,9 +1979,7 @@ IOverlapAnyWindow( { sbox = WindowExtents(pSib, &sboxrec); if (BOXES_OVERLAP(sbox, box) -#ifdef SHAPE && ShapeOverlap (pWin, box, pSib, sbox) -#endif ) return(TRUE); } @@ -2172,9 +2132,6 @@ ReflectStackChange( Bool WasViewable = (Bool)pWin->viewable; Bool anyMarked; WindowPtr pFirstChange; -#ifdef DO_SAVE_UNDERS - Bool dosave = FALSE; -#endif WindowPtr pLayerWin; ScreenPtr pScreen = pWin->drawable.pScreen; @@ -2189,21 +2146,11 @@ ReflectStackChange( anyMarked = (*pScreen->MarkOverlappedWindows)(pWin, pFirstChange, &pLayerWin); if (pLayerWin != pWin) pFirstChange = pLayerWin; -#ifdef DO_SAVE_UNDERS - if (DO_SAVE_UNDERS(pWin)) - { - dosave = (*pScreen->ChangeSaveUnder)(pLayerWin, pFirstChange); - } -#endif /* DO_SAVE_UNDERS */ if (anyMarked) { (*pScreen->ValidateTree)(pLayerWin->parent, pFirstChange, kind); (*pScreen->HandleExposures)(pLayerWin->parent); } -#ifdef DO_SAVE_UNDERS - if (dosave) - (*pScreen->PostChangeSaveUnder)(pLayerWin, pFirstChange); -#endif /* DO_SAVE_UNDERS */ if (anyMarked && pWin->drawable.pScreen->PostValidateTree) (*pScreen->PostValidateTree)(pLayerWin->parent, pFirstChange, kind); } @@ -2232,10 +2179,6 @@ ConfigureWindow(WindowPtr pWin, Mask mask, XID *vlist, ClientPtr client) h = pWin->drawable.height, bw = pWin->borderWidth; int rc, action, smode = Above; -#ifdef XAPPGROUP - ClientPtr win_owner; - ClientPtr ag_leader = NULL; -#endif xEvent event; if ((pWin->drawable.class == InputOnly) && (mask & IllegalInputOnlyConfigureMask)) @@ -2331,17 +2274,9 @@ ConfigureWindow(WindowPtr pWin, Mask mask, XID *vlist, ClientPtr client) else pSib = pWin->nextSib; -#ifdef XAPPGROUP - win_owner = clients[CLIENT_ID(pWin->drawable.id)]; - ag_leader = XagLeader (win_owner); -#endif if ((!pWin->overrideRedirect) && (RedirectSend(pParent) -#ifdef XAPPGROUP - || (win_owner->appgroup && ag_leader && - XagIsControlledRoot (client, pParent)) -#endif )) { event.u.u.type = ConfigureRequest; @@ -2366,16 +2301,6 @@ ConfigureWindow(WindowPtr pWin, Mask mask, XID *vlist, ClientPtr client) event.u.configureRequest.height = h; event.u.configureRequest.borderWidth = bw; event.u.configureRequest.valueMask = mask; -#ifdef XAPPGROUP - /* make sure if the ag_leader maps the window it goes to the wm */ - if (ag_leader && ag_leader != client && - XagIsControlledRoot (client, pParent)) { - event.u.configureRequest.parent = XagId (win_owner); - (void) TryClientEvents (ag_leader, &event, 1, - NoEventMask, NoEventMask, NullGrab); - return Success; - } -#endif event.u.configureRequest.parent = pParent->drawable.id; if (MaybeDeliverEventsToClient(pParent, &event, 1, SubstructureRedirectMask, client) == 1) @@ -2676,10 +2601,6 @@ RealizeTree(WindowPtr pWin) if (pChild->mapped) { pChild->realized = TRUE; -#ifdef DO_SAVE_UNDERS - if (pChild->saveUnder) - deltaSaveUndersViewable++; -#endif pChild->viewable = (pChild->drawable.class == InputOutput); (* Realize)(pChild); if (pChild->firstChild) @@ -2734,9 +2655,6 @@ MapWindow(WindowPtr pWin, ClientPtr client) ScreenPtr pScreen; WindowPtr pParent; -#ifdef DO_SAVE_UNDERS - Bool dosave = FALSE; -#endif WindowPtr pLayerWin; if (pWin->mapped) @@ -2752,31 +2670,13 @@ MapWindow(WindowPtr pWin, ClientPtr client) { xEvent event; Bool anyMarked; -#ifdef XAPPGROUP - ClientPtr win_owner = clients[CLIENT_ID(pWin->drawable.id)]; - ClientPtr ag_leader = XagLeader (win_owner); -#endif if ((!pWin->overrideRedirect) && (RedirectSend(pParent) -#ifdef XAPPGROUP - || (win_owner->appgroup && ag_leader && - XagIsControlledRoot (client, pParent)) -#endif )) { event.u.u.type = MapRequest; event.u.mapRequest.window = pWin->drawable.id; -#ifdef XAPPGROUP - /* make sure if the ag_leader maps the window it goes to the wm */ - if (ag_leader && ag_leader != client && - XagIsControlledRoot (client, pParent)) { - event.u.mapRequest.parent = XagId (win_owner); - (void) TryClientEvents (ag_leader, &event, 1, - NoEventMask, NoEventMask, NullGrab); - return Success; - } -#endif event.u.mapRequest.parent = pParent->drawable.id; if (MaybeDeliverEventsToClient(pParent, &event, 1, @@ -2800,21 +2700,11 @@ MapWindow(WindowPtr pWin, ClientPtr client) { anyMarked = (*pScreen->MarkOverlappedWindows)(pWin, pWin, &pLayerWin); -#ifdef DO_SAVE_UNDERS - if (DO_SAVE_UNDERS(pWin)) - { - dosave = (*pScreen->ChangeSaveUnder)(pLayerWin, pWin->nextSib); - } -#endif /* DO_SAVE_UNDERS */ if (anyMarked) { (*pScreen->ValidateTree)(pLayerWin->parent, pLayerWin, VTMap); (*pScreen->HandleExposures)(pLayerWin->parent); } -#ifdef DO_SAVE_UNDERS - if (dosave) - (*pScreen->PostChangeSaveUnder)(pLayerWin, pWin->nextSib); -#endif /* DO_SAVE_UNDERS */ if (anyMarked && pScreen->PostValidateTree) (*pScreen->PostValidateTree)(pLayerWin->parent, pLayerWin, VTMap); } @@ -2854,17 +2744,11 @@ MapSubwindows(WindowPtr pParent, ClientPtr client) { WindowPtr pWin; WindowPtr pFirstMapped = NullWindow; -#ifdef DO_SAVE_UNDERS - WindowPtr pFirstSaveUndered = NullWindow; -#endif ScreenPtr pScreen; Mask parentRedirect; Mask parentNotify; xEvent event; Bool anyMarked; -#ifdef DO_SAVE_UNDERS - Bool dosave = FALSE; -#endif WindowPtr pLayerWin; pScreen = pParent->drawable.pScreen; @@ -2904,12 +2788,6 @@ MapSubwindows(WindowPtr pParent, ClientPtr client) { anyMarked |= (*pScreen->MarkOverlappedWindows)(pWin, pWin, (WindowPtr *)NULL); -#ifdef DO_SAVE_UNDERS - if (DO_SAVE_UNDERS(pWin)) - { - dosave = TRUE; - } -#endif /* DO_SAVE_UNDERS */ } } } @@ -2926,38 +2804,9 @@ MapSubwindows(WindowPtr pParent, ClientPtr client) } if (anyMarked) { -#ifdef DO_SAVE_UNDERS - if (pLayerWin->parent != pParent) - { - if (dosave || (DO_SAVE_UNDERS(pLayerWin))) - { - dosave = (*pScreen->ChangeSaveUnder)(pLayerWin, - pLayerWin); - } - } - else if (dosave) - { - dosave = FALSE; - for (pWin = pParent->firstChild; pWin; pWin = pWin->nextSib) - { - if (DO_SAVE_UNDERS(pWin)) - { - dosave |= (*pScreen->ChangeSaveUnder)(pWin, - pWin->nextSib); - if (dosave && !pFirstSaveUndered) - pFirstSaveUndered = pWin; - } - } - } -#endif /* DO_SAVE_UNDERS */ (*pScreen->ValidateTree)(pLayerWin->parent, pFirstMapped, VTMap); (*pScreen->HandleExposures)(pLayerWin->parent); } -#ifdef DO_SAVE_UNDERS - if (dosave) - (*pScreen->PostChangeSaveUnder)(pLayerWin, - pFirstSaveUndered->nextSib); -#endif /* DO_SAVE_UNDERS */ if (anyMarked && pScreen->PostValidateTree) (*pScreen->PostValidateTree)(pLayerWin->parent, pFirstMapped, VTMap); @@ -2997,10 +2846,6 @@ UnrealizeTree( DeleteWindowFromAnyEvents(pChild, FALSE); if (pChild->viewable) { -#ifdef DO_SAVE_UNDERS - if (pChild->saveUnder) - deltaSaveUndersViewable--; -#endif pChild->viewable = FALSE; (* MarkUnrealizedWindow)(pChild, pWin, fromConfigure); pChild->drawable.serialNumber = NEXT_SERIAL_NUMBER; @@ -3061,16 +2906,6 @@ UnmapWindow(WindowPtr pWin, Bool fromConfigure) (*pScreen->ValidateTree)(pLayerWin->parent, pWin, VTUnmap); (*pScreen->HandleExposures)(pLayerWin->parent); } -#ifdef DO_SAVE_UNDERS - if (DO_SAVE_UNDERS(pWin)) - { - if ( (*pScreen->ChangeSaveUnder)(pLayerWin, pWin->nextSib) ) - { - (*pScreen->PostChangeSaveUnder)(pLayerWin, pWin->nextSib); - } - } - pWin->DIXsaveUnder = FALSE; -#endif /* DO_SAVE_UNDERS */ if (!fromConfigure && pScreen->PostValidateTree) (*pScreen->PostValidateTree)(pLayerWin->parent, pWin, VTUnmap); } @@ -3126,9 +2961,6 @@ UnmapSubwindows(WindowPtr pWin) UnrealizeTree(pChild, FALSE); if (wasViewable) { -#ifdef DO_SAVE_UNDERS - pChild->DIXsaveUnder = FALSE; -#endif /* DO_SAVE_UNDERS */ } } } @@ -3158,13 +2990,6 @@ UnmapSubwindows(WindowPtr pWin) (*pScreen->ValidateTree)(pLayerWin->parent, pHead, VTUnmap); (*pScreen->HandleExposures)(pLayerWin->parent); } -#ifdef DO_SAVE_UNDERS - if (DO_SAVE_UNDERS(pWin)) - { - if ( (*pScreen->ChangeSaveUnder)(pLayerWin, pLayerWin)) - (*pScreen->PostChangeSaveUnder)(pLayerWin, pLayerWin); - } -#endif /* DO_SAVE_UNDERS */ if (anyMarked && pScreen->PostValidateTree) (*pScreen->PostValidateTree)(pLayerWin->parent, pHead, VTUnmap); } @@ -3196,6 +3021,11 @@ HandleSaveSet(ClientPtr client) { if (pParent != pWin->parent) { +#ifdef XFIXES + /* unmap first so that ReparentWindow doesn't remap */ + if (!SaveSetShouldMap (client->saveSet[j])) + UnmapWindow(pWin, FALSE); +#endif ReparentWindow(pWin, pParent, pWin->drawable.x - wBorderWidth (pWin) - pParent->drawable.x, pWin->drawable.y - wBorderWidth (pWin) - pParent->drawable.y, @@ -3204,7 +3034,7 @@ HandleSaveSet(ClientPtr client) pWin->mapped = FALSE; } #ifdef XFIXES - if (SaveSetRemap (client->saveSet[j])) + if (SaveSetShouldMap (client->saveSet[j])) #endif MapWindow(pWin, client); } @@ -3254,10 +3084,12 @@ NotClippedByChildren(WindowPtr pWin) return(pReg); } -_X_EXPORT void +void SendVisibilityNotify(WindowPtr pWin) { xEvent event; + if (!MapUnmapEventsEnabled(pWin)) + return; #ifndef NO_XINERAMA_PORT unsigned int visibility = pWin->visibility; #endif @@ -3614,18 +3446,31 @@ CheckWindowOptionalNeed (WindowPtr w) return; if (optional->backingPixel != 0) return; -#ifdef SHAPE if (optional->boundingShape != NULL) return; if (optional->clipShape != NULL) return; if (optional->inputShape != NULL) return; -#endif -#ifdef XINPUT if (optional->inputMasks != NULL) return; -#endif + if (optional->deviceCursors != NULL) + { + DevCursNodePtr pNode = optional->deviceCursors; + while(pNode) + { + if (pNode->cursor != None) + return; + pNode = pNode->next; + } + } + if (optional->access.nperm != 0 || + optional->access.ndeny != 0) + return; + + if (optional->geMasks != NULL) + return; + parentOptional = FindWindowWithOptional(w)->optional; if (optional->visual != parentOptional->visual) return; @@ -3663,14 +3508,30 @@ MakeWindowOptional (WindowPtr pWin) optional->userProps = NULL; optional->backingBitPlanes = ~0L; optional->backingPixel = 0; -#ifdef SHAPE optional->boundingShape = NULL; optional->clipShape = NULL; optional->inputShape = NULL; -#endif -#ifdef XINPUT optional->inputMasks = NULL; -#endif + optional->deviceCursors = NULL; + + optional->geMasks = + (GenericClientMasksPtr)xalloc(sizeof(GenericClientMasksRec)); + if (!optional->geMasks) + { + xfree(optional); + return FALSE; + } else { + int i; + optional->geMasks->geClients = 0; + for (i = 0; i < MAXEXTENSIONS; i++) + optional->geMasks->eventMasks[i] = 0; + } + + optional->access.nperm = 0; + optional->access.ndeny = 0; + optional->access.perm = NULL; + optional->access.deny = NULL; + optional->access.defaultRule = 0; parentOptional = FindWindowWithOptional(pWin)->optional; optional->visual = parentOptional->visual; if (!pWin->cursorIsNone) @@ -3687,6 +3548,222 @@ MakeWindowOptional (WindowPtr pWin) return TRUE; } +/* + * Changes the cursor struct for the given device and the given window. + * A cursor that does not have a device cursor set will use whatever the + * standard cursor is for the window. If all devices have a cursor set, + * changing the window cursor (e.g. using XDefineCursor()) will not have any + * visible effect. Only when one of the device cursors is set to None again, + * this device's cursor will display the changed standard cursor. + * + * CursorIsNone of the window struct is NOT modified if you set a device + * cursor. + * + * Assumption: If there is a node for a device in the list, the device has a + * cursor. If the cursor is set to None, it is inherited by the parent. + */ +_X_EXPORT int +ChangeWindowDeviceCursor(WindowPtr pWin, + DeviceIntPtr pDev, + CursorPtr pCursor) +{ + DevCursNodePtr pNode, pPrev; + CursorPtr pOldCursor = NULL; + ScreenPtr pScreen; + WindowPtr pChild; + + if (!pWin->optional && !MakeWindowOptional(pWin)) + return BadAlloc; + + /* 1) Check if window has device cursor set + * Yes: 1.1) swap cursor with given cursor if parent does not have same + * cursor, free old cursor + * 1.2) free old cursor, use parent cursor + * No: 1.1) add node to beginning of list. + * 1.2) add cursor to node if parent does not have same cursor + * 1.3) use parent cursor if parent does not have same cursor + * 2) Patch up children if child has a devcursor + * 2.1) if child has cursor None, it inherited from parent, set to old + * cursor + * 2.2) if child has same cursor as new cursor, remove and set to None + */ + + pScreen = pWin->drawable.pScreen; + + if (WindowSeekDeviceCursor(pWin, pDev, &pNode, &pPrev)) + { + /* has device cursor */ + + if (pNode->cursor == pCursor) + return Success; + + pOldCursor = pNode->cursor; + + if (!pCursor) /* remove from list */ + { + if(pPrev) + pPrev->next = pNode->next; + else + /* first item in list */ + pWin->optional->deviceCursors = pNode->next; + + xfree(pNode); + return Success; + } + + } else + { + /* no device cursor yet */ + DevCursNodePtr pNewNode; + + if (!pCursor) + return Success; + + pNewNode = (DevCursNodePtr)xalloc(sizeof(DevCursNodeRec)); + pNewNode->dev = pDev; + pNewNode->next = pWin->optional->deviceCursors; + pWin->optional->deviceCursors = pNewNode; + pNode = pNewNode; + + } + + if (pCursor && WindowParentHasDeviceCursor(pWin, pDev, pCursor)) + pNode->cursor = None; + else + { + pNode->cursor = pCursor; + pCursor->refcnt++; + } + + pNode = pPrev = NULL; + /* fix up children */ + for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib) + { + if (WindowSeekDeviceCursor(pChild, pDev, &pNode, &pPrev)) + { + if (pNode->cursor == None) /* inherited from parent */ + { + pNode->cursor = pOldCursor; + pOldCursor->refcnt++; + } else if (pNode->cursor == pCursor) + { + pNode->cursor = None; + FreeCursor(pCursor, (Cursor)0); /* fix up refcnt */ + } + } + } + + if (pWin->realized) + WindowHasNewCursor(pWin); + + if (pOldCursor) + FreeCursor(pOldCursor, (Cursor)0); + + /* FIXME: We SHOULD check for an error value here XXX + (comment taken from ChangeWindowAttributes) */ + (*pScreen->ChangeWindowAttributes)(pWin, CWCursor); + + return Success; +} + +/* Get device cursor for given device or None if none is set */ +_X_EXPORT CursorPtr +WindowGetDeviceCursor(WindowPtr pWin, DeviceIntPtr pDev) +{ + DevCursorList pList; + + if (!pWin->optional || !pWin->optional->deviceCursors) + return NULL; + + pList = pWin->optional->deviceCursors; + + while(pList) + { + if (pList->dev == pDev) + { + if (pList->cursor == None) /* inherited from parent */ + return WindowGetDeviceCursor(pWin->parent, pDev); + else + return pList->cursor; + } + pList = pList->next; + } + return NULL; +} + +/* Searches for a DevCursorNode for the given window and device. If one is + * found, return True and set pNode and pPrev to the node and to the node + * before the node respectively. Otherwise return False. + * If the device is the first in list, pPrev is set to NULL. + */ +static Bool +WindowSeekDeviceCursor(WindowPtr pWin, + DeviceIntPtr pDev, + DevCursNodePtr* pNode, + DevCursNodePtr* pPrev) +{ + DevCursorList pList; + + if (!pWin->optional) + return FALSE; + + pList = pWin->optional->deviceCursors; + + if (pList && pList->dev == pDev) + { + *pNode = pList; + *pPrev = NULL; + return TRUE; + } + + while(pList) + { + if (pList->next) + { + if (pList->next->dev == pDev) + { + *pNode = pList->next; + *pPrev = pList; + return TRUE; + } + } + pList = pList->next; + } + return FALSE; +} + +/* Return True if a parent has the same device cursor set or False if + * otherwise + */ +static Bool +WindowParentHasDeviceCursor(WindowPtr pWin, + DeviceIntPtr pDev, + CursorPtr pCursor) +{ + WindowPtr pParent; + DevCursNodePtr pParentNode, pParentPrev; + + pParent = pWin->parent; + while(pParent) + { + if (WindowSeekDeviceCursor(pParent, pDev, + &pParentNode, &pParentPrev)) + { + /* if there is a node in the list, the win has a dev cursor */ + if (!pParentNode->cursor) /* inherited. loop needs to cont. */ + { + } else if (pParentNode->cursor == pCursor) /* inherit */ + return TRUE; + else /* different cursor */ + return FALSE; + } + else + /* parent does not have a device cursor for our device */ + return FALSE; + } + return FALSE; +} + #ifndef NOLOGOHACK static void DrawLogo(WindowPtr pWin) diff --git a/xorg-server/dix/xpstubs.c b/xorg-server/dix/xpstubs.c deleted file mode 100644 index 59340ad21..000000000 --- a/xorg-server/dix/xpstubs.c +++ /dev/null @@ -1,78 +0,0 @@ -/* -Copyright 1996, 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 "misc.h" -#include <X11/fonts/font.h> -#ifdef XPRINT -#include "DiPrint.h" -#else -extern Bool XpClientIsBitmapClient(ClientPtr client); -extern Bool XpClientIsPrintClient(ClientPtr client, FontPathElementPtr fpe); -#endif - -Bool -XpClientIsBitmapClient( - ClientPtr client) -{ - return TRUE; -} - -Bool -XpClientIsPrintClient( - ClientPtr client, - FontPathElementPtr fpe) -{ - return FALSE; -} -#ifdef XPRINT -int -PrinterOptions( - int argc, - char **argv, - int i) -{ - return i; -} -void -PrinterInitOutput( - ScreenInfo *pScreenInfo, - int argc, - char **argv) -{ -} -void PrinterUseMsg(void) -{ -} -void PrinterInitGlobals(void) -{ -} -#endif /* XPRINT */ - |