From f851244b9298d88c29331ab285c2839d8bee6925 Mon Sep 17 00:00:00 2001 From: marha Date: Thu, 16 Dec 2010 16:13:08 +0000 Subject: xserver libXdmcp git update 16-12-2010 --- xorg-server/hw/dmx/Makefile.am | 229 +- xorg-server/hw/dmx/doc/Makefile.am | 530 ++-- xorg-server/hw/xfree86/common/xf86Option.c | 1790 ++++++------- xorg-server/hw/xfree86/common/xf86Xinput.c | 2791 ++++++++++---------- xorg-server/hw/xfree86/doc/Makefile.am | 12 +- xorg-server/hw/xquartz/GL/Makefile.am | 2 +- xorg-server/hw/xquartz/Makefile.am | 110 +- xorg-server/hw/xquartz/X11Application.h | 219 +- xorg-server/hw/xquartz/X11Application.m | 2642 +++++++++--------- xorg-server/hw/xquartz/X11Controller.h | 1 - xorg-server/hw/xquartz/X11Controller.m | 1684 ++++++------ .../English.lproj/main.nib/designable.nib | 320 ++- .../English.lproj/main.nib/keyedobjects.nib | Bin 45258 -> 44012 bytes xorg-server/hw/xquartz/quartz.c | 905 +++---- xorg-server/hw/xquartz/quartz.h | 291 +- xorg-server/hw/xquartz/quartzAudio.c | 329 --- xorg-server/hw/xquartz/quartzAudio.h | 37 - xorg-server/hw/xquartz/quartzKeyboard.c | 1715 ++++++------ xorg-server/hw/xquartz/quartzStartup.c | 4 - 19 files changed, 6671 insertions(+), 6940 deletions(-) delete mode 100644 xorg-server/hw/xquartz/quartzAudio.c delete mode 100644 xorg-server/hw/xquartz/quartzAudio.h (limited to 'xorg-server/hw') diff --git a/xorg-server/hw/dmx/Makefile.am b/xorg-server/hw/dmx/Makefile.am index 939e8ec31..2a87c3966 100644 --- a/xorg-server/hw/dmx/Makefile.am +++ b/xorg-server/hw/dmx/Makefile.am @@ -1,117 +1,112 @@ -DIST_SUBDIRS = input config glxProxy examples doc - -SUBDIRS = input config examples -bin_PROGRAMS = Xdmx - -if XINERAMA -PANORAMIX_SRCS = $(top_srcdir)/Xext/panoramiX.c -endif - -if GLX -SUBDIRS += glxProxy -GLX_LIBS = glxProxy/libglxproxy.a -GLX_SRCS = $(PANORAMIX_SRCS) dmx_glxvisuals.c dmx_glxvisuals.h -GLX_INCS = -I$(top_srcdir)/hw/xfree86/dixmods/extmod -GLX_DEFS = @GL_CFLAGS@ -endif - -if BUILDDOCS -SUBDIRS += doc -endif - -AM_CFLAGS = \ - -DHAVE_DMX_CONFIG_H \ - $(DIX_CFLAGS) \ - $(GLX_INCS) \ - $(GLX_DEFS) \ - $(DMX_CFLAGS) \ - @DMXMODULES_CFLAGS@ - -Xdmx_SOURCES = dmx.c \ - dmxcb.c \ - dmxcb.h \ - dmxclient.h \ - dmxcmap.c \ - dmxcmap.h \ - dmx-config.h \ - dmxcursor.c \ - dmxcursor.h \ - dmxdpms.c \ - dmxdpms.h \ - dmxextension.c \ - dmxextension.h \ - dmxfont.c \ - dmxfont.h \ - dmxgc.c \ - dmxgc.h \ - dmxgcops.c \ - dmxgcops.h \ - dmx.h \ - dmxinit.c \ - dmxinit.h \ - dmxinput.c \ - dmxinput.h \ - dmxlog.c \ - dmxlog.h \ - dmxpict.c \ - dmxpict.h \ - dmxpixmap.c \ - dmxpixmap.h \ - dmxprop.c \ - dmxprop.h \ - dmxscrinit.c \ - dmxscrinit.h \ - dmxshadow.c \ - dmxshadow.h \ - dmxstat.c \ - dmxstat.h \ - dmxsync.c \ - dmxsync.h \ - dmxvisual.c \ - dmxvisual.h \ - dmxwindow.c \ - dmxwindow.h \ - $(top_srcdir)/mi/miinitext.c \ - $(top_srcdir)/fb/fbcmap_mi.c \ - $(GLX_SRCS) - - -#if COMPOSITE -#Xdmx_SOURCES += fakecw.c -#endif - -XDMX_LIBS = \ - $(GLX_LIBS) \ - @XDMX_LIBS@ \ - input/libdmxinput.a \ - config/libdmxconfig.a - -Xdmx_LDFLAGS = $(LD_EXPORT_SYMBOLS_FLAG) -Xdmx_DEPENDENCIES= $(XDMX_LIBS) -Xdmx_LDADD = $(XDMX_LIBS) $(XDMX_SYS_LIBS) $(XSERVER_SYS_LIBS) - -# Man page -appmandir = $(APP_MAN_DIR) - -appman_PRE = Xdmx.man -appman_DATA = $(appman_PRE:man=@APP_MAN_SUFFIX@) - -CLEANFILES = $(appman_DATA) - -# Strings to replace in man pages -XORGRELSTRING = @PACKAGE_STRING@ - XORGMANNAME = X Version 11 - -MAN_SUBSTS = \ - -e 's|__vendorversion__|"$(XORGRELSTRING)" "$(XORGMANNAME)"|' \ - -e 's|__miscmansuffix__|$(MISC_MAN_SUFFIX)|g' - -SUFFIXES = .$(APP_MAN_SUFFIX) .man - -.man.$(APP_MAN_SUFFIX): - $(AM_V_GEN)$(SED) $(MAN_SUBSTS) < $< > $@ - -EXTRA_DIST = $(appman_PRE) - -relink: - $(AM_V_at)rm -f Xdmx$(EXEEXT) && $(MAKE) Xdmx$(EXEEXT) + +SUBDIRS = input config examples doc +bin_PROGRAMS = Xdmx + +if XINERAMA +PANORAMIX_SRCS = $(top_srcdir)/Xext/panoramiX.c +endif + +if GLX +SUBDIRS += glxProxy +GLX_LIBS = glxProxy/libglxproxy.a +GLX_SRCS = $(PANORAMIX_SRCS) dmx_glxvisuals.c dmx_glxvisuals.h +GLX_INCS = -I$(top_srcdir)/hw/xfree86/dixmods/extmod +GLX_DEFS = @GL_CFLAGS@ +endif + +AM_CFLAGS = \ + -DHAVE_DMX_CONFIG_H \ + $(DIX_CFLAGS) \ + $(GLX_INCS) \ + $(GLX_DEFS) \ + $(DMX_CFLAGS) \ + @DMXMODULES_CFLAGS@ + +Xdmx_SOURCES = dmx.c \ + dmxcb.c \ + dmxcb.h \ + dmxclient.h \ + dmxcmap.c \ + dmxcmap.h \ + dmx-config.h \ + dmxcursor.c \ + dmxcursor.h \ + dmxdpms.c \ + dmxdpms.h \ + dmxextension.c \ + dmxextension.h \ + dmxfont.c \ + dmxfont.h \ + dmxgc.c \ + dmxgc.h \ + dmxgcops.c \ + dmxgcops.h \ + dmx.h \ + dmxinit.c \ + dmxinit.h \ + dmxinput.c \ + dmxinput.h \ + dmxlog.c \ + dmxlog.h \ + dmxpict.c \ + dmxpict.h \ + dmxpixmap.c \ + dmxpixmap.h \ + dmxprop.c \ + dmxprop.h \ + dmxscrinit.c \ + dmxscrinit.h \ + dmxshadow.c \ + dmxshadow.h \ + dmxstat.c \ + dmxstat.h \ + dmxsync.c \ + dmxsync.h \ + dmxvisual.c \ + dmxvisual.h \ + dmxwindow.c \ + dmxwindow.h \ + $(top_srcdir)/mi/miinitext.c \ + $(top_srcdir)/fb/fbcmap_mi.c \ + $(GLX_SRCS) + + +#if COMPOSITE +#Xdmx_SOURCES += fakecw.c +#endif + +XDMX_LIBS = \ + $(GLX_LIBS) \ + @XDMX_LIBS@ \ + input/libdmxinput.a \ + config/libdmxconfig.a + +Xdmx_LDFLAGS = $(LD_EXPORT_SYMBOLS_FLAG) +Xdmx_DEPENDENCIES= $(XDMX_LIBS) +Xdmx_LDADD = $(XDMX_LIBS) $(XDMX_SYS_LIBS) $(XSERVER_SYS_LIBS) + +# Man page +appmandir = $(APP_MAN_DIR) + +appman_PRE = Xdmx.man +appman_DATA = $(appman_PRE:man=@APP_MAN_SUFFIX@) + +CLEANFILES = $(appman_DATA) + +# Strings to replace in man pages +XORGRELSTRING = @PACKAGE_STRING@ + XORGMANNAME = X Version 11 + +MAN_SUBSTS = \ + -e 's|__vendorversion__|"$(XORGRELSTRING)" "$(XORGMANNAME)"|' \ + -e 's|__miscmansuffix__|$(MISC_MAN_SUFFIX)|g' + +SUFFIXES = .$(APP_MAN_SUFFIX) .man + +.man.$(APP_MAN_SUFFIX): + $(AM_V_GEN)$(SED) $(MAN_SUBSTS) < $< > $@ + +EXTRA_DIST = $(appman_PRE) + +relink: + $(AM_V_at)rm -f Xdmx$(EXEEXT) && $(MAKE) Xdmx$(EXEEXT) diff --git a/xorg-server/hw/dmx/doc/Makefile.am b/xorg-server/hw/dmx/doc/Makefile.am index 5f845763e..4bbc8bf88 100644 --- a/xorg-server/hw/dmx/doc/Makefile.am +++ b/xorg-server/hw/dmx/doc/Makefile.am @@ -1,265 +1,265 @@ -# Copyright 2005 Red Hat, Inc. -# -# Permission to use, copy, modify, distribute, and sell this software -# and its documentation for any purpose is hereby granted without -# fee, provided that the above copyright notice appear in all copies -# and that both that copyright notice and this permission notice -# appear in supporting documentation, and that the name of Red Hat -# not be used in advertising or publicity pertaining to distribution -# of the software without specific, written prior permission. Red -# Hat makes no representations about the suitability of this software -# for any purpose. It is provided "as is" without express or implied -# warranty. -# -# RED HAT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, -# INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN -# NO EVENT SHALL RED HAT BE LIABLE FOR ANY SPECIAL, INDIRECT OR -# CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS -# OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, -# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -doc_sources = dmx.xml scaled.xml - -# Developer's documentation is not installed -if ENABLE_DEVEL_DOCS -include $(top_srcdir)/doc/xml/xmlrules-noinst.in -endif - -if HAVE_DOXYGEN - -DOXYGEN_SRC=doxygen.head doxygen.foot doxygen.css doxygen.conf - -all-local: html/annotated.html - -dist-local: html/annotated.html - -html/annotated.html: $(DOXYGEN_SRC) - $(DOXYGEN) $(srcdir)/doxygen.conf - -maintainer-clean-local: - rm -rf html/ -endif - -EXTRA_DIST = \ - $(XML_FILES) \ - DMXSpec.txt \ - DMXSpec-v1.txt \ - dmx.txt \ - doxygen.conf \ - doxygen.css \ - doxygen.foot \ - doxygen.head \ - scaled.txt \ - html/annotated.html \ - html/ChkNotMaskEv_8c.html \ - html/ChkNotMaskEv_8h.html \ - html/ChkNotMaskEv_8h_source.html \ - html/classes.html \ - html/dmx_8h.html \ - html/dmx_8h_source.html \ - html/dmxarg_8c.html \ - html/dmxarg_8h.html \ - html/dmxarg_8h_source.html \ - html/dmxbackend_8c.html \ - html/dmxbackend_8h.html \ - html/dmxbackend_8h_source.html \ - html/dmxcb_8c.html \ - html/dmxcb_8h.html \ - html/dmxcb_8h_source.html \ - html/dmxclient_8h.html \ - html/dmxclient_8h_source.html \ - html/dmxcmap_8c.html \ - html/dmxcmap_8h.html \ - html/dmxcmap_8h_source.html \ - html/dmxcommon_8c.html \ - html/dmxcommon_8h.html \ - html/dmxcommon_8h_source.html \ - html/dmxcompat_8c.html \ - html/dmxcompat_8h.html \ - html/dmxcompat_8h_source.html \ - html/dmxconfig_8c.html \ - html/dmxconfig_8h.html \ - html/dmxconfig_8h_source.html \ - html/dmxconsole_8c.html \ - html/dmxconsole_8h.html \ - html/dmxconsole_8h_source.html \ - html/dmxcursor_8c.html \ - html/dmxcursor_8h.html \ - html/dmxcursor_8h_source.html \ - html/dmxdetach_8c.html \ - html/dmxdpms_8c.html \ - html/dmxdpms_8h.html \ - html/dmxdpms_8h_source.html \ - html/dmxdummy_8c.html \ - html/dmxdummy_8h.html \ - html/dmxdummy_8h_source.html \ - html/dmxevents_8c.html \ - html/dmxevents_8h.html \ - html/dmxevents_8h_source.html \ - html/dmxextension_8c.html \ - html/dmxextension_8h.html \ - html/dmxextension_8h_source.html \ - html/dmxfont_8c.html \ - html/dmxfont_8h.html \ - html/dmxfont_8h_source.html \ - html/dmxgc_8c.html \ - html/dmxgc_8h.html \ - html/dmxgc_8h_source.html \ - html/dmxgcops_8c.html \ - html/dmxgcops_8h.html \ - html/dmxgcops_8h_source.html \ - html/dmx__glxvisuals_8h_source.html \ - html/dmxinit_8c.html \ - html/dmxinit_8h.html \ - html/dmxinit_8h_source.html \ - html/dmxinput_8c.html \ - html/dmxinput_8h.html \ - html/dmxinput_8h_source.html \ - html/dmxinputinit_8c.html \ - html/dmxinputinit_8h.html \ - html/dmxinputinit_8h_source.html \ - html/dmxlog_8c.html \ - html/dmxlog_8h.html \ - html/dmxlog_8h_source.html \ - html/dmxmap_8c.html \ - html/dmxmap_8h.html \ - html/dmxmap_8h_source.html \ - html/dmxmotion_8c.html \ - html/dmxmotion_8h.html \ - html/dmxmotion_8h_source.html \ - html/dmxparse_8c.html \ - html/dmxparse_8h.html \ - html/dmxparse_8h_source.html \ - html/dmxpict_8c.html \ - html/dmxpict_8h.html \ - html/dmxpict_8h_source.html \ - html/dmxpixmap_8c.html \ - html/dmxpixmap_8h.html \ - html/dmxpixmap_8h_source.html \ - html/dmxprint_8c.html \ - html/dmxprint_8h.html \ - html/dmxprint_8h_source.html \ - html/dmxprop_8c.html \ - html/dmxprop_8h.html \ - html/dmxprop_8h_source.html \ - html/dmxscrinit_8c.html \ - html/dmxscrinit_8h.html \ - html/dmxscrinit_8h_source.html \ - html/dmxshadow_8c.html \ - html/dmxshadow_8h.html \ - html/dmxshadow_8h_source.html \ - html/dmxsigio_8c.html \ - html/dmxsigio_8h.html \ - html/dmxsigio_8h_source.html \ - html/dmxstat_8c.html \ - html/dmxstat_8h.html \ - html/dmxstat_8h_source.html \ - html/dmxsync_8c.html \ - html/dmxsync_8h.html \ - html/dmxsync_8h_source.html \ - html/dmxvisual_8c.html \ - html/dmxvisual_8h.html \ - html/dmxvisual_8h_source.html \ - html/dmxwindow_8c.html \ - html/dmxwindow_8h.html \ - html/dmxwindow_8h_source.html \ - html/dmxxinput_8c.html \ - html/doxygen.css \ - html/doxygen.png \ - html/files.html \ - html/ftv2blank.png \ - html/ftv2doc.png \ - html/ftv2folderclosed.png \ - html/ftv2folderopen.png \ - html/ftv2lastnode.png \ - html/ftv2link.png \ - html/ftv2mlastnode.png \ - html/ftv2mnode.png \ - html/ftv2node.png \ - html/ftv2plastnode.png \ - html/ftv2pnode.png \ - html/ftv2vertline.png \ - html/functions.html \ - html/functions_vars.html \ - html/globals_defs.html \ - html/globals_enum.html \ - html/globals_eval.html \ - html/globals_func.html \ - html/globals.html \ - html/globals_type.html \ - html/globals_vars.html \ - html/index.html \ - html/lnx-keyboard_8c.html \ - html/lnx-keyboard_8h.html \ - html/lnx-keyboard_8h_source.html \ - html/lnx-ms_8c.html \ - html/lnx-ms_8h.html \ - html/lnx-ms_8h_source.html \ - html/lnx-ps2_8c.html \ - html/lnx-ps2_8h.html \ - html/lnx-ps2_8h_source.html \ - html/main.html \ - html/struct__dmxArg.html \ - html/struct__dmxColormapPriv.html \ - html/structDMXConfigCmdStruct.html \ - html/struct__DMXConfigComment.html \ - html/struct__DMXConfigDisplay.html \ - html/struct__DMXConfigEntry.html \ - html/struct__DMXConfigFullDim.html \ - html/structDMXConfigListStruct.html \ - html/struct__DMXConfigNumber.html \ - html/struct__DMXConfigOption.html \ - html/struct__DMXConfigPair.html \ - html/struct__DMXConfigParam.html \ - html/struct__DMXConfigPartDim.html \ - html/struct__DMXConfigString.html \ - html/struct__DMXConfigSub.html \ - html/struct__DMXConfigToken.html \ - html/struct__DMXConfigVirtual.html \ - html/struct__DMXConfigWall.html \ - html/struct__dmxCursorPriv.html \ - html/structDMXDesktopAttributesRec.html \ - html/struct__DMXEventMap.html \ - html/struct__dmxFontPriv.html \ - html/struct__dmxGCPriv.html \ - html/structdmxGlxVisualPrivate.html \ - html/struct__dmxGlyphPriv.html \ - html/structDMXInputAttributesRec.html \ - html/struct__DMXInputInfo.html \ - html/struct__DMXLocalInitInfo.html \ - html/struct__DMXLocalInputInfo.html \ - html/struct__dmxPictPriv.html \ - html/struct__dmxPixPriv.html \ - html/structDMXScreenAttributesRec.html \ - html/struct__DMXScreenInfo.html \ - html/struct__DMXStatAvg.html \ - html/struct__DMXStatInfo.html \ - html/structDMXWindowAttributesRec.html \ - html/struct__dmxWinPriv.html \ - html/struct__myPrivate.html \ - html/tree.html \ - html/usb-common_8c.html \ - html/usb-common_8h.html \ - html/usb-common_8h_source.html \ - html/usb-keyboard_8c.html \ - html/usb-keyboard_8h.html \ - html/usb-keyboard_8h_source.html \ - html/usb-mouse_8c.html \ - html/usb-mouse_8h.html \ - html/usb-mouse_8h_source.html \ - html/usb-other_8c.html \ - html/usb-other_8h.html \ - html/usb-other_8h_source.html \ - html/usb-private_8h.html \ - html/usb-private_8h_source.html - -$(builddir)/doxygen.head: - $(LN_S) $(srcdir)/doxygen.head $@ - -$(builddir)/doxygen.foot: - $(LN_S) $(srcdir)/doxygen.foot $@ - -$(builddir)doxygen.css: - $(LN_S) $(srcdir)/doxygen.css $@ - +# Copyright 2005 Red Hat, Inc. +# +# Permission to use, copy, modify, distribute, and sell this software +# and its documentation for any purpose is hereby granted without +# fee, provided that the above copyright notice appear in all copies +# and that both that copyright notice and this permission notice +# appear in supporting documentation, and that the name of Red Hat +# not be used in advertising or publicity pertaining to distribution +# of the software without specific, written prior permission. Red +# Hat makes no representations about the suitability of this software +# for any purpose. It is provided "as is" without express or implied +# warranty. +# +# RED HAT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +# INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN +# NO EVENT SHALL RED HAT BE LIABLE FOR ANY SPECIAL, INDIRECT OR +# CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS +# OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, +# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +doc_sources = dmx.xml scaled.xml + +# Developer's documentation is not installed +if ENABLE_DEVEL_DOCS +include $(top_srcdir)/doc/xml/xmlrules-noinst.in + +if HAVE_DOXYGEN + +DOXYGEN_SRC=doxygen.head doxygen.foot doxygen.css doxygen.conf + +all-local: html/annotated.html + +dist-local: html/annotated.html + +html/annotated.html: $(DOXYGEN_SRC) + $(DOXYGEN) $(srcdir)/doxygen.conf + +maintainer-clean-local: + rm -rf html/ +endif +endif ENABLE_DEVEL_DOCS + +EXTRA_DIST = \ + $(XML_FILES) \ + DMXSpec.txt \ + DMXSpec-v1.txt \ + dmx.txt \ + doxygen.conf \ + doxygen.css \ + doxygen.foot \ + doxygen.head \ + scaled.txt \ + html/annotated.html \ + html/ChkNotMaskEv_8c.html \ + html/ChkNotMaskEv_8h.html \ + html/ChkNotMaskEv_8h_source.html \ + html/classes.html \ + html/dmx_8h.html \ + html/dmx_8h_source.html \ + html/dmxarg_8c.html \ + html/dmxarg_8h.html \ + html/dmxarg_8h_source.html \ + html/dmxbackend_8c.html \ + html/dmxbackend_8h.html \ + html/dmxbackend_8h_source.html \ + html/dmxcb_8c.html \ + html/dmxcb_8h.html \ + html/dmxcb_8h_source.html \ + html/dmxclient_8h.html \ + html/dmxclient_8h_source.html \ + html/dmxcmap_8c.html \ + html/dmxcmap_8h.html \ + html/dmxcmap_8h_source.html \ + html/dmxcommon_8c.html \ + html/dmxcommon_8h.html \ + html/dmxcommon_8h_source.html \ + html/dmxcompat_8c.html \ + html/dmxcompat_8h.html \ + html/dmxcompat_8h_source.html \ + html/dmxconfig_8c.html \ + html/dmxconfig_8h.html \ + html/dmxconfig_8h_source.html \ + html/dmxconsole_8c.html \ + html/dmxconsole_8h.html \ + html/dmxconsole_8h_source.html \ + html/dmxcursor_8c.html \ + html/dmxcursor_8h.html \ + html/dmxcursor_8h_source.html \ + html/dmxdetach_8c.html \ + html/dmxdpms_8c.html \ + html/dmxdpms_8h.html \ + html/dmxdpms_8h_source.html \ + html/dmxdummy_8c.html \ + html/dmxdummy_8h.html \ + html/dmxdummy_8h_source.html \ + html/dmxevents_8c.html \ + html/dmxevents_8h.html \ + html/dmxevents_8h_source.html \ + html/dmxextension_8c.html \ + html/dmxextension_8h.html \ + html/dmxextension_8h_source.html \ + html/dmxfont_8c.html \ + html/dmxfont_8h.html \ + html/dmxfont_8h_source.html \ + html/dmxgc_8c.html \ + html/dmxgc_8h.html \ + html/dmxgc_8h_source.html \ + html/dmxgcops_8c.html \ + html/dmxgcops_8h.html \ + html/dmxgcops_8h_source.html \ + html/dmx__glxvisuals_8h_source.html \ + html/dmxinit_8c.html \ + html/dmxinit_8h.html \ + html/dmxinit_8h_source.html \ + html/dmxinput_8c.html \ + html/dmxinput_8h.html \ + html/dmxinput_8h_source.html \ + html/dmxinputinit_8c.html \ + html/dmxinputinit_8h.html \ + html/dmxinputinit_8h_source.html \ + html/dmxlog_8c.html \ + html/dmxlog_8h.html \ + html/dmxlog_8h_source.html \ + html/dmxmap_8c.html \ + html/dmxmap_8h.html \ + html/dmxmap_8h_source.html \ + html/dmxmotion_8c.html \ + html/dmxmotion_8h.html \ + html/dmxmotion_8h_source.html \ + html/dmxparse_8c.html \ + html/dmxparse_8h.html \ + html/dmxparse_8h_source.html \ + html/dmxpict_8c.html \ + html/dmxpict_8h.html \ + html/dmxpict_8h_source.html \ + html/dmxpixmap_8c.html \ + html/dmxpixmap_8h.html \ + html/dmxpixmap_8h_source.html \ + html/dmxprint_8c.html \ + html/dmxprint_8h.html \ + html/dmxprint_8h_source.html \ + html/dmxprop_8c.html \ + html/dmxprop_8h.html \ + html/dmxprop_8h_source.html \ + html/dmxscrinit_8c.html \ + html/dmxscrinit_8h.html \ + html/dmxscrinit_8h_source.html \ + html/dmxshadow_8c.html \ + html/dmxshadow_8h.html \ + html/dmxshadow_8h_source.html \ + html/dmxsigio_8c.html \ + html/dmxsigio_8h.html \ + html/dmxsigio_8h_source.html \ + html/dmxstat_8c.html \ + html/dmxstat_8h.html \ + html/dmxstat_8h_source.html \ + html/dmxsync_8c.html \ + html/dmxsync_8h.html \ + html/dmxsync_8h_source.html \ + html/dmxvisual_8c.html \ + html/dmxvisual_8h.html \ + html/dmxvisual_8h_source.html \ + html/dmxwindow_8c.html \ + html/dmxwindow_8h.html \ + html/dmxwindow_8h_source.html \ + html/dmxxinput_8c.html \ + html/doxygen.css \ + html/doxygen.png \ + html/files.html \ + html/ftv2blank.png \ + html/ftv2doc.png \ + html/ftv2folderclosed.png \ + html/ftv2folderopen.png \ + html/ftv2lastnode.png \ + html/ftv2link.png \ + html/ftv2mlastnode.png \ + html/ftv2mnode.png \ + html/ftv2node.png \ + html/ftv2plastnode.png \ + html/ftv2pnode.png \ + html/ftv2vertline.png \ + html/functions.html \ + html/functions_vars.html \ + html/globals_defs.html \ + html/globals_enum.html \ + html/globals_eval.html \ + html/globals_func.html \ + html/globals.html \ + html/globals_type.html \ + html/globals_vars.html \ + html/index.html \ + html/lnx-keyboard_8c.html \ + html/lnx-keyboard_8h.html \ + html/lnx-keyboard_8h_source.html \ + html/lnx-ms_8c.html \ + html/lnx-ms_8h.html \ + html/lnx-ms_8h_source.html \ + html/lnx-ps2_8c.html \ + html/lnx-ps2_8h.html \ + html/lnx-ps2_8h_source.html \ + html/main.html \ + html/struct__dmxArg.html \ + html/struct__dmxColormapPriv.html \ + html/structDMXConfigCmdStruct.html \ + html/struct__DMXConfigComment.html \ + html/struct__DMXConfigDisplay.html \ + html/struct__DMXConfigEntry.html \ + html/struct__DMXConfigFullDim.html \ + html/structDMXConfigListStruct.html \ + html/struct__DMXConfigNumber.html \ + html/struct__DMXConfigOption.html \ + html/struct__DMXConfigPair.html \ + html/struct__DMXConfigParam.html \ + html/struct__DMXConfigPartDim.html \ + html/struct__DMXConfigString.html \ + html/struct__DMXConfigSub.html \ + html/struct__DMXConfigToken.html \ + html/struct__DMXConfigVirtual.html \ + html/struct__DMXConfigWall.html \ + html/struct__dmxCursorPriv.html \ + html/structDMXDesktopAttributesRec.html \ + html/struct__DMXEventMap.html \ + html/struct__dmxFontPriv.html \ + html/struct__dmxGCPriv.html \ + html/structdmxGlxVisualPrivate.html \ + html/struct__dmxGlyphPriv.html \ + html/structDMXInputAttributesRec.html \ + html/struct__DMXInputInfo.html \ + html/struct__DMXLocalInitInfo.html \ + html/struct__DMXLocalInputInfo.html \ + html/struct__dmxPictPriv.html \ + html/struct__dmxPixPriv.html \ + html/structDMXScreenAttributesRec.html \ + html/struct__DMXScreenInfo.html \ + html/struct__DMXStatAvg.html \ + html/struct__DMXStatInfo.html \ + html/structDMXWindowAttributesRec.html \ + html/struct__dmxWinPriv.html \ + html/struct__myPrivate.html \ + html/tree.html \ + html/usb-common_8c.html \ + html/usb-common_8h.html \ + html/usb-common_8h_source.html \ + html/usb-keyboard_8c.html \ + html/usb-keyboard_8h.html \ + html/usb-keyboard_8h_source.html \ + html/usb-mouse_8c.html \ + html/usb-mouse_8h.html \ + html/usb-mouse_8h_source.html \ + html/usb-other_8c.html \ + html/usb-other_8h.html \ + html/usb-other_8h_source.html \ + html/usb-private_8h.html \ + html/usb-private_8h_source.html + +$(builddir)/doxygen.head: + $(LN_S) $(srcdir)/doxygen.head $@ + +$(builddir)/doxygen.foot: + $(LN_S) $(srcdir)/doxygen.foot $@ + +$(builddir)doxygen.css: + $(LN_S) $(srcdir)/doxygen.css $@ + diff --git a/xorg-server/hw/xfree86/common/xf86Option.c b/xorg-server/hw/xfree86/common/xf86Option.c index d7b294a86..16c27e5ee 100644 --- a/xorg-server/hw/xfree86/common/xf86Option.c +++ b/xorg-server/hw/xfree86/common/xf86Option.c @@ -1,895 +1,895 @@ -/* - * Copyright (c) 1998-2003 by The XFree86 Project, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Except as contained in this notice, the name of the copyright holder(s) - * and author(s) shall not be used in advertising or otherwise to promote - * the sale, use or other dealings in this Software without prior written - * authorization from the copyright holder(s) and author(s). - */ - -/* - * Author: David Dawes - * - * This file includes public option handling functions. - */ - -#ifdef HAVE_XORG_CONFIG_H -#include -#endif - -#include -#include -#include -#include "os.h" -#include "xf86.h" -#include "xf86Xinput.h" -#include "xf86Optrec.h" -#include "xf86Parser.h" - -static Bool ParseOptionValue(int scrnIndex, pointer options, OptionInfoPtr p, - Bool markUsed); - -/* - * xf86CollectOptions collects the options from each of the config file - * sections used by the screen and puts the combined list in pScrn->options. - * This function requires that the following have been initialised: - * - * pScrn->confScreen - * pScrn->Entities[i]->device - * pScrn->display - * pScrn->monitor - * - * The extraOpts parameter may optionally contain a list of additional options - * to include. - * - * The order of precedence for options is: - * - * extraOpts, display, confScreen, monitor, device - */ - -void -xf86CollectOptions(ScrnInfoPtr pScrn, pointer extraOpts) -{ - XF86OptionPtr tmp; - XF86OptionPtr extras = (XF86OptionPtr)extraOpts; - GDevPtr device; - - int i; - - pScrn->options = NULL; - - for (i=pScrn->numEntities - 1; i >= 0; i--) { - device = xf86GetDevFromEntity(pScrn->entityList[i], - pScrn->entityInstanceList[i]); - if (device && device->options) { - tmp = xf86optionListDup(device->options); - if (pScrn->options) - xf86optionListMerge(pScrn->options,tmp); - else - pScrn->options = tmp; - } - } - if (pScrn->monitor->options) { - tmp = xf86optionListDup(pScrn->monitor->options); - if (pScrn->options) - pScrn->options = xf86optionListMerge(pScrn->options, tmp); - else - pScrn->options = tmp; - } - if (pScrn->confScreen->options) { - tmp = xf86optionListDup(pScrn->confScreen->options); - if (pScrn->options) - pScrn->options = xf86optionListMerge(pScrn->options, tmp); - else - pScrn->options = tmp; - } - if (pScrn->display->options) { - tmp = xf86optionListDup(pScrn->display->options); - if (pScrn->options) - pScrn->options = xf86optionListMerge(pScrn->options, tmp); - else - pScrn->options = tmp; - } - if (extras) { - tmp = xf86optionListDup(extras); - if (pScrn->options) - pScrn->options = xf86optionListMerge(pScrn->options, tmp); - else - pScrn->options = tmp; - } -} - -/* - * xf86CollectInputOptions collects extra options for an InputDevice (other - * than those added by the config backend). - * The options are merged into the existing ones and thus take precedence - * over the others. - */ - -void -xf86CollectInputOptions(InputInfoPtr pInfo, const char **defaultOpts) -{ - if (defaultOpts) { - XF86OptionPtr tmp =xf86optionListCreate(defaultOpts, -1, 0); - if (pInfo->options) - pInfo->options = xf86optionListMerge(pInfo->options, tmp); - else - pInfo->options = tmp; - } -} - -/** - * Duplicate the option list passed in. The returned pointer will be a newly - * allocated option list and must be freed by the caller. - */ -pointer -xf86OptionListDuplicate(pointer options) -{ - pointer o = NULL; - - while (options) - { - o = xf86AddNewOption(o, xf86OptionName(options), xf86OptionValue(options)); - options = xf86nextOption(options); - } - - return o; -} - - -/* Created for new XInput stuff -- essentially extensions to the parser */ - -static int -LookupIntOption(pointer optlist, const char *name, int deflt, Bool markUsed) -{ - OptionInfoRec o; - - o.name = name; - o.type = OPTV_INTEGER; - if (ParseOptionValue(-1, optlist, &o, markUsed)) - deflt = o.value.num; - return deflt; -} - - -static double -LookupRealOption(pointer optlist, const char *name, double deflt, - Bool markUsed) -{ - OptionInfoRec o; - - o.name = name; - o.type = OPTV_REAL; - if (ParseOptionValue(-1, optlist, &o, markUsed)) - deflt = o.value.realnum; - return deflt; -} - - -static char * -LookupStrOption(pointer optlist, const char *name, char *deflt, Bool markUsed) -{ - OptionInfoRec o; - - o.name = name; - o.type = OPTV_STRING; - if (ParseOptionValue(-1, optlist, &o, markUsed)) - deflt = o.value.str; - if (deflt) - return strdup(deflt); - else - return NULL; -} - - -static int -LookupBoolOption(pointer optlist, const char *name, int deflt, Bool markUsed) -{ - OptionInfoRec o; - - o.name = name; - o.type = OPTV_BOOLEAN; - if (ParseOptionValue(-1, optlist, &o, markUsed)) - deflt = o.value.bool; - return deflt; -} - -static int -LookupPercentOption(pointer optlist, const char *name, double deflt, Bool markUsed) -{ - OptionInfoRec o; - - o.name = name; - o.type = OPTV_PERCENT; - if (ParseOptionValue(-1, optlist, &o, markUsed)) - deflt = o.value.realnum; - return deflt; -} - -/* These xf86Set* functions are intended for use by non-screen specific code */ - -int -xf86SetIntOption(pointer optlist, const char *name, int deflt) -{ - return LookupIntOption(optlist, name, deflt, TRUE); -} - - -double -xf86SetRealOption(pointer optlist, const char *name, double deflt) -{ - return LookupRealOption(optlist, name, deflt, TRUE); -} - - -char * -xf86SetStrOption(pointer optlist, const char *name, char *deflt) -{ - return LookupStrOption(optlist, name, deflt, TRUE); -} - - -int -xf86SetBoolOption(pointer optlist, const char *name, int deflt) -{ - return LookupBoolOption(optlist, name, deflt, TRUE); -} - -double -xf86SetPercentOption(pointer optlist, const char *name, double deflt) -{ - return LookupPercentOption(optlist, name, deflt, TRUE); -} - -/* - * These are like the Set*Option functions, but they don't mark the options - * as used. - */ -int -xf86CheckIntOption(pointer optlist, const char *name, int deflt) -{ - return LookupIntOption(optlist, name, deflt, FALSE); -} - - -double -xf86CheckRealOption(pointer optlist, const char *name, double deflt) -{ - return LookupRealOption(optlist, name, deflt, FALSE); -} - - -char * -xf86CheckStrOption(pointer optlist, const char *name, char *deflt) -{ - return LookupStrOption(optlist, name, deflt, FALSE); -} - - -int -xf86CheckBoolOption(pointer optlist, const char *name, int deflt) -{ - return LookupBoolOption(optlist, name, deflt, FALSE); -} - - -double -xf86CheckPercentOption(pointer optlist, const char *name, double deflt) -{ - return LookupPercentOption(optlist, name, deflt, FALSE); -} -/* - * addNewOption() has the required property of replacing the option value - * if the option is already present. - */ -pointer -xf86ReplaceIntOption(pointer optlist, const char *name, const int val) -{ - char tmp[16]; - sprintf(tmp,"%i",val); - return xf86AddNewOption(optlist,name,tmp); -} - -pointer -xf86ReplaceRealOption(pointer optlist, const char *name, const double val) -{ - char tmp[32]; - snprintf(tmp,32,"%f",val); - return xf86AddNewOption(optlist,name,tmp); -} - -pointer -xf86ReplaceBoolOption(pointer optlist, const char *name, const Bool val) -{ - return xf86AddNewOption(optlist,name,val?"True":"False"); -} - -pointer -xf86ReplacePercentOption(pointer optlist, const char *name, const double val) -{ - char tmp[16]; - sprintf(tmp, "%lf%%", val); - return xf86AddNewOption(optlist,name,tmp); -} - -pointer -xf86ReplaceStrOption(pointer optlist, const char *name, const char* val) -{ - return xf86AddNewOption(optlist,name,val); -} - -pointer -xf86AddNewOption(pointer head, const char *name, const char *val) -{ - /* XXX These should actually be allocated in the parser library. */ - char *tmp = strdup(val); - char *tmp_name = strdup(name); - - return xf86addNewOption(head, tmp_name, tmp); -} - - -pointer -xf86NewOption(char *name, char *value) -{ - return xf86newOption(name, value); -} - - -pointer -xf86NextOption(pointer list) -{ - return xf86nextOption(list); -} - -pointer -xf86OptionListCreate(const char **options, int count, int used) -{ - return xf86optionListCreate(options, count, used); -} - -pointer -xf86OptionListMerge(pointer head, pointer tail) -{ - return xf86optionListMerge(head, tail); -} - -void -xf86OptionListFree(pointer opt) -{ - xf86optionListFree(opt); -} - -char * -xf86OptionName(pointer opt) -{ - return xf86optionName(opt); -} - -char * -xf86OptionValue(pointer opt) -{ - return xf86optionValue(opt); -} - -void -xf86OptionListReport(pointer parm) -{ - XF86OptionPtr opts = parm; - - while(opts) { - if (xf86optionValue(opts)) - xf86ErrorFVerb(5, "\tOption \"%s\" \"%s\"\n", - xf86optionName(opts), xf86optionValue(opts)); - else - xf86ErrorFVerb( 5, "\tOption \"%s\"\n", xf86optionName(opts)); - opts = xf86nextOption(opts); - } -} - -/* End of XInput-caused section */ - -pointer -xf86FindOption(pointer options, const char *name) -{ - return xf86findOption(options, name); -} - - -char * -xf86FindOptionValue(pointer options, const char *name) -{ - return xf86findOptionValue(options, name); -} - - -void -xf86MarkOptionUsed(pointer option) -{ - if (option != NULL) - ((XF86OptionPtr)option)->opt_used = TRUE; -} - - -void -xf86MarkOptionUsedByName(pointer options, const char *name) -{ - XF86OptionPtr opt; - - opt = xf86findOption(options, name); - if (opt != NULL) - opt->opt_used = TRUE; -} - -Bool -xf86CheckIfOptionUsed(pointer option) -{ - if (option != NULL) - return ((XF86OptionPtr)option)->opt_used; - else - return FALSE; -} - -Bool -xf86CheckIfOptionUsedByName(pointer options, const char *name) -{ - XF86OptionPtr opt; - - opt = xf86findOption(options, name); - if (opt != NULL) - return opt->opt_used; - else - return FALSE; -} - -void -xf86ShowUnusedOptions(int scrnIndex, pointer options) -{ - XF86OptionPtr opt = options; - - while (opt) { - if (opt->opt_name && !opt->opt_used) { - xf86DrvMsg(scrnIndex, X_WARNING, "Option \"%s\" is not used\n", - opt->opt_name); - } - opt = opt->list.next; - } -} - - -static Bool -GetBoolValue(OptionInfoPtr p, const char *s) -{ - return xf86getBoolValue(&p->value.bool, s); -} - -static Bool -ParseOptionValue(int scrnIndex, pointer options, OptionInfoPtr p, - Bool markUsed) -{ - char *s, *end; - Bool wasUsed = FALSE; - - if ((s = xf86findOptionValue(options, p->name)) != NULL) { - if (markUsed) { - wasUsed = xf86CheckIfOptionUsedByName(options, p->name); - xf86MarkOptionUsedByName(options, p->name); - } - switch (p->type) { - case OPTV_INTEGER: - if (*s == '\0') { - xf86DrvMsg(scrnIndex, X_WARNING, - "Option \"%s\" requires an integer value\n", - p->name); - p->found = FALSE; - } else { - p->value.num = strtoul(s, &end, 0); - if (*end == '\0') { - p->found = TRUE; - } else { - xf86DrvMsg(scrnIndex, X_WARNING, - "Option \"%s\" requires an integer value\n", - p->name); - p->found = FALSE; - } - } - break; - case OPTV_STRING: - if (*s == '\0') { - xf86DrvMsg(scrnIndex, X_WARNING, - "Option \"%s\" requires an string value\n", - p->name); - p->found = FALSE; - } else { - p->value.str = s; - p->found = TRUE; - } - break; - case OPTV_ANYSTR: - p->value.str = s; - p->found = TRUE; - break; - case OPTV_REAL: - if (*s == '\0') { - xf86DrvMsg(scrnIndex, X_WARNING, - "Option \"%s\" requires a floating point value\n", - p->name); - p->found = FALSE; - } else { - p->value.realnum = strtod(s, &end); - if (*end == '\0') { - p->found = TRUE; - } else { - xf86DrvMsg(scrnIndex, X_WARNING, - "Option \"%s\" requires a floating point value\n", - p->name); - p->found = FALSE; - } - } - break; - case OPTV_BOOLEAN: - if (GetBoolValue(p, s)) { - p->found = TRUE; - } else { - xf86DrvMsg(scrnIndex, X_WARNING, - "Option \"%s\" requires a boolean value\n", p->name); - p->found = FALSE; - } - break; - case OPTV_PERCENT: - { - char tmp = 0; - /* awkward match, but %% doesn't increase the match counter, - * hence 100 looks the same as 100% to the caller of sccanf - */ - if (sscanf(s, "%lf%c", &p->value.realnum, &tmp) != 2 || tmp != '%') { - xf86DrvMsg(scrnIndex, X_WARNING, - "Option \"%s\" requires a percent value\n", p->name); - p->found = FALSE; - } else { - p->found = TRUE; - } - } - break; - case OPTV_FREQ: - if (*s == '\0') { - xf86DrvMsg(scrnIndex, X_WARNING, - "Option \"%s\" requires a frequency value\n", - p->name); - p->found = FALSE; - } else { - double freq = strtod(s, &end); - int units = 0; - - if (end != s) { - p->found = TRUE; - if (!xf86NameCmp(end, "Hz")) - units = 1; - else if (!xf86NameCmp(end, "kHz") || - !xf86NameCmp(end, "k")) - units = 1000; - else if (!xf86NameCmp(end, "MHz") || - !xf86NameCmp(end, "M")) - units = 1000000; - else { - xf86DrvMsg(scrnIndex, X_WARNING, - "Option \"%s\" requires a frequency value\n", - p->name); - p->found = FALSE; - } - if (p->found) - freq *= (double)units; - } else { - xf86DrvMsg(scrnIndex, X_WARNING, - "Option \"%s\" requires a frequency value\n", - p->name); - p->found = FALSE; - } - if (p->found) { - p->value.freq.freq = freq; - p->value.freq.units = units; - } - } - break; - case OPTV_NONE: - /* Should never get here */ - p->found = FALSE; - break; - } - if (p->found && markUsed) { - int verb = 2; - if (wasUsed) - verb = 4; - xf86DrvMsgVerb(scrnIndex, X_CONFIG, verb, "Option \"%s\"", p->name); - if (!(p->type == OPTV_BOOLEAN && *s == 0)) { - xf86ErrorFVerb(verb, " \"%s\"", s); - } - xf86ErrorFVerb(verb, "\n"); - } - } else if (p->type == OPTV_BOOLEAN) { - /* Look for matches with options with or without a "No" prefix. */ - char *n, *newn; - OptionInfoRec opt; - - n = xf86NormalizeName(p->name); - if (!n) { - p->found = FALSE; - return FALSE; - } - if (strncmp(n, "no", 2) == 0) { - newn = n + 2; - } else { - free(n); - if (asprintf(&n, "No%s", p->name) == -1) { - p->found = FALSE; - return FALSE; - } - newn = n; - } - if ((s = xf86findOptionValue(options, newn)) != NULL) { - if (markUsed) - xf86MarkOptionUsedByName(options, newn); - if (GetBoolValue(&opt, s)) { - p->value.bool = !opt.value.bool; - p->found = TRUE; - } else { - xf86DrvMsg(scrnIndex, X_WARNING, - "Option \"%s\" requires a boolean value\n", newn); - p->found = FALSE; - } - } else { - p->found = FALSE; - } - if (p->found && markUsed) { - xf86DrvMsgVerb(scrnIndex, X_CONFIG, 2, "Option \"%s\"", newn); - if (*s != 0) { - xf86ErrorFVerb(2, " \"%s\"", s); - } - xf86ErrorFVerb(2, "\n"); - } - free(n); - } else { - p->found = FALSE; - } - return p->found; -} - - -void -xf86ProcessOptions(int scrnIndex, pointer options, OptionInfoPtr optinfo) -{ - OptionInfoPtr p; - - for (p = optinfo; p->name != NULL; p++) { - ParseOptionValue(scrnIndex, options, p, TRUE); - } -} - - -OptionInfoPtr -xf86TokenToOptinfo(const OptionInfoRec *table, int token) -{ - const OptionInfoRec *p, *match = NULL, *set = NULL; - - if (!table) { - ErrorF("xf86TokenToOptinfo: table is NULL\n"); - return NULL; - } - - for (p = table; p->token >= 0; p++) { - if (p->token == token) { - match = p; - if (p->found) - set = p; - } - } - - if (set) - return (OptionInfoPtr)set; - else if (match) - return (OptionInfoPtr)match; - else - return NULL; -} - - -const char * -xf86TokenToOptName(const OptionInfoRec *table, int token) -{ - const OptionInfoRec *p; - - p = xf86TokenToOptinfo(table, token); - return p->name; -} - - -Bool -xf86IsOptionSet(const OptionInfoRec *table, int token) -{ - OptionInfoPtr p; - - p = xf86TokenToOptinfo(table, token); - return p && p->found; -} - - -char * -xf86GetOptValString(const OptionInfoRec *table, int token) -{ - OptionInfoPtr p; - - p = xf86TokenToOptinfo(table, token); - if (p && p->found) - return p->value.str; - else - return NULL; -} - - -Bool -xf86GetOptValInteger(const OptionInfoRec *table, int token, int *value) -{ - OptionInfoPtr p; - - p = xf86TokenToOptinfo(table, token); - if (p && p->found) { - *value = p->value.num; - return TRUE; - } else - return FALSE; -} - - -Bool -xf86GetOptValULong(const OptionInfoRec *table, int token, unsigned long *value) -{ - OptionInfoPtr p; - - p = xf86TokenToOptinfo(table, token); - if (p && p->found) { - *value = p->value.num; - return TRUE; - } else - return FALSE; -} - - -Bool -xf86GetOptValReal(const OptionInfoRec *table, int token, double *value) -{ - OptionInfoPtr p; - - p = xf86TokenToOptinfo(table, token); - if (p && p->found) { - *value = p->value.realnum; - return TRUE; - } else - return FALSE; -} - - -Bool -xf86GetOptValFreq(const OptionInfoRec *table, int token, - OptFreqUnits expectedUnits, double *value) -{ - OptionInfoPtr p; - - p = xf86TokenToOptinfo(table, token); - if (p && p->found) { - if (p->value.freq.units > 0) { - /* Units give, so the scaling is known. */ - switch (expectedUnits) { - case OPTUNITS_HZ: - *value = p->value.freq.freq; - break; - case OPTUNITS_KHZ: - *value = p->value.freq.freq / 1000.0; - break; - case OPTUNITS_MHZ: - *value = p->value.freq.freq / 1000000.0; - break; - } - } else { - /* No units given, so try to guess the scaling. */ - switch (expectedUnits) { - case OPTUNITS_HZ: - *value = p->value.freq.freq; - break; - case OPTUNITS_KHZ: - if (p->value.freq.freq > 1000.0) - *value = p->value.freq.freq / 1000.0; - else - *value = p->value.freq.freq; - break; - case OPTUNITS_MHZ: - if (p->value.freq.freq > 1000000.0) - *value = p->value.freq.freq / 1000000.0; - else if (p->value.freq.freq > 1000.0) - *value = p->value.freq.freq / 1000.0; - else - *value = p->value.freq.freq; - } - } - return TRUE; - } else - return FALSE; -} - - -Bool -xf86GetOptValBool(const OptionInfoRec *table, int token, Bool *value) -{ - OptionInfoPtr p; - - p = xf86TokenToOptinfo(table, token); - if (p && p->found) { - *value = p->value.bool; - return TRUE; - } else - return FALSE; -} - - -Bool -xf86ReturnOptValBool(const OptionInfoRec *table, int token, Bool def) -{ - OptionInfoPtr p; - - p = xf86TokenToOptinfo(table, token); - if (p && p->found) { - return p->value.bool; - } else - return def; -} - - -int -xf86NameCmp(const char *s1, const char *s2) -{ - return xf86nameCompare(s1, s2); -} - -char * -xf86NormalizeName(const char *s) -{ - char *ret, *q; - const char *p; - - if (s == NULL) - return NULL; - - ret = malloc(strlen(s) + 1); - for (p = s, q = ret; *p != 0; p++) { - switch (*p) { - case '_': - case ' ': - case '\t': - continue; - default: - if (isupper(*p)) - *q++ = tolower(*p); - else - *q++ = *p; - } - } - *q = '\0'; - return ret; -} +/* + * Copyright (c) 1998-2003 by The XFree86 Project, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the copyright holder(s) + * and author(s) shall not be used in advertising or otherwise to promote + * the sale, use or other dealings in this Software without prior written + * authorization from the copyright holder(s) and author(s). + */ + +/* + * Author: David Dawes + * + * This file includes public option handling functions. + */ + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include +#include +#include +#include "os.h" +#include "xf86.h" +#include "xf86Xinput.h" +#include "xf86Optrec.h" +#include "xf86Parser.h" + +static Bool ParseOptionValue(int scrnIndex, pointer options, OptionInfoPtr p, + Bool markUsed); + +/* + * xf86CollectOptions collects the options from each of the config file + * sections used by the screen and puts the combined list in pScrn->options. + * This function requires that the following have been initialised: + * + * pScrn->confScreen + * pScrn->Entities[i]->device + * pScrn->display + * pScrn->monitor + * + * The extraOpts parameter may optionally contain a list of additional options + * to include. + * + * The order of precedence for options is: + * + * extraOpts, display, confScreen, monitor, device + */ + +void +xf86CollectOptions(ScrnInfoPtr pScrn, pointer extraOpts) +{ + XF86OptionPtr tmp; + XF86OptionPtr extras = (XF86OptionPtr)extraOpts; + GDevPtr device; + + int i; + + pScrn->options = NULL; + + for (i=pScrn->numEntities - 1; i >= 0; i--) { + device = xf86GetDevFromEntity(pScrn->entityList[i], + pScrn->entityInstanceList[i]); + if (device && device->options) { + tmp = xf86optionListDup(device->options); + if (pScrn->options) + xf86optionListMerge(pScrn->options,tmp); + else + pScrn->options = tmp; + } + } + if (pScrn->monitor->options) { + tmp = xf86optionListDup(pScrn->monitor->options); + if (pScrn->options) + pScrn->options = xf86optionListMerge(pScrn->options, tmp); + else + pScrn->options = tmp; + } + if (pScrn->confScreen->options) { + tmp = xf86optionListDup(pScrn->confScreen->options); + if (pScrn->options) + pScrn->options = xf86optionListMerge(pScrn->options, tmp); + else + pScrn->options = tmp; + } + if (pScrn->display->options) { + tmp = xf86optionListDup(pScrn->display->options); + if (pScrn->options) + pScrn->options = xf86optionListMerge(pScrn->options, tmp); + else + pScrn->options = tmp; + } + if (extras) { + tmp = xf86optionListDup(extras); + if (pScrn->options) + pScrn->options = xf86optionListMerge(pScrn->options, tmp); + else + pScrn->options = tmp; + } +} + +/* + * xf86CollectInputOptions collects extra options for an InputDevice (other + * than those added by the config backend). + * The options are merged into the existing ones and thus take precedence + * over the others. + */ + +void +xf86CollectInputOptions(InputInfoPtr pInfo, const char **defaultOpts) +{ + if (defaultOpts) { + XF86OptionPtr tmp =xf86optionListCreate(defaultOpts, -1, 0); + if (pInfo->options) + pInfo->options = xf86optionListMerge(tmp, pInfo->options); + else + pInfo->options = tmp; + } +} + +/** + * Duplicate the option list passed in. The returned pointer will be a newly + * allocated option list and must be freed by the caller. + */ +pointer +xf86OptionListDuplicate(pointer options) +{ + pointer o = NULL; + + while (options) + { + o = xf86AddNewOption(o, xf86OptionName(options), xf86OptionValue(options)); + options = xf86nextOption(options); + } + + return o; +} + + +/* Created for new XInput stuff -- essentially extensions to the parser */ + +static int +LookupIntOption(pointer optlist, const char *name, int deflt, Bool markUsed) +{ + OptionInfoRec o; + + o.name = name; + o.type = OPTV_INTEGER; + if (ParseOptionValue(-1, optlist, &o, markUsed)) + deflt = o.value.num; + return deflt; +} + + +static double +LookupRealOption(pointer optlist, const char *name, double deflt, + Bool markUsed) +{ + OptionInfoRec o; + + o.name = name; + o.type = OPTV_REAL; + if (ParseOptionValue(-1, optlist, &o, markUsed)) + deflt = o.value.realnum; + return deflt; +} + + +static char * +LookupStrOption(pointer optlist, const char *name, char *deflt, Bool markUsed) +{ + OptionInfoRec o; + + o.name = name; + o.type = OPTV_STRING; + if (ParseOptionValue(-1, optlist, &o, markUsed)) + deflt = o.value.str; + if (deflt) + return strdup(deflt); + else + return NULL; +} + + +static int +LookupBoolOption(pointer optlist, const char *name, int deflt, Bool markUsed) +{ + OptionInfoRec o; + + o.name = name; + o.type = OPTV_BOOLEAN; + if (ParseOptionValue(-1, optlist, &o, markUsed)) + deflt = o.value.bool; + return deflt; +} + +static int +LookupPercentOption(pointer optlist, const char *name, double deflt, Bool markUsed) +{ + OptionInfoRec o; + + o.name = name; + o.type = OPTV_PERCENT; + if (ParseOptionValue(-1, optlist, &o, markUsed)) + deflt = o.value.realnum; + return deflt; +} + +/* These xf86Set* functions are intended for use by non-screen specific code */ + +int +xf86SetIntOption(pointer optlist, const char *name, int deflt) +{ + return LookupIntOption(optlist, name, deflt, TRUE); +} + + +double +xf86SetRealOption(pointer optlist, const char *name, double deflt) +{ + return LookupRealOption(optlist, name, deflt, TRUE); +} + + +char * +xf86SetStrOption(pointer optlist, const char *name, char *deflt) +{ + return LookupStrOption(optlist, name, deflt, TRUE); +} + + +int +xf86SetBoolOption(pointer optlist, const char *name, int deflt) +{ + return LookupBoolOption(optlist, name, deflt, TRUE); +} + +double +xf86SetPercentOption(pointer optlist, const char *name, double deflt) +{ + return LookupPercentOption(optlist, name, deflt, TRUE); +} + +/* + * These are like the Set*Option functions, but they don't mark the options + * as used. + */ +int +xf86CheckIntOption(pointer optlist, const char *name, int deflt) +{ + return LookupIntOption(optlist, name, deflt, FALSE); +} + + +double +xf86CheckRealOption(pointer optlist, const char *name, double deflt) +{ + return LookupRealOption(optlist, name, deflt, FALSE); +} + + +char * +xf86CheckStrOption(pointer optlist, const char *name, char *deflt) +{ + return LookupStrOption(optlist, name, deflt, FALSE); +} + + +int +xf86CheckBoolOption(pointer optlist, const char *name, int deflt) +{ + return LookupBoolOption(optlist, name, deflt, FALSE); +} + + +double +xf86CheckPercentOption(pointer optlist, const char *name, double deflt) +{ + return LookupPercentOption(optlist, name, deflt, FALSE); +} +/* + * addNewOption() has the required property of replacing the option value + * if the option is already present. + */ +pointer +xf86ReplaceIntOption(pointer optlist, const char *name, const int val) +{ + char tmp[16]; + sprintf(tmp,"%i",val); + return xf86AddNewOption(optlist,name,tmp); +} + +pointer +xf86ReplaceRealOption(pointer optlist, const char *name, const double val) +{ + char tmp[32]; + snprintf(tmp,32,"%f",val); + return xf86AddNewOption(optlist,name,tmp); +} + +pointer +xf86ReplaceBoolOption(pointer optlist, const char *name, const Bool val) +{ + return xf86AddNewOption(optlist,name,val?"True":"False"); +} + +pointer +xf86ReplacePercentOption(pointer optlist, const char *name, const double val) +{ + char tmp[16]; + sprintf(tmp, "%lf%%", val); + return xf86AddNewOption(optlist,name,tmp); +} + +pointer +xf86ReplaceStrOption(pointer optlist, const char *name, const char* val) +{ + return xf86AddNewOption(optlist,name,val); +} + +pointer +xf86AddNewOption(pointer head, const char *name, const char *val) +{ + /* XXX These should actually be allocated in the parser library. */ + char *tmp = strdup(val); + char *tmp_name = strdup(name); + + return xf86addNewOption(head, tmp_name, tmp); +} + + +pointer +xf86NewOption(char *name, char *value) +{ + return xf86newOption(name, value); +} + + +pointer +xf86NextOption(pointer list) +{ + return xf86nextOption(list); +} + +pointer +xf86OptionListCreate(const char **options, int count, int used) +{ + return xf86optionListCreate(options, count, used); +} + +pointer +xf86OptionListMerge(pointer head, pointer tail) +{ + return xf86optionListMerge(head, tail); +} + +void +xf86OptionListFree(pointer opt) +{ + xf86optionListFree(opt); +} + +char * +xf86OptionName(pointer opt) +{ + return xf86optionName(opt); +} + +char * +xf86OptionValue(pointer opt) +{ + return xf86optionValue(opt); +} + +void +xf86OptionListReport(pointer parm) +{ + XF86OptionPtr opts = parm; + + while(opts) { + if (xf86optionValue(opts)) + xf86ErrorFVerb(5, "\tOption \"%s\" \"%s\"\n", + xf86optionName(opts), xf86optionValue(opts)); + else + xf86ErrorFVerb( 5, "\tOption \"%s\"\n", xf86optionName(opts)); + opts = xf86nextOption(opts); + } +} + +/* End of XInput-caused section */ + +pointer +xf86FindOption(pointer options, const char *name) +{ + return xf86findOption(options, name); +} + + +char * +xf86FindOptionValue(pointer options, const char *name) +{ + return xf86findOptionValue(options, name); +} + + +void +xf86MarkOptionUsed(pointer option) +{ + if (option != NULL) + ((XF86OptionPtr)option)->opt_used = TRUE; +} + + +void +xf86MarkOptionUsedByName(pointer options, const char *name) +{ + XF86OptionPtr opt; + + opt = xf86findOption(options, name); + if (opt != NULL) + opt->opt_used = TRUE; +} + +Bool +xf86CheckIfOptionUsed(pointer option) +{ + if (option != NULL) + return ((XF86OptionPtr)option)->opt_used; + else + return FALSE; +} + +Bool +xf86CheckIfOptionUsedByName(pointer options, const char *name) +{ + XF86OptionPtr opt; + + opt = xf86findOption(options, name); + if (opt != NULL) + return opt->opt_used; + else + return FALSE; +} + +void +xf86ShowUnusedOptions(int scrnIndex, pointer options) +{ + XF86OptionPtr opt = options; + + while (opt) { + if (opt->opt_name && !opt->opt_used) { + xf86DrvMsg(scrnIndex, X_WARNING, "Option \"%s\" is not used\n", + opt->opt_name); + } + opt = opt->list.next; + } +} + + +static Bool +GetBoolValue(OptionInfoPtr p, const char *s) +{ + return xf86getBoolValue(&p->value.bool, s); +} + +static Bool +ParseOptionValue(int scrnIndex, pointer options, OptionInfoPtr p, + Bool markUsed) +{ + char *s, *end; + Bool wasUsed = FALSE; + + if ((s = xf86findOptionValue(options, p->name)) != NULL) { + if (markUsed) { + wasUsed = xf86CheckIfOptionUsedByName(options, p->name); + xf86MarkOptionUsedByName(options, p->name); + } + switch (p->type) { + case OPTV_INTEGER: + if (*s == '\0') { + xf86DrvMsg(scrnIndex, X_WARNING, + "Option \"%s\" requires an integer value\n", + p->name); + p->found = FALSE; + } else { + p->value.num = strtoul(s, &end, 0); + if (*end == '\0') { + p->found = TRUE; + } else { + xf86DrvMsg(scrnIndex, X_WARNING, + "Option \"%s\" requires an integer value\n", + p->name); + p->found = FALSE; + } + } + break; + case OPTV_STRING: + if (*s == '\0') { + xf86DrvMsg(scrnIndex, X_WARNING, + "Option \"%s\" requires an string value\n", + p->name); + p->found = FALSE; + } else { + p->value.str = s; + p->found = TRUE; + } + break; + case OPTV_ANYSTR: + p->value.str = s; + p->found = TRUE; + break; + case OPTV_REAL: + if (*s == '\0') { + xf86DrvMsg(scrnIndex, X_WARNING, + "Option \"%s\" requires a floating point value\n", + p->name); + p->found = FALSE; + } else { + p->value.realnum = strtod(s, &end); + if (*end == '\0') { + p->found = TRUE; + } else { + xf86DrvMsg(scrnIndex, X_WARNING, + "Option \"%s\" requires a floating point value\n", + p->name); + p->found = FALSE; + } + } + break; + case OPTV_BOOLEAN: + if (GetBoolValue(p, s)) { + p->found = TRUE; + } else { + xf86DrvMsg(scrnIndex, X_WARNING, + "Option \"%s\" requires a boolean value\n", p->name); + p->found = FALSE; + } + break; + case OPTV_PERCENT: + { + char tmp = 0; + /* awkward match, but %% doesn't increase the match counter, + * hence 100 looks the same as 100% to the caller of sccanf + */ + if (sscanf(s, "%lf%c", &p->value.realnum, &tmp) != 2 || tmp != '%') { + xf86DrvMsg(scrnIndex, X_WARNING, + "Option \"%s\" requires a percent value\n", p->name); + p->found = FALSE; + } else { + p->found = TRUE; + } + } + break; + case OPTV_FREQ: + if (*s == '\0') { + xf86DrvMsg(scrnIndex, X_WARNING, + "Option \"%s\" requires a frequency value\n", + p->name); + p->found = FALSE; + } else { + double freq = strtod(s, &end); + int units = 0; + + if (end != s) { + p->found = TRUE; + if (!xf86NameCmp(end, "Hz")) + units = 1; + else if (!xf86NameCmp(end, "kHz") || + !xf86NameCmp(end, "k")) + units = 1000; + else if (!xf86NameCmp(end, "MHz") || + !xf86NameCmp(end, "M")) + units = 1000000; + else { + xf86DrvMsg(scrnIndex, X_WARNING, + "Option \"%s\" requires a frequency value\n", + p->name); + p->found = FALSE; + } + if (p->found) + freq *= (double)units; + } else { + xf86DrvMsg(scrnIndex, X_WARNING, + "Option \"%s\" requires a frequency value\n", + p->name); + p->found = FALSE; + } + if (p->found) { + p->value.freq.freq = freq; + p->value.freq.units = units; + } + } + break; + case OPTV_NONE: + /* Should never get here */ + p->found = FALSE; + break; + } + if (p->found && markUsed) { + int verb = 2; + if (wasUsed) + verb = 4; + xf86DrvMsgVerb(scrnIndex, X_CONFIG, verb, "Option \"%s\"", p->name); + if (!(p->type == OPTV_BOOLEAN && *s == 0)) { + xf86ErrorFVerb(verb, " \"%s\"", s); + } + xf86ErrorFVerb(verb, "\n"); + } + } else if (p->type == OPTV_BOOLEAN) { + /* Look for matches with options with or without a "No" prefix. */ + char *n, *newn; + OptionInfoRec opt; + + n = xf86NormalizeName(p->name); + if (!n) { + p->found = FALSE; + return FALSE; + } + if (strncmp(n, "no", 2) == 0) { + newn = n + 2; + } else { + free(n); + if (asprintf(&n, "No%s", p->name) == -1) { + p->found = FALSE; + return FALSE; + } + newn = n; + } + if ((s = xf86findOptionValue(options, newn)) != NULL) { + if (markUsed) + xf86MarkOptionUsedByName(options, newn); + if (GetBoolValue(&opt, s)) { + p->value.bool = !opt.value.bool; + p->found = TRUE; + } else { + xf86DrvMsg(scrnIndex, X_WARNING, + "Option \"%s\" requires a boolean value\n", newn); + p->found = FALSE; + } + } else { + p->found = FALSE; + } + if (p->found && markUsed) { + xf86DrvMsgVerb(scrnIndex, X_CONFIG, 2, "Option \"%s\"", newn); + if (*s != 0) { + xf86ErrorFVerb(2, " \"%s\"", s); + } + xf86ErrorFVerb(2, "\n"); + } + free(n); + } else { + p->found = FALSE; + } + return p->found; +} + + +void +xf86ProcessOptions(int scrnIndex, pointer options, OptionInfoPtr optinfo) +{ + OptionInfoPtr p; + + for (p = optinfo; p->name != NULL; p++) { + ParseOptionValue(scrnIndex, options, p, TRUE); + } +} + + +OptionInfoPtr +xf86TokenToOptinfo(const OptionInfoRec *table, int token) +{ + const OptionInfoRec *p, *match = NULL, *set = NULL; + + if (!table) { + ErrorF("xf86TokenToOptinfo: table is NULL\n"); + return NULL; + } + + for (p = table; p->token >= 0; p++) { + if (p->token == token) { + match = p; + if (p->found) + set = p; + } + } + + if (set) + return (OptionInfoPtr)set; + else if (match) + return (OptionInfoPtr)match; + else + return NULL; +} + + +const char * +xf86TokenToOptName(const OptionInfoRec *table, int token) +{ + const OptionInfoRec *p; + + p = xf86TokenToOptinfo(table, token); + return p->name; +} + + +Bool +xf86IsOptionSet(const OptionInfoRec *table, int token) +{ + OptionInfoPtr p; + + p = xf86TokenToOptinfo(table, token); + return p && p->found; +} + + +char * +xf86GetOptValString(const OptionInfoRec *table, int token) +{ + OptionInfoPtr p; + + p = xf86TokenToOptinfo(table, token); + if (p && p->found) + return p->value.str; + else + return NULL; +} + + +Bool +xf86GetOptValInteger(const OptionInfoRec *table, int token, int *value) +{ + OptionInfoPtr p; + + p = xf86TokenToOptinfo(table, token); + if (p && p->found) { + *value = p->value.num; + return TRUE; + } else + return FALSE; +} + + +Bool +xf86GetOptValULong(const OptionInfoRec *table, int token, unsigned long *value) +{ + OptionInfoPtr p; + + p = xf86TokenToOptinfo(table, token); + if (p && p->found) { + *value = p->value.num; + return TRUE; + } else + return FALSE; +} + + +Bool +xf86GetOptValReal(const OptionInfoRec *table, int token, double *value) +{ + OptionInfoPtr p; + + p = xf86TokenToOptinfo(table, token); + if (p && p->found) { + *value = p->value.realnum; + return TRUE; + } else + return FALSE; +} + + +Bool +xf86GetOptValFreq(const OptionInfoRec *table, int token, + OptFreqUnits expectedUnits, double *value) +{ + OptionInfoPtr p; + + p = xf86TokenToOptinfo(table, token); + if (p && p->found) { + if (p->value.freq.units > 0) { + /* Units give, so the scaling is known. */ + switch (expectedUnits) { + case OPTUNITS_HZ: + *value = p->value.freq.freq; + break; + case OPTUNITS_KHZ: + *value = p->value.freq.freq / 1000.0; + break; + case OPTUNITS_MHZ: + *value = p->value.freq.freq / 1000000.0; + break; + } + } else { + /* No units given, so try to guess the scaling. */ + switch (expectedUnits) { + case OPTUNITS_HZ: + *value = p->value.freq.freq; + break; + case OPTUNITS_KHZ: + if (p->value.freq.freq > 1000.0) + *value = p->value.freq.freq / 1000.0; + else + *value = p->value.freq.freq; + break; + case OPTUNITS_MHZ: + if (p->value.freq.freq > 1000000.0) + *value = p->value.freq.freq / 1000000.0; + else if (p->value.freq.freq > 1000.0) + *value = p->value.freq.freq / 1000.0; + else + *value = p->value.freq.freq; + } + } + return TRUE; + } else + return FALSE; +} + + +Bool +xf86GetOptValBool(const OptionInfoRec *table, int token, Bool *value) +{ + OptionInfoPtr p; + + p = xf86TokenToOptinfo(table, token); + if (p && p->found) { + *value = p->value.bool; + return TRUE; + } else + return FALSE; +} + + +Bool +xf86ReturnOptValBool(const OptionInfoRec *table, int token, Bool def) +{ + OptionInfoPtr p; + + p = xf86TokenToOptinfo(table, token); + if (p && p->found) { + return p->value.bool; + } else + return def; +} + + +int +xf86NameCmp(const char *s1, const char *s2) +{ + return xf86nameCompare(s1, s2); +} + +char * +xf86NormalizeName(const char *s) +{ + char *ret, *q; + const char *p; + + if (s == NULL) + return NULL; + + ret = malloc(strlen(s) + 1); + for (p = s, q = ret; *p != 0; p++) { + switch (*p) { + case '_': + case ' ': + case '\t': + continue; + default: + if (isupper(*p)) + *q++ = tolower(*p); + else + *q++ = *p; + } + } + *q = '\0'; + return ret; +} diff --git a/xorg-server/hw/xfree86/common/xf86Xinput.c b/xorg-server/hw/xfree86/common/xf86Xinput.c index dad993ec1..b9006ab07 100644 --- a/xorg-server/hw/xfree86/common/xf86Xinput.c +++ b/xorg-server/hw/xfree86/common/xf86Xinput.c @@ -1,1392 +1,1399 @@ -/* - * Copyright 1995-1999 by Frederic Lepied, France. - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that - * copyright notice and this permission notice appear in supporting - * documentation, and that the name of Frederic Lepied not be used in - * advertising or publicity pertaining to distribution of the software without - * specific, written prior permission. Frederic Lepied makes no - * representations about the suitability of this software for any purpose. It - * is provided "as is" without express or implied warranty. - * - * FREDERIC LEPIED DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL FREDERIC LEPIED BE LIABLE FOR ANY SPECIAL, INDIRECT OR - * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, - * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - * - */ -/* - * Copyright (c) 2000-2002 by The XFree86 Project, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * OTHER DEALINGS IN THE SOFTWARE. - * - * Except as contained in this notice, the name of the copyright holder(s) - * and author(s) shall not be used in advertising or otherwise to promote - * the sale, use or other dealings in this Software without prior written - * authorization from the copyright holder(s) and author(s). - */ - -#ifdef HAVE_XORG_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include -#include "xf86.h" -#include "xf86Priv.h" -#include "xf86Config.h" -#include "xf86Xinput.h" -#include "xf86Optrec.h" -#include "mipointer.h" -#include "extinit.h" -#include "loaderProcs.h" - -#include "exevents.h" /* AddInputDevice */ -#include "exglobals.h" -#include "eventstr.h" -#include "inpututils.h" - -#include /* InputClassMatches */ -#ifdef HAVE_FNMATCH_H -#include -#endif -#ifdef HAVE_SYS_UTSNAME_H -#include -#endif - -#include -#include /* for int64_t */ - -#include "mi.h" - -#include /* dix pointer acceleration */ -#include - -#ifdef XFreeXDGA -#include "dgaproc.h" -#endif - -#include "xkbsrv.h" - -/* Valuator verification macro */ -#define XI_VERIFY_VALUATORS(num_valuators) \ - if (num_valuators > MAX_VALUATORS) { \ - xf86Msg(X_ERROR, "%s: num_valuator %d is greater than" \ - " MAX_VALUATORS\n", __FUNCTION__, num_valuators); \ - return; \ - } - -EventListPtr xf86Events = NULL; - -static int -xf86InputDevicePostInit(DeviceIntPtr dev); - -/** - * Eval config and modify DeviceVelocityRec accordingly - */ -static void -ProcessVelocityConfiguration(DeviceIntPtr pDev, char* devname, pointer list, - DeviceVelocityPtr s) -{ - int tempi; - float tempf; - Atom float_prop = XIGetKnownProperty(XATOM_FLOAT); - Atom prop; - - if(!s) - return; - - /* common settings (available via device properties) */ - tempf = xf86SetRealOption(list, "ConstantDeceleration", 1.0); - if (tempf > 1.0) { - xf86Msg(X_CONFIG, "%s: (accel) constant deceleration by %.1f\n", - devname, tempf); - prop = XIGetKnownProperty(ACCEL_PROP_CONSTANT_DECELERATION); - XIChangeDeviceProperty(pDev, prop, float_prop, 32, - PropModeReplace, 1, &tempf, FALSE); - } - - tempf = xf86SetRealOption(list, "AdaptiveDeceleration", 1.0); - if (tempf > 1.0) { - xf86Msg(X_CONFIG, "%s: (accel) adaptive deceleration by %.1f\n", - devname, tempf); - prop = XIGetKnownProperty(ACCEL_PROP_ADAPTIVE_DECELERATION); - XIChangeDeviceProperty(pDev, prop, float_prop, 32, - PropModeReplace, 1, &tempf, FALSE); - } - - /* select profile by number */ - tempi = xf86SetIntOption(list, "AccelerationProfile", - s->statistics.profile_number); - - prop = XIGetKnownProperty(ACCEL_PROP_PROFILE_NUMBER); - if (XIChangeDeviceProperty(pDev, prop, XA_INTEGER, 32, - PropModeReplace, 1, &tempi, FALSE) == Success) { - xf86Msg(X_CONFIG, "%s: (accel) acceleration profile %i\n", devname, - tempi); - } else { - xf86Msg(X_CONFIG, "%s: (accel) acceleration profile %i is unknown\n", - devname, tempi); - } - - /* set scaling */ - tempf = xf86SetRealOption(list, "ExpectedRate", 0); - prop = XIGetKnownProperty(ACCEL_PROP_VELOCITY_SCALING); - if (tempf > 0) { - tempf = 1000.0 / tempf; - XIChangeDeviceProperty(pDev, prop, float_prop, 32, - PropModeReplace, 1, &tempf, FALSE); - } else { - tempf = xf86SetRealOption(list, "VelocityScale", s->corr_mul); - XIChangeDeviceProperty(pDev, prop, float_prop, 32, - PropModeReplace, 1, &tempf, FALSE); - } - - tempi = xf86SetIntOption(list, "VelocityTrackerCount", -1); - if (tempi > 1) - InitTrackers(s, tempi); - - s->initial_range = xf86SetIntOption(list, "VelocityInitialRange", - s->initial_range); - - s->max_diff = xf86SetRealOption(list, "VelocityAbsDiff", s->max_diff); - - tempf = xf86SetRealOption(list, "VelocityRelDiff", -1); - if (tempf >= 0) { - xf86Msg(X_CONFIG, "%s: (accel) max rel. velocity difference: %.1f%%\n", - devname, tempf*100.0); - s->max_rel_diff = tempf; - } - - /* Configure softening. If const deceleration is used, this is expected - * to provide better subpixel information so we enable - * softening by default only if ConstantDeceleration is not used - */ - s->use_softening = xf86SetBoolOption(list, "Softening", - s->const_acceleration == 1.0); - - s->average_accel = xf86SetBoolOption(list, "AccelerationProfileAveraging", - s->average_accel); - - s->reset_time = xf86SetIntOption(list, "VelocityReset", s->reset_time); -} - -static void -ApplyAccelerationSettings(DeviceIntPtr dev){ - int scheme, i; - DeviceVelocityPtr pVel; - InputInfoPtr pInfo = (InputInfoPtr)dev->public.devicePrivate; - char* schemeStr; - - if (dev->valuator && dev->ptrfeed) { - schemeStr = xf86SetStrOption(pInfo->options, "AccelerationScheme", ""); - - scheme = dev->valuator->accelScheme.number; - - if (!xf86NameCmp(schemeStr, "predictable")) - scheme = PtrAccelPredictable; - - if (!xf86NameCmp(schemeStr, "lightweight")) - scheme = PtrAccelLightweight; - - if (!xf86NameCmp(schemeStr, "none")) - scheme = PtrAccelNoOp; - - /* reinit scheme if needed */ - if (dev->valuator->accelScheme.number != scheme) { - if (dev->valuator->accelScheme.AccelCleanupProc) { - dev->valuator->accelScheme.AccelCleanupProc(dev); - } - - if (InitPointerAccelerationScheme(dev, scheme)) { - xf86Msg(X_CONFIG, "%s: (accel) selected scheme %s/%i\n", - pInfo->name, schemeStr, scheme); - } else { - xf86Msg(X_CONFIG, "%s: (accel) could not init scheme %s\n", - pInfo->name, schemeStr); - scheme = dev->valuator->accelScheme.number; - } - } else { - xf86Msg(X_CONFIG, "%s: (accel) keeping acceleration scheme %i\n", - pInfo->name, scheme); - } - - free(schemeStr); - - /* process special configuration */ - switch (scheme) { - case PtrAccelPredictable: - pVel = GetDevicePredictableAccelData(dev); - ProcessVelocityConfiguration (dev, pInfo->name, pInfo->options, - pVel); - break; - } - - i = xf86SetIntOption(pInfo->options, "AccelerationNumerator", - dev->ptrfeed->ctrl.num); - if (i >= 0) - dev->ptrfeed->ctrl.num = i; - - i = xf86SetIntOption(pInfo->options, "AccelerationDenominator", - dev->ptrfeed->ctrl.den); - if (i > 0) - dev->ptrfeed->ctrl.den = i; - - i = xf86SetIntOption(pInfo->options, "AccelerationThreshold", - dev->ptrfeed->ctrl.threshold); - if (i >= 0) - dev->ptrfeed->ctrl.threshold = i; - - xf86Msg(X_CONFIG, "%s: (accel) acceleration factor: %.3f\n", - pInfo->name, ((float)dev->ptrfeed->ctrl.num)/ - ((float)dev->ptrfeed->ctrl.den)); - xf86Msg(X_CONFIG, "%s: (accel) acceleration threshold: %i\n", - pInfo->name, dev->ptrfeed->ctrl.threshold); - } -} - -/*********************************************************************** - * - * xf86ProcessCommonOptions -- - * - * Process global options. - * - *********************************************************************** - */ -void -xf86ProcessCommonOptions(InputInfoPtr pInfo, - pointer list) -{ - if (xf86SetBoolOption(list, "Floating", 0) || - !xf86SetBoolOption(list, "AlwaysCore", 1) || - !xf86SetBoolOption(list, "SendCoreEvents", 1) || - !xf86SetBoolOption(list, "CorePointer", 1) || - !xf86SetBoolOption(list, "CoreKeyboard", 1)) { - xf86Msg(X_CONFIG, "%s: doesn't report core events\n", pInfo->name); - } else { - pInfo->flags |= XI86_ALWAYS_CORE; - xf86Msg(X_CONFIG, "%s: always reports core events\n", pInfo->name); - } -} - -/*********************************************************************** - * - * xf86ActivateDevice -- - * - * Initialize an input device. - * - * Returns TRUE on success, or FALSE otherwise. - *********************************************************************** - */ -static DeviceIntPtr -xf86ActivateDevice(InputInfoPtr pInfo) -{ - DeviceIntPtr dev; - Atom atom; - - dev = AddInputDevice(serverClient, pInfo->device_control, TRUE); - - if (dev == NULL) - { - xf86Msg(X_ERROR, "Too many input devices. Ignoring %s\n", - pInfo->name); - pInfo->dev = NULL; - return NULL; - } - - atom = MakeAtom(pInfo->type_name, strlen(pInfo->type_name), TRUE); - AssignTypeAndName(dev, atom, pInfo->name); - dev->public.devicePrivate = pInfo; - pInfo->dev = dev; - - dev->coreEvents = pInfo->flags & XI86_ALWAYS_CORE; - dev->type = SLAVE; - dev->spriteInfo->spriteOwner = FALSE; - - dev->config_info = xf86SetStrOption(pInfo->options, "config_info", NULL); - - if (serverGeneration == 1) - xf86Msg(X_INFO, "XINPUT: Adding extended input device \"%s\" (type: %s)\n", - pInfo->name, pInfo->type_name); - - return dev; -} - -/**************************************************************************** - * - * Caller: ProcXSetDeviceMode - * - * Change the mode of an extension device. - * This function is used to change the mode of a device from reporting - * relative motion to reporting absolute positional information, and - * vice versa. - * The default implementation below is that no such devices are supported. - * - *********************************************************************** - */ - -int -SetDeviceMode (ClientPtr client, DeviceIntPtr dev, int mode) -{ - InputInfoPtr pInfo = (InputInfoPtr)dev->public.devicePrivate; - - if (pInfo->switch_mode) { - return (*pInfo->switch_mode)(client, dev, mode); - } - else - return BadMatch; -} - - -/*********************************************************************** - * - * Caller: ProcXSetDeviceValuators - * - * Set the value of valuators on an extension input device. - * This function is used to set the initial value of valuators on - * those input devices that are capable of reporting either relative - * motion or an absolute position, and allow an initial position to be set. - * The default implementation below is that no such devices are supported. - * - *********************************************************************** - */ - -int -SetDeviceValuators (ClientPtr client, DeviceIntPtr dev, int *valuators, - int first_valuator, int num_valuators) -{ - InputInfoPtr pInfo = (InputInfoPtr) dev->public.devicePrivate; - - if (pInfo->set_device_valuators) - return (*pInfo->set_device_valuators)(pInfo, valuators, first_valuator, - num_valuators); - - return BadMatch; -} - - -/*********************************************************************** - * - * Caller: ProcXChangeDeviceControl - * - * Change the specified device controls on an extension input device. - * - *********************************************************************** - */ - -int -ChangeDeviceControl (ClientPtr client, DeviceIntPtr dev, xDeviceCtl *control) -{ - InputInfoPtr pInfo = (InputInfoPtr)dev->public.devicePrivate; - - if (!pInfo->control_proc) { - switch (control->control) { - case DEVICE_CORE: - return BadMatch; - case DEVICE_RESOLUTION: - case DEVICE_ABS_CALIB: - case DEVICE_ABS_AREA: - case DEVICE_ENABLE: - return Success; - default: - return BadMatch; - } - } - else { - return (*pInfo->control_proc)(pInfo, control); - } -} - -/* - * Get the operating system name from uname and store it statically to avoid - * repeating the system call each time MatchOS is checked. - */ -static const char * -HostOS(void) -{ -#ifdef HAVE_SYS_UTSNAME_H - struct utsname name; - static char host_os[sizeof(name.sysname)] = ""; - - if (*host_os == '\0') { - if (uname(&name) >= 0) - strcpy(host_os, name.sysname); - else { - strncpy(host_os, "unknown", sizeof(host_os)); - host_os[sizeof(host_os)-1] = '\0'; - } - } - return host_os; -#else - return ""; -#endif -} - -static int -match_substring(const char *attr, const char *pattern) -{ - return (strstr(attr, pattern)) ? 0 : -1; -} - -#ifdef HAVE_FNMATCH_H -static int -match_pattern(const char *attr, const char *pattern) -{ - return fnmatch(pattern, attr, 0); -} -#else -#define match_pattern match_substring -#endif - -#ifdef HAVE_FNMATCH_H -static int -match_path_pattern(const char *attr, const char *pattern) -{ - return fnmatch(pattern, attr, FNM_PATHNAME); -} -#else -#define match_path_pattern match_substring -#endif - -/* - * Match an attribute against a list of NULL terminated arrays of patterns. - * If a pattern in each list entry is matched, return TRUE. - */ -static Bool -MatchAttrToken(const char *attr, struct list *patterns, - int (*compare)(const char *attr, const char *pattern)) -{ - const xf86MatchGroup *group; - - /* If there are no patterns, accept the match */ - if (list_is_empty(patterns)) - return TRUE; - - /* If there are patterns but no attribute, reject the match */ - if (!attr) - return FALSE; - - /* - * Otherwise, iterate the list of patterns ensuring each entry has a - * match. Each list entry is a separate Match line of the same type. - */ - list_for_each_entry(group, patterns, entry) { - char * const *cur; - Bool match = FALSE; - - for (cur = group->values; *cur; cur++) - if ((*compare)(attr, *cur) == 0) { - match = TRUE; - break; - } - if (!match) - return FALSE; - } - - /* All the entries in the list matched the attribute */ - return TRUE; -} - -/* - * Classes without any Match statements match all devices. Otherwise, all - * statements must match. - */ -static Bool -InputClassMatches(const XF86ConfInputClassPtr iclass, const InputInfoPtr idev, - const InputAttributes *attrs) -{ - /* MatchProduct substring */ - if (!MatchAttrToken(attrs->product, &iclass->match_product, match_substring)) - return FALSE; - - /* MatchVendor substring */ - if (!MatchAttrToken(attrs->vendor, &iclass->match_vendor, match_substring)) - return FALSE; - - /* MatchDevicePath pattern */ - if (!MatchAttrToken(attrs->device, &iclass->match_device, match_path_pattern)) - return FALSE; - - /* MatchOS case-insensitive string */ - if (!MatchAttrToken(HostOS(), &iclass->match_os, strcasecmp)) - return FALSE; - - /* MatchPnPID pattern */ - if (!MatchAttrToken(attrs->pnp_id, &iclass->match_pnpid, match_pattern)) - return FALSE; - - /* MatchUSBID pattern */ - if (!MatchAttrToken(attrs->usb_id, &iclass->match_usbid, match_pattern)) - return FALSE; - - /* MatchDriver string */ - if (!MatchAttrToken(idev->driver, &iclass->match_driver, strcmp)) - return FALSE; - - /* - * MatchTag string - * See if any of the device's tags match any of the MatchTag tokens. - */ - if (!list_is_empty(&iclass->match_tag)) { - char * const *tag; - Bool match; - - if (!attrs->tags) - return FALSE; - for (tag = attrs->tags, match = FALSE; *tag; tag++) { - if (MatchAttrToken(*tag, &iclass->match_tag, strcmp)) { - match = TRUE; - break; - } - } - if (!match) - return FALSE; - } - - /* MatchIs* booleans */ - if (iclass->is_keyboard.set && - iclass->is_keyboard.val != !!(attrs->flags & ATTR_KEYBOARD)) - return FALSE; - if (iclass->is_pointer.set && - iclass->is_pointer.val != !!(attrs->flags & ATTR_POINTER)) - return FALSE; - if (iclass->is_joystick.set && - iclass->is_joystick.val != !!(attrs->flags & ATTR_JOYSTICK)) - return FALSE; - if (iclass->is_tablet.set && - iclass->is_tablet.val != !!(attrs->flags & ATTR_TABLET)) - return FALSE; - if (iclass->is_touchpad.set && - iclass->is_touchpad.val != !!(attrs->flags & ATTR_TOUCHPAD)) - return FALSE; - if (iclass->is_touchscreen.set && - iclass->is_touchscreen.val != !!(attrs->flags & ATTR_TOUCHSCREEN)) - return FALSE; - - return TRUE; -} - -/* - * Merge in any InputClass configurations. Options in each InputClass - * section have more priority than the original device configuration as - * well as any previous InputClass sections. - */ -static int -MergeInputClasses(const InputInfoPtr idev, const InputAttributes *attrs) -{ - XF86ConfInputClassPtr cl; - XF86OptionPtr classopts; - - for (cl = xf86configptr->conf_inputclass_lst; cl; cl = cl->list.next) { - if (!InputClassMatches(cl, idev, attrs)) - continue; - - /* Collect class options and driver settings */ - classopts = xf86optionListDup(cl->option_lst); - if (cl->driver) { - free(idev->driver); - idev->driver = xstrdup(cl->driver); - if (!idev->driver) { - xf86Msg(X_ERROR, "Failed to allocate memory while merging " - "InputClass configuration"); - return BadAlloc; - } - classopts = xf86ReplaceStrOption(classopts, "driver", - idev->driver); - } - - /* Apply options to device with InputClass settings preferred. */ - xf86Msg(X_CONFIG, "%s: Applying InputClass \"%s\"\n", - idev->name, cl->identifier); - idev->options = xf86optionListMerge(idev->options, classopts); - } - - return Success; -} - -/* - * Iterate the list of classes and look for Option "Ignore". Return the - * value of the last matching class and holler when returning TRUE. - */ -static Bool -IgnoreInputClass(const InputInfoPtr idev, const InputAttributes *attrs) -{ - XF86ConfInputClassPtr cl; - Bool ignore = FALSE; - const char *ignore_class; - - for (cl = xf86configptr->conf_inputclass_lst; cl; cl = cl->list.next) { - if (!InputClassMatches(cl, idev, attrs)) - continue; - if (xf86findOption(cl->option_lst, "Ignore")) { - ignore = xf86CheckBoolOption(cl->option_lst, "Ignore", FALSE); - ignore_class = cl->identifier; - } - } - - if (ignore) - xf86Msg(X_CONFIG, "%s: Ignoring device from InputClass \"%s\"\n", - idev->name, ignore_class); - return ignore; -} - -InputInfoPtr -xf86AllocateInput(void) -{ - InputInfoPtr pInfo; - - pInfo = calloc(sizeof(*pInfo), 1); - if (!pInfo) - return NULL; - - pInfo->fd = -1; - pInfo->type_name = "UNKNOWN"; - - return pInfo; -} - -/* Append InputInfoRec to the tail of xf86InputDevs. */ -static void -xf86AddInput(InputDriverPtr drv, InputInfoPtr pInfo) -{ - InputInfoPtr *prev = NULL; - - pInfo->drv = drv; - pInfo->module = DuplicateModule(drv->module, NULL); - - for (prev = &xf86InputDevs; *prev; prev = &(*prev)->next) - ; - - *prev = pInfo; - pInfo->next = NULL; - - xf86CollectInputOptions(pInfo, (const char**)drv->default_options); - xf86ProcessCommonOptions(pInfo, pInfo->options); -} - -/* - * Remove an entry from xf86InputDevs and free all the device's information. - */ -void -xf86DeleteInput(InputInfoPtr pInp, int flags) -{ - /* First check if the inputdev is valid. */ - if (pInp == NULL) - return; - - if (pInp->module) - UnloadModule(pInp->module); - - /* This should *really* be handled in drv->UnInit(dev) call instead, but - * if the driver forgets about it make sure we free it or at least crash - * with flying colors */ - free(pInp->private); - - FreeInputAttributes(pInp->attrs); - - /* Remove the entry from the list. */ - if (pInp == xf86InputDevs) - xf86InputDevs = pInp->next; - else { - InputInfoPtr p = xf86InputDevs; - while (p && p->next != pInp) - p = p->next; - if (p) - p->next = pInp->next; - /* Else the entry wasn't in the xf86InputDevs list (ignore this). */ - } - - free(pInp->driver); - free(pInp->name); - xf86optionListFree(pInp->options); - free(pInp); -} - -/* - * Apply backend-specific initialization. Invoked after ActiveteDevice(), - * i.e. after the driver successfully completed DEVICE_INIT and the device - * is advertised. - * @param dev the device - * @return Success or an error code - */ -static int -xf86InputDevicePostInit(DeviceIntPtr dev) { - ApplyAccelerationSettings(dev); - return Success; -} - -/** - * Create a new input device, activate and enable it. - * - * Possible return codes: - * BadName .. a bad driver name was supplied. - * BadImplementation ... The driver does not have a PreInit function. This - * is a driver bug. - * BadMatch .. device initialization failed. - * BadAlloc .. too many input devices - * - * @param idev The device, already set up with identifier, driver, and the - * options. - * @param pdev Pointer to the new device, if Success was reported. - * @param enable Enable the device after activating it. - * - * @return Success or an error code - */ -_X_INTERNAL int -xf86NewInputDevice(InputInfoPtr pInfo, DeviceIntPtr *pdev, BOOL enable) -{ - InputDriverPtr drv = NULL; - DeviceIntPtr dev = NULL; - int rval; - - /* Memory leak for every attached device if we don't - * test if the module is already loaded first */ - drv = xf86LookupInputDriver(pInfo->driver); - if (!drv) - if (xf86LoadOneModule(pInfo->driver, NULL)) - drv = xf86LookupInputDriver(pInfo->driver); - if (!drv) { - xf86Msg(X_ERROR, "No input driver matching `%s'\n", pInfo->driver); - rval = BadName; - goto unwind; - } - - if (!drv->PreInit) { - xf86Msg(X_ERROR, - "Input driver `%s' has no PreInit function (ignoring)\n", - drv->driverName); - rval = BadImplementation; - goto unwind; - } - - xf86AddInput(drv, pInfo); - - rval = drv->PreInit(drv, pInfo, 0); - - if (rval != Success) { - xf86Msg(X_ERROR, "PreInit returned %d for \"%s\"\n", rval, pInfo->name); - goto unwind; - } - - if (!(dev = xf86ActivateDevice(pInfo))) - { - rval = BadAlloc; - goto unwind; - } - - rval = ActivateDevice(dev, TRUE); - if (rval != Success) - { - xf86Msg(X_ERROR, "Couldn't init device \"%s\"\n", pInfo->name); - RemoveDevice(dev, TRUE); - goto unwind; - } - - rval = xf86InputDevicePostInit(dev); - if (rval != Success) - { - xf86Msg(X_ERROR, "Couldn't post-init device \"%s\"\n", pInfo->name); - RemoveDevice(dev, TRUE); - goto unwind; - } - - /* Enable it if it's properly initialised and we're currently in the VT */ - if (enable && dev->inited && dev->startup && xf86Screens[0]->vtSema) - { - EnableDevice(dev, TRUE); - if (!dev->enabled) - { - xf86Msg(X_ERROR, "Couldn't init device \"%s\"\n", pInfo->name); - rval = BadMatch; - goto unwind; - } - /* send enter/leave event, update sprite window */ - CheckMotion(NULL, dev); - } - - *pdev = dev; - return Success; - -unwind: - if(pInfo) { - if(drv && drv->UnInit) - drv->UnInit(drv, pInfo, 0); - else - xf86DeleteInput(pInfo, 0); - } - return rval; -} - -int -NewInputDeviceRequest (InputOption *options, InputAttributes *attrs, - DeviceIntPtr *pdev) -{ - InputInfoPtr pInfo = NULL; - InputOption *option = NULL; - int rval = Success; - int is_auto = 0; - - pInfo = xf86AllocateInput(); - if (!pInfo) - return BadAlloc; - - for (option = options; option; option = option->next) { - if (strcasecmp(option->key, "driver") == 0) { - if (pInfo->driver) { - rval = BadRequest; - goto unwind; - } - pInfo->driver = xstrdup(option->value); - if (!pInfo->driver) { - rval = BadAlloc; - goto unwind; - } - } - - if (strcasecmp(option->key, "name") == 0 || - strcasecmp(option->key, "identifier") == 0) { - if (pInfo->name) { - rval = BadRequest; - goto unwind; - } - pInfo->name = xstrdup(option->value); - if (!pInfo->name) { - rval = BadAlloc; - goto unwind; - } - } - - if (strcmp(option->key, "_source") == 0 && - (strcmp(option->value, "server/hal") == 0 || - strcmp(option->value, "server/udev") == 0)) { - is_auto = 1; - if (!xf86Info.autoAddDevices) { - rval = BadMatch; - goto unwind; - } - } - } - - for (option = options; option; option = option->next) { - /* Steal option key/value strings from the provided list. - * We need those strings, the InputOption list doesn't. */ - pInfo->options = xf86addNewOption(pInfo->options, - option->key, option->value); - option->key = NULL; - option->value = NULL; - } - - /* Apply InputClass settings */ - if (attrs) { - if (IgnoreInputClass(pInfo, attrs)) { - rval = BadIDChoice; - goto unwind; - } - - rval = MergeInputClasses(pInfo, attrs); - if (rval != Success) - goto unwind; - - pInfo->attrs = DuplicateInputAttributes(attrs); - } - - if (!pInfo->driver || !pInfo->name) { - xf86Msg(X_INFO, "No input driver/identifier specified (ignoring)\n"); - rval = BadRequest; - goto unwind; - } - - if (!pInfo->name) { - xf86Msg(X_ERROR, "No device identifier specified (ignoring)\n"); - rval = BadMatch; - goto unwind; - } - - rval = xf86NewInputDevice(pInfo, pdev, - (!is_auto || (is_auto && xf86Info.autoEnableDevices))); - - return rval; - -unwind: - if (is_auto && !xf86Info.autoAddDevices) - xf86Msg(X_INFO, "AutoAddDevices is off - not adding device.\n"); - xf86DeleteInput(pInfo, 0); - return rval; -} - -void -DeleteInputDeviceRequest(DeviceIntPtr pDev) -{ - InputInfoPtr pInfo = (InputInfoPtr) pDev->public.devicePrivate; - InputDriverPtr drv = NULL; - Bool isMaster = IsMaster(pDev); - - if (pInfo) /* need to get these before RemoveDevice */ - drv = pInfo->drv; - - OsBlockSignals(); - RemoveDevice(pDev, TRUE); - - if (!isMaster && pInfo != NULL) - { - if(drv->UnInit) - drv->UnInit(drv, pInfo, 0); - else - xf86DeleteInput(pInfo, 0); - } - OsReleaseSignals(); -} - -/* - * convenient functions to post events - */ - -void -xf86PostMotionEvent(DeviceIntPtr device, - int is_absolute, - int first_valuator, - int num_valuators, - ...) -{ - va_list var; - int i = 0; - ValuatorMask mask; - - XI_VERIFY_VALUATORS(num_valuators); - - valuator_mask_zero(&mask); - va_start(var, num_valuators); - for (i = 0; i < num_valuators; i++) - valuator_mask_set(&mask, first_valuator + i, va_arg(var, int)); - va_end(var); - - xf86PostMotionEventM(device, is_absolute, &mask); -} - -void -xf86PostMotionEventP(DeviceIntPtr device, - int is_absolute, - int first_valuator, - int num_valuators, - const int *valuators) -{ - ValuatorMask mask; - - XI_VERIFY_VALUATORS(num_valuators); - - valuator_mask_set_range(&mask, first_valuator, num_valuators, valuators); - xf86PostMotionEventM(device, is_absolute, &mask); -} - -void -xf86PostMotionEventM(DeviceIntPtr device, - int is_absolute, - const ValuatorMask *mask) -{ - int i = 0, nevents = 0; - DeviceEvent *event; - int flags = 0; - -#if XFreeXDGA - int index; - int dx = 0, dy = 0; -#endif - - if (is_absolute) - flags = POINTER_ABSOLUTE; - else - flags = POINTER_RELATIVE | POINTER_ACCELERATE; - -#if XFreeXDGA - /* The evdev driver may not always send all axes across. */ - if (valuator_mask_isset(mask, 0) || - valuator_mask_isset(mask, 1)) - if (miPointerGetScreen(device)) { - index = miPointerGetScreen(device)->myNum; - if (valuator_mask_isset(mask, 0)) - { - dx = valuator_mask_get(mask, 0); - if (is_absolute) - dx -= device->last.valuators[0]; - } - - if (valuator_mask_isset(mask, 1)) - { - dy = valuator_mask_get(mask, 1); - if (is_absolute) - dy -= device->last.valuators[1]; - } - - if (DGAStealMotionEvent(device, index, dx, dy)) - return; - } -#endif - - nevents = GetPointerEvents(xf86Events, device, MotionNotify, 0, flags, mask); - - for (i = 0; i < nevents; i++) { - event = (DeviceEvent*)((xf86Events + i)->event); - mieqEnqueue(device, (InternalEvent*)((xf86Events + i)->event)); - } -} - -void -xf86PostProximityEvent(DeviceIntPtr device, - int is_in, - int first_valuator, - int num_valuators, - ...) -{ - va_list var; - int i; - ValuatorMask mask; - - XI_VERIFY_VALUATORS(num_valuators); - - valuator_mask_zero(&mask); - va_start(var, num_valuators); - for (i = 0; i < num_valuators; i++) - valuator_mask_set(&mask, first_valuator + i, va_arg(var, int)); - va_end(var); - - xf86PostProximityEventM(device, is_in, &mask); -} - -void -xf86PostProximityEventP(DeviceIntPtr device, - int is_in, - int first_valuator, - int num_valuators, - const int *valuators) -{ - ValuatorMask mask; - - XI_VERIFY_VALUATORS(num_valuators); - - valuator_mask_set_range(&mask, first_valuator, num_valuators, valuators); - xf86PostProximityEventM(device, is_in, &mask); -} - -void -xf86PostProximityEventM(DeviceIntPtr device, - int is_in, - const ValuatorMask *mask) -{ - int i, nevents; - - nevents = GetProximityEvents(xf86Events, device, - is_in ? ProximityIn : ProximityOut, mask); - for (i = 0; i < nevents; i++) - mieqEnqueue(device, (InternalEvent*)((xf86Events + i)->event)); - -} - -void -xf86PostButtonEvent(DeviceIntPtr device, - int is_absolute, - int button, - int is_down, - int first_valuator, - int num_valuators, - ...) -{ - va_list var; - ValuatorMask mask; - int i = 0; - - XI_VERIFY_VALUATORS(num_valuators); - - valuator_mask_zero(&mask); - - va_start(var, num_valuators); - for (i = 0; i < num_valuators; i++) - valuator_mask_set(&mask, first_valuator + i, va_arg(var, int)); - va_end(var); - - xf86PostButtonEventM(device, is_absolute, button, is_down, &mask); -} - -void -xf86PostButtonEventP(DeviceIntPtr device, - int is_absolute, - int button, - int is_down, - int first_valuator, - int num_valuators, - const int *valuators) -{ - ValuatorMask mask; - - XI_VERIFY_VALUATORS(num_valuators); - - valuator_mask_set_range(&mask, first_valuator, num_valuators, valuators); - xf86PostButtonEventM(device, is_absolute, button, is_down, &mask); -} - -void -xf86PostButtonEventM(DeviceIntPtr device, - int is_absolute, - int button, - int is_down, - const ValuatorMask *mask) -{ - int i = 0, nevents = 0; - int flags = 0; - -#if XFreeXDGA - int index; -#endif - - if (is_absolute) - flags = POINTER_ABSOLUTE; - else - flags = POINTER_RELATIVE | POINTER_ACCELERATE; - -#if XFreeXDGA - if (miPointerGetScreen(device)) { - index = miPointerGetScreen(device)->myNum; - if (DGAStealButtonEvent(device, index, button, is_down)) - return; - } -#endif - - nevents = GetPointerEvents(xf86Events, device, - is_down ? ButtonPress : ButtonRelease, button, - flags, mask); - - for (i = 0; i < nevents; i++) - mieqEnqueue(device, (InternalEvent*)((xf86Events + i)->event)); - -} - -void -xf86PostKeyEvent(DeviceIntPtr device, - unsigned int key_code, - int is_down, - int is_absolute, - int first_valuator, - int num_valuators, - ...) -{ - va_list var; - int i = 0; - ValuatorMask mask; - - XI_VERIFY_VALUATORS(num_valuators); - - valuator_mask_zero(&mask); - - va_start(var, num_valuators); - for (i = 0; i < num_valuators; i++) - valuator_mask_set(&mask, first_valuator + i, va_arg(var, int)); - va_end(var); - - xf86PostKeyEventM(device, key_code, is_down, is_absolute, &mask); -} - -void -xf86PostKeyEventP(DeviceIntPtr device, - unsigned int key_code, - int is_down, - int is_absolute, - int first_valuator, - int num_valuators, - const int *valuators) -{ - ValuatorMask mask; - - XI_VERIFY_VALUATORS(num_valuators); - - valuator_mask_set_range(&mask, first_valuator, num_valuators, valuators); - xf86PostKeyEventM(device, key_code, is_down, is_absolute, &mask); -} - -void -xf86PostKeyEventM(DeviceIntPtr device, - unsigned int key_code, - int is_down, - int is_absolute, - const ValuatorMask *mask) -{ - int i = 0, nevents = 0; - - if (is_absolute) { - nevents = GetKeyboardValuatorEvents(xf86Events, device, - is_down ? KeyPress : KeyRelease, - key_code, mask); - } - else { - nevents = GetKeyboardEvents(xf86Events, device, - is_down ? KeyPress : KeyRelease, - key_code); - } - - for (i = 0; i < nevents; i++) - mieqEnqueue(device, (InternalEvent*)((xf86Events + i)->event)); -} - -void -xf86PostKeyboardEvent(DeviceIntPtr device, - unsigned int key_code, - int is_down) -{ - ValuatorMask mask; - - valuator_mask_zero(&mask); - xf86PostKeyEventM(device, key_code, is_down, 0, &mask); -} - -InputInfoPtr -xf86FirstLocalDevice(void) -{ - return xf86InputDevs; -} - -/* - * Cx - raw data from touch screen - * to_max - scaled highest dimension - * (remember, this is of rows - 1 because of 0 origin) - * to_min - scaled lowest dimension - * from_max - highest raw value from touch screen calibration - * from_min - lowest raw value from touch screen calibration - * - * This function is the same for X or Y coordinates. - * You may have to reverse the high and low values to compensate for - * different orgins on the touch screen vs X. - * - * e.g. to scale from device coordinates into screen coordinates, call - * xf86ScaleAxis(x, 0, screen_width, dev_min, dev_max); - */ - -int -xf86ScaleAxis(int Cx, - int to_max, - int to_min, - int from_max, - int from_min ) -{ - int X; - int64_t to_width = to_max - to_min; - int64_t from_width = from_max - from_min; - - if (from_width) { - X = (int)(((to_width * (Cx - from_min)) / from_width) + to_min); - } - else { - X = 0; - ErrorF ("Divide by Zero in xf86ScaleAxis\n"); - } - - if (X > to_max) - X = to_max; - if (X < to_min) - X = to_min; - - return X; -} - -/* - * This function checks the given screen against the current screen and - * makes changes if appropriate. It should be called from an XInput driver's - * ReadInput function before any events are posted, if the device is screen - * specific like a touch screen. - */ -void -xf86XInputSetScreen(InputInfoPtr pInfo, - int screen_number, - int x, - int y) -{ - if (miPointerGetScreen(pInfo->dev) != - screenInfo.screens[screen_number]) { - miPointerSetScreen(pInfo->dev, screen_number, x, y); - } -} - - -void -xf86InitValuatorAxisStruct(DeviceIntPtr dev, int axnum, Atom label, int minval, int maxval, - int resolution, int min_res, int max_res, int mode) -{ - if (!dev || !dev->valuator) - return; - - InitValuatorAxisStruct(dev, axnum, label, minval, maxval, resolution, min_res, - max_res, mode); -} - -/* - * Set the valuator values to be in synch with dix/event.c - * DefineInitialRootWindow(). - */ -void -xf86InitValuatorDefaults(DeviceIntPtr dev, int axnum) -{ - if (axnum == 0) { - dev->valuator->axisVal[0] = screenInfo.screens[0]->width / 2; - dev->last.valuators[0] = dev->valuator->axisVal[0]; - } - else if (axnum == 1) { - dev->valuator->axisVal[1] = screenInfo.screens[0]->height / 2; - dev->last.valuators[1] = dev->valuator->axisVal[1]; - } -} - - -/** - * Deactivate a device. Call this function from the driver if you receive a - * read error or something else that spoils your day. - * Device will be moved to the off_devices list, but it will still be there - * until you really clean up after it. - * Notifies the client about an inactive device. - * - * @param panic True if device is unrecoverable and needs to be removed. - */ -void -xf86DisableDevice(DeviceIntPtr dev, Bool panic) -{ - if(!panic) - { - DisableDevice(dev, TRUE); - } else - { - SendDevicePresenceEvent(dev->id, DeviceUnrecoverable); - DeleteInputDeviceRequest(dev); - } -} - -/** - * Reactivate a device. Call this function from the driver if you just found - * out that the read error wasn't quite that bad after all. - * Device will be re-activated, and an event sent to the client. - */ -void -xf86EnableDevice(DeviceIntPtr dev) -{ - EnableDevice(dev, TRUE); -} - -/* end of xf86Xinput.c */ +/* + * Copyright 1995-1999 by Frederic Lepied, France. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Frederic Lepied not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Frederic Lepied makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * FREDERIC LEPIED DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL FREDERIC LEPIED BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + * + */ +/* + * Copyright (c) 2000-2002 by The XFree86 Project, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the copyright holder(s) + * and author(s) shall not be used in advertising or otherwise to promote + * the sale, use or other dealings in this Software without prior written + * authorization from the copyright holder(s) and author(s). + */ + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include "xf86.h" +#include "xf86Priv.h" +#include "xf86Config.h" +#include "xf86Xinput.h" +#include "xf86Optrec.h" +#include "mipointer.h" +#include "extinit.h" +#include "loaderProcs.h" + +#include "exevents.h" /* AddInputDevice */ +#include "exglobals.h" +#include "eventstr.h" +#include "inpututils.h" + +#include /* InputClassMatches */ +#ifdef HAVE_FNMATCH_H +#include +#endif +#ifdef HAVE_SYS_UTSNAME_H +#include +#endif + +#include +#include /* for int64_t */ + +#include "mi.h" + +#include /* dix pointer acceleration */ +#include + +#ifdef XFreeXDGA +#include "dgaproc.h" +#endif + +#include "xkbsrv.h" + +/* Valuator verification macro */ +#define XI_VERIFY_VALUATORS(num_valuators) \ + if (num_valuators > MAX_VALUATORS) { \ + xf86Msg(X_ERROR, "%s: num_valuator %d is greater than" \ + " MAX_VALUATORS\n", __FUNCTION__, num_valuators); \ + return; \ + } + +EventListPtr xf86Events = NULL; + +static int +xf86InputDevicePostInit(DeviceIntPtr dev); + +/** + * Eval config and modify DeviceVelocityRec accordingly + */ +static void +ProcessVelocityConfiguration(DeviceIntPtr pDev, char* devname, pointer list, + DeviceVelocityPtr s) +{ + int tempi; + float tempf; + Atom float_prop = XIGetKnownProperty(XATOM_FLOAT); + Atom prop; + + if(!s) + return; + + /* common settings (available via device properties) */ + tempf = xf86SetRealOption(list, "ConstantDeceleration", 1.0); + if (tempf > 1.0) { + xf86Msg(X_CONFIG, "%s: (accel) constant deceleration by %.1f\n", + devname, tempf); + prop = XIGetKnownProperty(ACCEL_PROP_CONSTANT_DECELERATION); + XIChangeDeviceProperty(pDev, prop, float_prop, 32, + PropModeReplace, 1, &tempf, FALSE); + } + + tempf = xf86SetRealOption(list, "AdaptiveDeceleration", 1.0); + if (tempf > 1.0) { + xf86Msg(X_CONFIG, "%s: (accel) adaptive deceleration by %.1f\n", + devname, tempf); + prop = XIGetKnownProperty(ACCEL_PROP_ADAPTIVE_DECELERATION); + XIChangeDeviceProperty(pDev, prop, float_prop, 32, + PropModeReplace, 1, &tempf, FALSE); + } + + /* select profile by number */ + tempi = xf86SetIntOption(list, "AccelerationProfile", + s->statistics.profile_number); + + prop = XIGetKnownProperty(ACCEL_PROP_PROFILE_NUMBER); + if (XIChangeDeviceProperty(pDev, prop, XA_INTEGER, 32, + PropModeReplace, 1, &tempi, FALSE) == Success) { + xf86Msg(X_CONFIG, "%s: (accel) acceleration profile %i\n", devname, + tempi); + } else { + xf86Msg(X_CONFIG, "%s: (accel) acceleration profile %i is unknown\n", + devname, tempi); + } + + /* set scaling */ + tempf = xf86SetRealOption(list, "ExpectedRate", 0); + prop = XIGetKnownProperty(ACCEL_PROP_VELOCITY_SCALING); + if (tempf > 0) { + tempf = 1000.0 / tempf; + XIChangeDeviceProperty(pDev, prop, float_prop, 32, + PropModeReplace, 1, &tempf, FALSE); + } else { + tempf = xf86SetRealOption(list, "VelocityScale", s->corr_mul); + XIChangeDeviceProperty(pDev, prop, float_prop, 32, + PropModeReplace, 1, &tempf, FALSE); + } + + tempi = xf86SetIntOption(list, "VelocityTrackerCount", -1); + if (tempi > 1) + InitTrackers(s, tempi); + + s->initial_range = xf86SetIntOption(list, "VelocityInitialRange", + s->initial_range); + + s->max_diff = xf86SetRealOption(list, "VelocityAbsDiff", s->max_diff); + + tempf = xf86SetRealOption(list, "VelocityRelDiff", -1); + if (tempf >= 0) { + xf86Msg(X_CONFIG, "%s: (accel) max rel. velocity difference: %.1f%%\n", + devname, tempf*100.0); + s->max_rel_diff = tempf; + } + + /* Configure softening. If const deceleration is used, this is expected + * to provide better subpixel information so we enable + * softening by default only if ConstantDeceleration is not used + */ + s->use_softening = xf86SetBoolOption(list, "Softening", + s->const_acceleration == 1.0); + + s->average_accel = xf86SetBoolOption(list, "AccelerationProfileAveraging", + s->average_accel); + + s->reset_time = xf86SetIntOption(list, "VelocityReset", s->reset_time); +} + +static void +ApplyAccelerationSettings(DeviceIntPtr dev){ + int scheme, i; + DeviceVelocityPtr pVel; + InputInfoPtr pInfo = (InputInfoPtr)dev->public.devicePrivate; + char* schemeStr; + + if (dev->valuator && dev->ptrfeed) { + schemeStr = xf86SetStrOption(pInfo->options, "AccelerationScheme", ""); + + scheme = dev->valuator->accelScheme.number; + + if (!xf86NameCmp(schemeStr, "predictable")) + scheme = PtrAccelPredictable; + + if (!xf86NameCmp(schemeStr, "lightweight")) + scheme = PtrAccelLightweight; + + if (!xf86NameCmp(schemeStr, "none")) + scheme = PtrAccelNoOp; + + /* reinit scheme if needed */ + if (dev->valuator->accelScheme.number != scheme) { + if (dev->valuator->accelScheme.AccelCleanupProc) { + dev->valuator->accelScheme.AccelCleanupProc(dev); + } + + if (InitPointerAccelerationScheme(dev, scheme)) { + xf86Msg(X_CONFIG, "%s: (accel) selected scheme %s/%i\n", + pInfo->name, schemeStr, scheme); + } else { + xf86Msg(X_CONFIG, "%s: (accel) could not init scheme %s\n", + pInfo->name, schemeStr); + scheme = dev->valuator->accelScheme.number; + } + } else { + xf86Msg(X_CONFIG, "%s: (accel) keeping acceleration scheme %i\n", + pInfo->name, scheme); + } + + free(schemeStr); + + /* process special configuration */ + switch (scheme) { + case PtrAccelPredictable: + pVel = GetDevicePredictableAccelData(dev); + ProcessVelocityConfiguration (dev, pInfo->name, pInfo->options, + pVel); + break; + } + + i = xf86SetIntOption(pInfo->options, "AccelerationNumerator", + dev->ptrfeed->ctrl.num); + if (i >= 0) + dev->ptrfeed->ctrl.num = i; + + i = xf86SetIntOption(pInfo->options, "AccelerationDenominator", + dev->ptrfeed->ctrl.den); + if (i > 0) + dev->ptrfeed->ctrl.den = i; + + i = xf86SetIntOption(pInfo->options, "AccelerationThreshold", + dev->ptrfeed->ctrl.threshold); + if (i >= 0) + dev->ptrfeed->ctrl.threshold = i; + + xf86Msg(X_CONFIG, "%s: (accel) acceleration factor: %.3f\n", + pInfo->name, ((float)dev->ptrfeed->ctrl.num)/ + ((float)dev->ptrfeed->ctrl.den)); + xf86Msg(X_CONFIG, "%s: (accel) acceleration threshold: %i\n", + pInfo->name, dev->ptrfeed->ctrl.threshold); + } +} + +/*********************************************************************** + * + * xf86ProcessCommonOptions -- + * + * Process global options. + * + *********************************************************************** + */ +void +xf86ProcessCommonOptions(InputInfoPtr pInfo, + pointer list) +{ + if (xf86SetBoolOption(list, "Floating", 0) || + !xf86SetBoolOption(list, "AlwaysCore", 1) || + !xf86SetBoolOption(list, "SendCoreEvents", 1) || + !xf86SetBoolOption(list, "CorePointer", 1) || + !xf86SetBoolOption(list, "CoreKeyboard", 1)) { + xf86Msg(X_CONFIG, "%s: doesn't report core events\n", pInfo->name); + } else { + pInfo->flags |= XI86_ALWAYS_CORE; + xf86Msg(X_CONFIG, "%s: always reports core events\n", pInfo->name); + } +} + +/*********************************************************************** + * + * xf86ActivateDevice -- + * + * Initialize an input device. + * + * Returns TRUE on success, or FALSE otherwise. + *********************************************************************** + */ +static DeviceIntPtr +xf86ActivateDevice(InputInfoPtr pInfo) +{ + DeviceIntPtr dev; + Atom atom; + + dev = AddInputDevice(serverClient, pInfo->device_control, TRUE); + + if (dev == NULL) + { + xf86Msg(X_ERROR, "Too many input devices. Ignoring %s\n", + pInfo->name); + pInfo->dev = NULL; + return NULL; + } + + atom = MakeAtom(pInfo->type_name, strlen(pInfo->type_name), TRUE); + AssignTypeAndName(dev, atom, pInfo->name); + dev->public.devicePrivate = pInfo; + pInfo->dev = dev; + + dev->coreEvents = pInfo->flags & XI86_ALWAYS_CORE; + dev->type = SLAVE; + dev->spriteInfo->spriteOwner = FALSE; + + dev->config_info = xf86SetStrOption(pInfo->options, "config_info", NULL); + + if (serverGeneration == 1) + xf86Msg(X_INFO, "XINPUT: Adding extended input device \"%s\" (type: %s)\n", + pInfo->name, pInfo->type_name); + + return dev; +} + +/**************************************************************************** + * + * Caller: ProcXSetDeviceMode + * + * Change the mode of an extension device. + * This function is used to change the mode of a device from reporting + * relative motion to reporting absolute positional information, and + * vice versa. + * The default implementation below is that no such devices are supported. + * + *********************************************************************** + */ + +int +SetDeviceMode (ClientPtr client, DeviceIntPtr dev, int mode) +{ + InputInfoPtr pInfo = (InputInfoPtr)dev->public.devicePrivate; + + if (pInfo->switch_mode) { + return (*pInfo->switch_mode)(client, dev, mode); + } + else + return BadMatch; +} + + +/*********************************************************************** + * + * Caller: ProcXSetDeviceValuators + * + * Set the value of valuators on an extension input device. + * This function is used to set the initial value of valuators on + * those input devices that are capable of reporting either relative + * motion or an absolute position, and allow an initial position to be set. + * The default implementation below is that no such devices are supported. + * + *********************************************************************** + */ + +int +SetDeviceValuators (ClientPtr client, DeviceIntPtr dev, int *valuators, + int first_valuator, int num_valuators) +{ + InputInfoPtr pInfo = (InputInfoPtr) dev->public.devicePrivate; + + if (pInfo->set_device_valuators) + return (*pInfo->set_device_valuators)(pInfo, valuators, first_valuator, + num_valuators); + + return BadMatch; +} + + +/*********************************************************************** + * + * Caller: ProcXChangeDeviceControl + * + * Change the specified device controls on an extension input device. + * + *********************************************************************** + */ + +int +ChangeDeviceControl (ClientPtr client, DeviceIntPtr dev, xDeviceCtl *control) +{ + InputInfoPtr pInfo = (InputInfoPtr)dev->public.devicePrivate; + + if (!pInfo->control_proc) { + switch (control->control) { + case DEVICE_CORE: + return BadMatch; + case DEVICE_RESOLUTION: + case DEVICE_ABS_CALIB: + case DEVICE_ABS_AREA: + case DEVICE_ENABLE: + return Success; + default: + return BadMatch; + } + } + else { + return (*pInfo->control_proc)(pInfo, control); + } +} + +/* + * Get the operating system name from uname and store it statically to avoid + * repeating the system call each time MatchOS is checked. + */ +static const char * +HostOS(void) +{ +#ifdef HAVE_SYS_UTSNAME_H + struct utsname name; + static char host_os[sizeof(name.sysname)] = ""; + + if (*host_os == '\0') { + if (uname(&name) >= 0) + strcpy(host_os, name.sysname); + else { + strncpy(host_os, "unknown", sizeof(host_os)); + host_os[sizeof(host_os)-1] = '\0'; + } + } + return host_os; +#else + return ""; +#endif +} + +static int +match_substring(const char *attr, const char *pattern) +{ + return (strstr(attr, pattern)) ? 0 : -1; +} + +#ifdef HAVE_FNMATCH_H +static int +match_pattern(const char *attr, const char *pattern) +{ + return fnmatch(pattern, attr, 0); +} +#else +#define match_pattern match_substring +#endif + +#ifdef HAVE_FNMATCH_H +static int +match_path_pattern(const char *attr, const char *pattern) +{ + return fnmatch(pattern, attr, FNM_PATHNAME); +} +#else +#define match_path_pattern match_substring +#endif + +/* + * Match an attribute against a list of NULL terminated arrays of patterns. + * If a pattern in each list entry is matched, return TRUE. + */ +static Bool +MatchAttrToken(const char *attr, struct list *patterns, + int (*compare)(const char *attr, const char *pattern)) +{ + const xf86MatchGroup *group; + + /* If there are no patterns, accept the match */ + if (list_is_empty(patterns)) + return TRUE; + + /* If there are patterns but no attribute, reject the match */ + if (!attr) + return FALSE; + + /* + * Otherwise, iterate the list of patterns ensuring each entry has a + * match. Each list entry is a separate Match line of the same type. + */ + list_for_each_entry(group, patterns, entry) { + char * const *cur; + Bool match = FALSE; + + for (cur = group->values; *cur; cur++) + if ((*compare)(attr, *cur) == 0) { + match = TRUE; + break; + } + if (!match) + return FALSE; + } + + /* All the entries in the list matched the attribute */ + return TRUE; +} + +/* + * Classes without any Match statements match all devices. Otherwise, all + * statements must match. + */ +static Bool +InputClassMatches(const XF86ConfInputClassPtr iclass, const InputInfoPtr idev, + const InputAttributes *attrs) +{ + /* MatchProduct substring */ + if (!MatchAttrToken(attrs->product, &iclass->match_product, match_substring)) + return FALSE; + + /* MatchVendor substring */ + if (!MatchAttrToken(attrs->vendor, &iclass->match_vendor, match_substring)) + return FALSE; + + /* MatchDevicePath pattern */ + if (!MatchAttrToken(attrs->device, &iclass->match_device, match_path_pattern)) + return FALSE; + + /* MatchOS case-insensitive string */ + if (!MatchAttrToken(HostOS(), &iclass->match_os, strcasecmp)) + return FALSE; + + /* MatchPnPID pattern */ + if (!MatchAttrToken(attrs->pnp_id, &iclass->match_pnpid, match_pattern)) + return FALSE; + + /* MatchUSBID pattern */ + if (!MatchAttrToken(attrs->usb_id, &iclass->match_usbid, match_pattern)) + return FALSE; + + /* MatchDriver string */ + if (!MatchAttrToken(idev->driver, &iclass->match_driver, strcmp)) + return FALSE; + + /* + * MatchTag string + * See if any of the device's tags match any of the MatchTag tokens. + */ + if (!list_is_empty(&iclass->match_tag)) { + char * const *tag; + Bool match; + + if (!attrs->tags) + return FALSE; + for (tag = attrs->tags, match = FALSE; *tag; tag++) { + if (MatchAttrToken(*tag, &iclass->match_tag, strcmp)) { + match = TRUE; + break; + } + } + if (!match) + return FALSE; + } + + /* MatchIs* booleans */ + if (iclass->is_keyboard.set && + iclass->is_keyboard.val != !!(attrs->flags & ATTR_KEYBOARD)) + return FALSE; + if (iclass->is_pointer.set && + iclass->is_pointer.val != !!(attrs->flags & ATTR_POINTER)) + return FALSE; + if (iclass->is_joystick.set && + iclass->is_joystick.val != !!(attrs->flags & ATTR_JOYSTICK)) + return FALSE; + if (iclass->is_tablet.set && + iclass->is_tablet.val != !!(attrs->flags & ATTR_TABLET)) + return FALSE; + if (iclass->is_touchpad.set && + iclass->is_touchpad.val != !!(attrs->flags & ATTR_TOUCHPAD)) + return FALSE; + if (iclass->is_touchscreen.set && + iclass->is_touchscreen.val != !!(attrs->flags & ATTR_TOUCHSCREEN)) + return FALSE; + + return TRUE; +} + +/* + * Merge in any InputClass configurations. Options in each InputClass + * section have more priority than the original device configuration as + * well as any previous InputClass sections. + */ +static int +MergeInputClasses(const InputInfoPtr idev, const InputAttributes *attrs) +{ + XF86ConfInputClassPtr cl; + XF86OptionPtr classopts; + + for (cl = xf86configptr->conf_inputclass_lst; cl; cl = cl->list.next) { + if (!InputClassMatches(cl, idev, attrs)) + continue; + + /* Collect class options and driver settings */ + classopts = xf86optionListDup(cl->option_lst); + if (cl->driver) { + free(idev->driver); + idev->driver = xstrdup(cl->driver); + if (!idev->driver) { + xf86Msg(X_ERROR, "Failed to allocate memory while merging " + "InputClass configuration"); + return BadAlloc; + } + classopts = xf86ReplaceStrOption(classopts, "driver", + idev->driver); + } + + /* Apply options to device with InputClass settings preferred. */ + xf86Msg(X_CONFIG, "%s: Applying InputClass \"%s\"\n", + idev->name, cl->identifier); + idev->options = xf86optionListMerge(idev->options, classopts); + } + + return Success; +} + +/* + * Iterate the list of classes and look for Option "Ignore". Return the + * value of the last matching class and holler when returning TRUE. + */ +static Bool +IgnoreInputClass(const InputInfoPtr idev, const InputAttributes *attrs) +{ + XF86ConfInputClassPtr cl; + Bool ignore = FALSE; + const char *ignore_class; + + for (cl = xf86configptr->conf_inputclass_lst; cl; cl = cl->list.next) { + if (!InputClassMatches(cl, idev, attrs)) + continue; + if (xf86findOption(cl->option_lst, "Ignore")) { + ignore = xf86CheckBoolOption(cl->option_lst, "Ignore", FALSE); + ignore_class = cl->identifier; + } + } + + if (ignore) + xf86Msg(X_CONFIG, "%s: Ignoring device from InputClass \"%s\"\n", + idev->name, ignore_class); + return ignore; +} + +InputInfoPtr +xf86AllocateInput(void) +{ + InputInfoPtr pInfo; + + pInfo = calloc(sizeof(*pInfo), 1); + if (!pInfo) + return NULL; + + pInfo->fd = -1; + pInfo->type_name = "UNKNOWN"; + + return pInfo; +} + +/* Append InputInfoRec to the tail of xf86InputDevs. */ +static void +xf86AddInput(InputDriverPtr drv, InputInfoPtr pInfo) +{ + InputInfoPtr *prev = NULL; + + pInfo->drv = drv; + pInfo->module = DuplicateModule(drv->module, NULL); + + for (prev = &xf86InputDevs; *prev; prev = &(*prev)->next) + ; + + *prev = pInfo; + pInfo->next = NULL; + + xf86CollectInputOptions(pInfo, (const char**)drv->default_options); + xf86OptionListReport(pInfo->options); + xf86ProcessCommonOptions(pInfo, pInfo->options); +} + +/* + * Remove an entry from xf86InputDevs and free all the device's information. + */ +void +xf86DeleteInput(InputInfoPtr pInp, int flags) +{ + /* First check if the inputdev is valid. */ + if (pInp == NULL) + return; + + if (pInp->module) + UnloadModule(pInp->module); + + /* This should *really* be handled in drv->UnInit(dev) call instead, but + * if the driver forgets about it make sure we free it or at least crash + * with flying colors */ + free(pInp->private); + + FreeInputAttributes(pInp->attrs); + + /* Remove the entry from the list. */ + if (pInp == xf86InputDevs) + xf86InputDevs = pInp->next; + else { + InputInfoPtr p = xf86InputDevs; + while (p && p->next != pInp) + p = p->next; + if (p) + p->next = pInp->next; + /* Else the entry wasn't in the xf86InputDevs list (ignore this). */ + } + + free(pInp->driver); + free(pInp->name); + xf86optionListFree(pInp->options); + free(pInp); +} + +/* + * Apply backend-specific initialization. Invoked after ActiveteDevice(), + * i.e. after the driver successfully completed DEVICE_INIT and the device + * is advertised. + * @param dev the device + * @return Success or an error code + */ +static int +xf86InputDevicePostInit(DeviceIntPtr dev) { + ApplyAccelerationSettings(dev); + return Success; +} + +/** + * Create a new input device, activate and enable it. + * + * Possible return codes: + * BadName .. a bad driver name was supplied. + * BadImplementation ... The driver does not have a PreInit function. This + * is a driver bug. + * BadMatch .. device initialization failed. + * BadAlloc .. too many input devices + * + * @param idev The device, already set up with identifier, driver, and the + * options. + * @param pdev Pointer to the new device, if Success was reported. + * @param enable Enable the device after activating it. + * + * @return Success or an error code + */ +_X_INTERNAL int +xf86NewInputDevice(InputInfoPtr pInfo, DeviceIntPtr *pdev, BOOL enable) +{ + InputDriverPtr drv = NULL; + DeviceIntPtr dev = NULL; + int rval; + + /* Memory leak for every attached device if we don't + * test if the module is already loaded first */ + drv = xf86LookupInputDriver(pInfo->driver); + if (!drv) + if (xf86LoadOneModule(pInfo->driver, NULL)) + drv = xf86LookupInputDriver(pInfo->driver); + if (!drv) { + xf86Msg(X_ERROR, "No input driver matching `%s'\n", pInfo->driver); + rval = BadName; + goto unwind; + } + + if (!drv->PreInit) { + xf86Msg(X_ERROR, + "Input driver `%s' has no PreInit function (ignoring)\n", + drv->driverName); + rval = BadImplementation; + goto unwind; + } + + xf86AddInput(drv, pInfo); + + rval = drv->PreInit(drv, pInfo, 0); + + if (rval != Success) { + xf86Msg(X_ERROR, "PreInit returned %d for \"%s\"\n", rval, pInfo->name); + goto unwind; + } + + if (!(dev = xf86ActivateDevice(pInfo))) + { + rval = BadAlloc; + goto unwind; + } + + rval = ActivateDevice(dev, TRUE); + if (rval != Success) + { + xf86Msg(X_ERROR, "Couldn't init device \"%s\"\n", pInfo->name); + RemoveDevice(dev, TRUE); + goto unwind; + } + + rval = xf86InputDevicePostInit(dev); + if (rval != Success) + { + xf86Msg(X_ERROR, "Couldn't post-init device \"%s\"\n", pInfo->name); + RemoveDevice(dev, TRUE); + goto unwind; + } + + /* Enable it if it's properly initialised and we're currently in the VT */ + if (enable && dev->inited && dev->startup && xf86Screens[0]->vtSema) + { + EnableDevice(dev, TRUE); + if (!dev->enabled) + { + xf86Msg(X_ERROR, "Couldn't init device \"%s\"\n", pInfo->name); + rval = BadMatch; + goto unwind; + } + /* send enter/leave event, update sprite window */ + CheckMotion(NULL, dev); + } + + *pdev = dev; + return Success; + +unwind: + if(pInfo) { + if(drv && drv->UnInit) + drv->UnInit(drv, pInfo, 0); + else + xf86DeleteInput(pInfo, 0); + } + return rval; +} + +int +NewInputDeviceRequest (InputOption *options, InputAttributes *attrs, + DeviceIntPtr *pdev) +{ + InputInfoPtr pInfo = NULL; + InputOption *option = NULL; + int rval = Success; + int is_auto = 0; + + pInfo = xf86AllocateInput(); + if (!pInfo) + return BadAlloc; + + for (option = options; option; option = option->next) { + if (strcasecmp(option->key, "driver") == 0) { + if (pInfo->driver) { + rval = BadRequest; + goto unwind; + } + pInfo->driver = xstrdup(option->value); + if (!pInfo->driver) { + rval = BadAlloc; + goto unwind; + } + } + + if (strcasecmp(option->key, "name") == 0 || + strcasecmp(option->key, "identifier") == 0) { + if (pInfo->name) { + rval = BadRequest; + goto unwind; + } + pInfo->name = xstrdup(option->value); + if (!pInfo->name) { + rval = BadAlloc; + goto unwind; + } + } + + if (strcmp(option->key, "_source") == 0 && + (strcmp(option->value, "server/hal") == 0 || + strcmp(option->value, "server/udev") == 0)) { + is_auto = 1; + if (!xf86Info.autoAddDevices) { + rval = BadMatch; + goto unwind; + } + } + } + + for (option = options; option; option = option->next) { + /* Steal option key/value strings from the provided list. + * We need those strings, the InputOption list doesn't. */ + pInfo->options = xf86addNewOption(pInfo->options, + option->key, option->value); + option->key = NULL; + option->value = NULL; + } + + /* Apply InputClass settings */ + if (attrs) { + if (IgnoreInputClass(pInfo, attrs)) { + rval = BadIDChoice; + goto unwind; + } + + rval = MergeInputClasses(pInfo, attrs); + if (rval != Success) + goto unwind; + + pInfo->attrs = DuplicateInputAttributes(attrs); + } + + if (!pInfo->driver || !pInfo->name) { + xf86Msg(X_INFO, "No input driver/identifier specified (ignoring)\n"); + rval = BadRequest; + goto unwind; + } + + if (!pInfo->name) { + xf86Msg(X_ERROR, "No device identifier specified (ignoring)\n"); + rval = BadMatch; + goto unwind; + } + + rval = xf86NewInputDevice(pInfo, pdev, + (!is_auto || (is_auto && xf86Info.autoEnableDevices))); + + return rval; + +unwind: + if (is_auto && !xf86Info.autoAddDevices) + xf86Msg(X_INFO, "AutoAddDevices is off - not adding device.\n"); + xf86DeleteInput(pInfo, 0); + return rval; +} + +void +DeleteInputDeviceRequest(DeviceIntPtr pDev) +{ + InputInfoPtr pInfo = (InputInfoPtr) pDev->public.devicePrivate; + InputDriverPtr drv = NULL; + Bool isMaster = IsMaster(pDev); + + if (pInfo) /* need to get these before RemoveDevice */ + drv = pInfo->drv; + + OsBlockSignals(); + RemoveDevice(pDev, TRUE); + + if (!isMaster && pInfo != NULL) + { + if(drv->UnInit) + drv->UnInit(drv, pInfo, 0); + else + xf86DeleteInput(pInfo, 0); + } + OsReleaseSignals(); +} + +/* + * convenient functions to post events + */ + +void +xf86PostMotionEvent(DeviceIntPtr device, + int is_absolute, + int first_valuator, + int num_valuators, + ...) +{ + va_list var; + int i = 0; + ValuatorMask mask; + + XI_VERIFY_VALUATORS(num_valuators); + + valuator_mask_zero(&mask); + va_start(var, num_valuators); + for (i = 0; i < num_valuators; i++) + valuator_mask_set(&mask, first_valuator + i, va_arg(var, int)); + va_end(var); + + xf86PostMotionEventM(device, is_absolute, &mask); +} + +void +xf86PostMotionEventP(DeviceIntPtr device, + int is_absolute, + int first_valuator, + int num_valuators, + const int *valuators) +{ + ValuatorMask mask; + + XI_VERIFY_VALUATORS(num_valuators); + + valuator_mask_set_range(&mask, first_valuator, num_valuators, valuators); + xf86PostMotionEventM(device, is_absolute, &mask); +} + +void +xf86PostMotionEventM(DeviceIntPtr device, + int is_absolute, + const ValuatorMask *mask) +{ + int i = 0, nevents = 0; + DeviceEvent *event; + int flags = 0; + +#if XFreeXDGA + int index; + int dx = 0, dy = 0; +#endif + + if (valuator_mask_num_valuators(mask) > 0) + { + if (is_absolute) + flags = POINTER_ABSOLUTE; + else + flags = POINTER_RELATIVE | POINTER_ACCELERATE; + } + +#if XFreeXDGA + /* The evdev driver may not always send all axes across. */ + if (valuator_mask_isset(mask, 0) || + valuator_mask_isset(mask, 1)) + if (miPointerGetScreen(device)) { + index = miPointerGetScreen(device)->myNum; + if (valuator_mask_isset(mask, 0)) + { + dx = valuator_mask_get(mask, 0); + if (is_absolute) + dx -= device->last.valuators[0]; + } + + if (valuator_mask_isset(mask, 1)) + { + dy = valuator_mask_get(mask, 1); + if (is_absolute) + dy -= device->last.valuators[1]; + } + + if (DGAStealMotionEvent(device, index, dx, dy)) + return; + } +#endif + + nevents = GetPointerEvents(xf86Events, device, MotionNotify, 0, flags, mask); + + for (i = 0; i < nevents; i++) { + event = (DeviceEvent*)((xf86Events + i)->event); + mieqEnqueue(device, (InternalEvent*)((xf86Events + i)->event)); + } +} + +void +xf86PostProximityEvent(DeviceIntPtr device, + int is_in, + int first_valuator, + int num_valuators, + ...) +{ + va_list var; + int i; + ValuatorMask mask; + + XI_VERIFY_VALUATORS(num_valuators); + + valuator_mask_zero(&mask); + va_start(var, num_valuators); + for (i = 0; i < num_valuators; i++) + valuator_mask_set(&mask, first_valuator + i, va_arg(var, int)); + va_end(var); + + xf86PostProximityEventM(device, is_in, &mask); +} + +void +xf86PostProximityEventP(DeviceIntPtr device, + int is_in, + int first_valuator, + int num_valuators, + const int *valuators) +{ + ValuatorMask mask; + + XI_VERIFY_VALUATORS(num_valuators); + + valuator_mask_set_range(&mask, first_valuator, num_valuators, valuators); + xf86PostProximityEventM(device, is_in, &mask); +} + +void +xf86PostProximityEventM(DeviceIntPtr device, + int is_in, + const ValuatorMask *mask) +{ + int i, nevents; + + nevents = GetProximityEvents(xf86Events, device, + is_in ? ProximityIn : ProximityOut, mask); + for (i = 0; i < nevents; i++) + mieqEnqueue(device, (InternalEvent*)((xf86Events + i)->event)); + +} + +void +xf86PostButtonEvent(DeviceIntPtr device, + int is_absolute, + int button, + int is_down, + int first_valuator, + int num_valuators, + ...) +{ + va_list var; + ValuatorMask mask; + int i = 0; + + XI_VERIFY_VALUATORS(num_valuators); + + valuator_mask_zero(&mask); + + va_start(var, num_valuators); + for (i = 0; i < num_valuators; i++) + valuator_mask_set(&mask, first_valuator + i, va_arg(var, int)); + va_end(var); + + xf86PostButtonEventM(device, is_absolute, button, is_down, &mask); +} + +void +xf86PostButtonEventP(DeviceIntPtr device, + int is_absolute, + int button, + int is_down, + int first_valuator, + int num_valuators, + const int *valuators) +{ + ValuatorMask mask; + + XI_VERIFY_VALUATORS(num_valuators); + + valuator_mask_set_range(&mask, first_valuator, num_valuators, valuators); + xf86PostButtonEventM(device, is_absolute, button, is_down, &mask); +} + +void +xf86PostButtonEventM(DeviceIntPtr device, + int is_absolute, + int button, + int is_down, + const ValuatorMask *mask) +{ + int i = 0, nevents = 0; + int flags = 0; + +#if XFreeXDGA + int index; +#endif + + if (valuator_mask_num_valuators(mask) > 0) + { + if (is_absolute) + flags = POINTER_ABSOLUTE; + else + flags = POINTER_RELATIVE | POINTER_ACCELERATE; + } + +#if XFreeXDGA + if (miPointerGetScreen(device)) { + index = miPointerGetScreen(device)->myNum; + if (DGAStealButtonEvent(device, index, button, is_down)) + return; + } +#endif + + nevents = GetPointerEvents(xf86Events, device, + is_down ? ButtonPress : ButtonRelease, button, + flags, mask); + + for (i = 0; i < nevents; i++) + mieqEnqueue(device, (InternalEvent*)((xf86Events + i)->event)); + +} + +void +xf86PostKeyEvent(DeviceIntPtr device, + unsigned int key_code, + int is_down, + int is_absolute, + int first_valuator, + int num_valuators, + ...) +{ + va_list var; + int i = 0; + ValuatorMask mask; + + XI_VERIFY_VALUATORS(num_valuators); + + valuator_mask_zero(&mask); + + va_start(var, num_valuators); + for (i = 0; i < num_valuators; i++) + valuator_mask_set(&mask, first_valuator + i, va_arg(var, int)); + va_end(var); + + xf86PostKeyEventM(device, key_code, is_down, is_absolute, &mask); +} + +void +xf86PostKeyEventP(DeviceIntPtr device, + unsigned int key_code, + int is_down, + int is_absolute, + int first_valuator, + int num_valuators, + const int *valuators) +{ + ValuatorMask mask; + + XI_VERIFY_VALUATORS(num_valuators); + + valuator_mask_set_range(&mask, first_valuator, num_valuators, valuators); + xf86PostKeyEventM(device, key_code, is_down, is_absolute, &mask); +} + +void +xf86PostKeyEventM(DeviceIntPtr device, + unsigned int key_code, + int is_down, + int is_absolute, + const ValuatorMask *mask) +{ + int i = 0, nevents = 0; + + if (is_absolute) { + nevents = GetKeyboardValuatorEvents(xf86Events, device, + is_down ? KeyPress : KeyRelease, + key_code, mask); + } + else { + nevents = GetKeyboardEvents(xf86Events, device, + is_down ? KeyPress : KeyRelease, + key_code); + } + + for (i = 0; i < nevents; i++) + mieqEnqueue(device, (InternalEvent*)((xf86Events + i)->event)); +} + +void +xf86PostKeyboardEvent(DeviceIntPtr device, + unsigned int key_code, + int is_down) +{ + ValuatorMask mask; + + valuator_mask_zero(&mask); + xf86PostKeyEventM(device, key_code, is_down, 0, &mask); +} + +InputInfoPtr +xf86FirstLocalDevice(void) +{ + return xf86InputDevs; +} + +/* + * Cx - raw data from touch screen + * to_max - scaled highest dimension + * (remember, this is of rows - 1 because of 0 origin) + * to_min - scaled lowest dimension + * from_max - highest raw value from touch screen calibration + * from_min - lowest raw value from touch screen calibration + * + * This function is the same for X or Y coordinates. + * You may have to reverse the high and low values to compensate for + * different orgins on the touch screen vs X. + * + * e.g. to scale from device coordinates into screen coordinates, call + * xf86ScaleAxis(x, 0, screen_width, dev_min, dev_max); + */ + +int +xf86ScaleAxis(int Cx, + int to_max, + int to_min, + int from_max, + int from_min ) +{ + int X; + int64_t to_width = to_max - to_min; + int64_t from_width = from_max - from_min; + + if (from_width) { + X = (int)(((to_width * (Cx - from_min)) / from_width) + to_min); + } + else { + X = 0; + ErrorF ("Divide by Zero in xf86ScaleAxis\n"); + } + + if (X > to_max) + X = to_max; + if (X < to_min) + X = to_min; + + return X; +} + +/* + * This function checks the given screen against the current screen and + * makes changes if appropriate. It should be called from an XInput driver's + * ReadInput function before any events are posted, if the device is screen + * specific like a touch screen. + */ +void +xf86XInputSetScreen(InputInfoPtr pInfo, + int screen_number, + int x, + int y) +{ + if (miPointerGetScreen(pInfo->dev) != + screenInfo.screens[screen_number]) { + miPointerSetScreen(pInfo->dev, screen_number, x, y); + } +} + + +void +xf86InitValuatorAxisStruct(DeviceIntPtr dev, int axnum, Atom label, int minval, int maxval, + int resolution, int min_res, int max_res, int mode) +{ + if (!dev || !dev->valuator) + return; + + InitValuatorAxisStruct(dev, axnum, label, minval, maxval, resolution, min_res, + max_res, mode); +} + +/* + * Set the valuator values to be in synch with dix/event.c + * DefineInitialRootWindow(). + */ +void +xf86InitValuatorDefaults(DeviceIntPtr dev, int axnum) +{ + if (axnum == 0) { + dev->valuator->axisVal[0] = screenInfo.screens[0]->width / 2; + dev->last.valuators[0] = dev->valuator->axisVal[0]; + } + else if (axnum == 1) { + dev->valuator->axisVal[1] = screenInfo.screens[0]->height / 2; + dev->last.valuators[1] = dev->valuator->axisVal[1]; + } +} + + +/** + * Deactivate a device. Call this function from the driver if you receive a + * read error or something else that spoils your day. + * Device will be moved to the off_devices list, but it will still be there + * until you really clean up after it. + * Notifies the client about an inactive device. + * + * @param panic True if device is unrecoverable and needs to be removed. + */ +void +xf86DisableDevice(DeviceIntPtr dev, Bool panic) +{ + if(!panic) + { + DisableDevice(dev, TRUE); + } else + { + SendDevicePresenceEvent(dev->id, DeviceUnrecoverable); + DeleteInputDeviceRequest(dev); + } +} + +/** + * Reactivate a device. Call this function from the driver if you just found + * out that the read error wasn't quite that bad after all. + * Device will be re-activated, and an event sent to the client. + */ +void +xf86EnableDevice(DeviceIntPtr dev) +{ + EnableDevice(dev, TRUE); +} + +/* end of xf86Xinput.c */ diff --git a/xorg-server/hw/xfree86/doc/Makefile.am b/xorg-server/hw/xfree86/doc/Makefile.am index a8cbc3c6b..80217365d 100644 --- a/xorg-server/hw/xfree86/doc/Makefile.am +++ b/xorg-server/hw/xfree86/doc/Makefile.am @@ -1,8 +1,4 @@ -if BUILDDOCS -SUBDIRS = devel man sgml -else -SUBDIRS = man -endif - -EXTRA_DIST = \ - README.modes +SUBDIRS = devel man sgml + +EXTRA_DIST = \ + README.modes diff --git a/xorg-server/hw/xquartz/GL/Makefile.am b/xorg-server/hw/xquartz/GL/Makefile.am index af890776e..736c94b4a 100644 --- a/xorg-server/hw/xquartz/GL/Makefile.am +++ b/xorg-server/hw/xquartz/GL/Makefile.am @@ -1,5 +1,5 @@ noinst_LTLIBRARIES = libCGLCore.la -AM_CFLAGS = $(DIX_CFLAGS) +AM_CFLAGS = $(DIX_CFLAGS) $(GL_CFLAGS) AM_CPPFLAGS = \ -I$(top_srcdir) \ -I$(top_srcdir)/glx \ diff --git a/xorg-server/hw/xquartz/Makefile.am b/xorg-server/hw/xquartz/Makefile.am index 23bf04c2e..96b1fb0c5 100644 --- a/xorg-server/hw/xquartz/Makefile.am +++ b/xorg-server/hw/xquartz/Makefile.am @@ -1,56 +1,54 @@ -noinst_LTLIBRARIES = libXquartz.la -AM_CFLAGS = $(DIX_CFLAGS) -AM_OBJCFLAGS = $(DIX_CFLAGS) -AM_CPPFLAGS = \ - -DBUILD_DATE=\"$(BUILD_DATE)\" \ - -DXSERVER_VERSION=\"$(VERSION)\" \ - -DINXQUARTZ \ - -DUSE_NEW_CLUT \ - -DXFree86Server \ - -I$(top_srcdir)/miext/rootless \ - -DX11LIBDIR=\"$(libdir)\" - -if GLX -GL_DIR = GL -endif - -SUBDIRS = bundle . $(GL_DIR) xpr pbproxy mach-startup doc - -DIST_SUBDIRS = bundle . GL xpr pbproxy mach-startup doc - -libXquartz_la_SOURCES = \ - $(top_srcdir)/fb/fbcmap_mi.c \ - $(top_srcdir)/mi/miinitext.c \ - X11Application.m \ - X11Controller.m \ - applewm.c \ - darwin.c \ - darwinEvents.c \ - darwinXinput.c \ - keysym2ucs.c \ - pseudoramiX.c \ - quartz.c \ - quartzAudio.c \ - quartzCocoa.m \ - quartzKeyboard.c \ - quartzStartup.c \ - quartzRandR.c \ - threadSafety.c - -EXTRA_DIST = \ - X11Application.h \ - X11Controller.h \ - applewmExt.h \ - darwin.h \ - darwinfb.h \ - darwinEvents.h \ - keysym2ucs.h \ - pseudoramiX.h \ - quartz.h \ - quartzAudio.h \ - quartzCommon.h \ - quartzKeyboard.h \ - quartzRandR.h \ - sanitizedCarbon.h \ - sanitizedCocoa.h \ - threadSafety.h +noinst_LTLIBRARIES = libXquartz.la +AM_CFLAGS = $(DIX_CFLAGS) +AM_OBJCFLAGS = $(DIX_CFLAGS) +AM_CPPFLAGS = \ + -DBUILD_DATE=\"$(BUILD_DATE)\" \ + -DXSERVER_VERSION=\"$(VERSION)\" \ + -DINXQUARTZ \ + -DUSE_NEW_CLUT \ + -DXFree86Server \ + -I$(top_srcdir)/miext/rootless \ + -DX11LIBDIR=\"$(libdir)\" + +if GLX +GL_DIR = GL +endif + +SUBDIRS = bundle . $(GL_DIR) xpr pbproxy mach-startup doc + +DIST_SUBDIRS = bundle . GL xpr pbproxy mach-startup doc + +libXquartz_la_SOURCES = \ + $(top_srcdir)/fb/fbcmap_mi.c \ + $(top_srcdir)/mi/miinitext.c \ + X11Application.m \ + X11Controller.m \ + applewm.c \ + darwin.c \ + darwinEvents.c \ + darwinXinput.c \ + keysym2ucs.c \ + pseudoramiX.c \ + quartz.c \ + quartzCocoa.m \ + quartzKeyboard.c \ + quartzStartup.c \ + quartzRandR.c \ + threadSafety.c + +EXTRA_DIST = \ + X11Application.h \ + X11Controller.h \ + applewmExt.h \ + darwin.h \ + darwinfb.h \ + darwinEvents.h \ + keysym2ucs.h \ + pseudoramiX.h \ + quartz.h \ + quartzCommon.h \ + quartzKeyboard.h \ + quartzRandR.h \ + sanitizedCarbon.h \ + sanitizedCocoa.h \ + threadSafety.h diff --git a/xorg-server/hw/xquartz/X11Application.h b/xorg-server/hw/xquartz/X11Application.h index 71a593b40..b3ad19b53 100644 --- a/xorg-server/hw/xquartz/X11Application.h +++ b/xorg-server/hw/xquartz/X11Application.h @@ -1,110 +1,109 @@ -/* X11Application.h -- subclass of NSApplication to multiplex events - - Copyright (c) 2002-2007 Apple Inc. All rights reserved. - - Permission is hereby granted, free of charge, to any person - obtaining a copy of this software and associated documentation files - (the "Software"), to deal in the Software without restriction, - including without limitation the rights to use, copy, modify, merge, - publish, distribute, sublicense, and/or sell copies of the Software, - and to permit persons to whom the Software is furnished to do so, - subject to the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT - HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name(s) of the above - copyright holders shall not be used in advertising or otherwise to - promote the sale, use or other dealings in this Software without - prior written authorization. */ - -#ifndef X11APPLICATION_H -#define X11APPLICATION_H 1 - -#if __OBJC__ - -#import "X11Controller.h" - -@interface X11Application : NSApplication { - X11Controller *_controller; - - unsigned int _x_active :1; -} - -- (void) set_controller:controller; -- (void) set_window_menu:(NSArray *)list; - -- (int) prefs_get_integer:(NSString *)key default:(int)def; -- (const char *) prefs_get_string:(NSString *)key default:(const char *)def; -- (float) prefs_get_float:(NSString *)key default:(float)def; -- (int) prefs_get_boolean:(NSString *)key default:(int)def; -- (NSURL *) prefs_copy_url:(NSString *)key default:(NSURL *)def; -- (NSArray *) prefs_get_array:(NSString *)key; -- (void) prefs_set_integer:(NSString *)key value:(int)value; -- (void) prefs_set_float:(NSString *)key value:(float)value; -- (void) prefs_set_boolean:(NSString *)key value:(int)value; -- (void) prefs_set_array:(NSString *)key value:(NSArray *)value; -- (void) prefs_set_string:(NSString *)key value:(NSString *)value; -- (void) prefs_synchronize; - -- (X11Controller *) controller; -- (OSX_BOOL) x_active; -@end - -extern X11Application *X11App; - -#endif /* __OBJC__ */ - -void X11ApplicationSetWindowMenu (int nitems, const char **items, - const char *shortcuts); -void X11ApplicationSetWindowMenuCheck (int idx); -void X11ApplicationSetFrontProcess (void); -void X11ApplicationSetCanQuit (int state); -void X11ApplicationServerReady (void); -void X11ApplicationShowHideMenubar (int state); -void X11ApplicationLaunchClient (const char *cmd); - -void X11ApplicationMain(int argc, char **argv, char **envp); - -#define PREFS_APPSMENU "apps_menu" -#define PREFS_FAKEBUTTONS "enable_fake_buttons" -#define PREFS_SYSBEEP "enable_system_beep" -#define PREFS_KEYEQUIVS "enable_key_equivalents" -#define PREFS_FULLSCREEN_HOTKEYS "fullscreen_hotkeys" -#define PREFS_FULLSCREEN_MENU "fullscreen_menu" -#define PREFS_SYNC_KEYMAP "sync_keymap" -#define PREFS_DEPTH "depth" -#define PREFS_NO_AUTH "no_auth" -#define PREFS_NO_TCP "nolisten_tcp" -#define PREFS_DONE_XINIT_CHECK "done_xinit_check" -#define PREFS_NO_QUIT_ALERT "no_quit_alert" -#define PREFS_OPTION_SENDS_ALT "option_sends_alt" -#define PREFS_FAKE_BUTTON2 "fake_button2" -#define PREFS_FAKE_BUTTON3 "fake_button3" -#define PREFS_APPKIT_MODIFIERS "appkit_modifiers" -#define PREFS_WINDOW_ITEM_MODIFIERS "window_item_modifiers" -#define PREFS_ROOTLESS "rootless" -#define PREFS_TEST_EXTENSIONS "enable_test_extensions" -#define PREFS_XP_OPTIONS "xp_options" -#define PREFS_LOGIN_SHELL "login_shell" -#define PREFS_UPDATE_FEED "update_feed" -#define PREFS_CLICK_THROUGH "wm_click_through" -#define PREFS_FFM "wm_ffm" -#define PREFS_FOCUS_ON_NEW_WINDOW "wm_focus_on_new_window" - -#define PREFS_SYNC_PB "sync_pasteboard" -#define PREFS_SYNC_PB_TO_CLIPBOARD "sync_pasteboard_to_clipboard" -#define PREFS_SYNC_PB_TO_PRIMARY "sync_pasteboard_to_primary" -#define PREFS_SYNC_CLIPBOARD_TO_PB "sync_clipboard_to_pasteboard" -#define PREFS_SYNC_PRIMARY_ON_SELECT "sync_primary_on_select" - -#endif /* X11APPLICATION_H */ +/* X11Application.h -- subclass of NSApplication to multiplex events + + Copyright (c) 2002-2007 Apple Inc. All rights reserved. + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation files + (the "Software"), to deal in the Software without restriction, + including without limitation the rights to use, copy, modify, merge, + publish, distribute, sublicense, and/or sell copies of the Software, + and to permit persons to whom the Software is furnished to do so, + subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT + HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the name(s) of the above + copyright holders shall not be used in advertising or otherwise to + promote the sale, use or other dealings in this Software without + prior written authorization. */ + +#ifndef X11APPLICATION_H +#define X11APPLICATION_H 1 + +#if __OBJC__ + +#import "X11Controller.h" + +@interface X11Application : NSApplication { + X11Controller *_controller; + + unsigned int _x_active :1; +} + +- (void) set_controller:controller; +- (void) set_window_menu:(NSArray *)list; + +- (int) prefs_get_integer:(NSString *)key default:(int)def; +- (const char *) prefs_get_string:(NSString *)key default:(const char *)def; +- (float) prefs_get_float:(NSString *)key default:(float)def; +- (int) prefs_get_boolean:(NSString *)key default:(int)def; +- (NSURL *) prefs_copy_url:(NSString *)key default:(NSURL *)def; +- (NSArray *) prefs_get_array:(NSString *)key; +- (void) prefs_set_integer:(NSString *)key value:(int)value; +- (void) prefs_set_float:(NSString *)key value:(float)value; +- (void) prefs_set_boolean:(NSString *)key value:(int)value; +- (void) prefs_set_array:(NSString *)key value:(NSArray *)value; +- (void) prefs_set_string:(NSString *)key value:(NSString *)value; +- (void) prefs_synchronize; + +- (X11Controller *) controller; +- (OSX_BOOL) x_active; +@end + +extern X11Application *X11App; + +#endif /* __OBJC__ */ + +void X11ApplicationSetWindowMenu (int nitems, const char **items, + const char *shortcuts); +void X11ApplicationSetWindowMenuCheck (int idx); +void X11ApplicationSetFrontProcess (void); +void X11ApplicationSetCanQuit (int state); +void X11ApplicationServerReady (void); +void X11ApplicationShowHideMenubar (int state); +void X11ApplicationLaunchClient (const char *cmd); + +void X11ApplicationMain(int argc, char **argv, char **envp); + +#define PREFS_APPSMENU "apps_menu" +#define PREFS_FAKEBUTTONS "enable_fake_buttons" +#define PREFS_KEYEQUIVS "enable_key_equivalents" +#define PREFS_FULLSCREEN_HOTKEYS "fullscreen_hotkeys" +#define PREFS_FULLSCREEN_MENU "fullscreen_menu" +#define PREFS_SYNC_KEYMAP "sync_keymap" +#define PREFS_DEPTH "depth" +#define PREFS_NO_AUTH "no_auth" +#define PREFS_NO_TCP "nolisten_tcp" +#define PREFS_DONE_XINIT_CHECK "done_xinit_check" +#define PREFS_NO_QUIT_ALERT "no_quit_alert" +#define PREFS_OPTION_SENDS_ALT "option_sends_alt" +#define PREFS_FAKE_BUTTON2 "fake_button2" +#define PREFS_FAKE_BUTTON3 "fake_button3" +#define PREFS_APPKIT_MODIFIERS "appkit_modifiers" +#define PREFS_WINDOW_ITEM_MODIFIERS "window_item_modifiers" +#define PREFS_ROOTLESS "rootless" +#define PREFS_TEST_EXTENSIONS "enable_test_extensions" +#define PREFS_XP_OPTIONS "xp_options" +#define PREFS_LOGIN_SHELL "login_shell" +#define PREFS_UPDATE_FEED "update_feed" +#define PREFS_CLICK_THROUGH "wm_click_through" +#define PREFS_FFM "wm_ffm" +#define PREFS_FOCUS_ON_NEW_WINDOW "wm_focus_on_new_window" + +#define PREFS_SYNC_PB "sync_pasteboard" +#define PREFS_SYNC_PB_TO_CLIPBOARD "sync_pasteboard_to_clipboard" +#define PREFS_SYNC_PB_TO_PRIMARY "sync_pasteboard_to_primary" +#define PREFS_SYNC_CLIPBOARD_TO_PB "sync_clipboard_to_pasteboard" +#define PREFS_SYNC_PRIMARY_ON_SELECT "sync_primary_on_select" + +#endif /* X11APPLICATION_H */ diff --git a/xorg-server/hw/xquartz/X11Application.m b/xorg-server/hw/xquartz/X11Application.m index 264c1fbea..b855c8358 100644 --- a/xorg-server/hw/xquartz/X11Application.m +++ b/xorg-server/hw/xquartz/X11Application.m @@ -1,1322 +1,1320 @@ -/* X11Application.m -- subclass of NSApplication to multiplex events - - Copyright (c) 2002-2008 Apple Inc. - - Permission is hereby granted, free of charge, to any person - obtaining a copy of this software and associated documentation files - (the "Software"), to deal in the Software without restriction, - including without limitation the rights to use, copy, modify, merge, - publish, distribute, sublicense, and/or sell copies of the Software, - and to permit persons to whom the Software is furnished to do so, - subject to the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT - HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name(s) of the above - copyright holders shall not be used in advertising or otherwise to - promote the sale, use or other dealings in this Software without - prior written authorization. */ - -#include "sanitizedCarbon.h" - -#ifdef HAVE_DIX_CONFIG_H -#include -#endif - -#include "quartzCommon.h" - -#import "X11Application.h" - -#include "darwin.h" -#include "quartz.h" -#include "darwinEvents.h" -#include "quartzKeyboard.h" -#include "quartz.h" -#include -#include "micmap.h" -#include "exglobals.h" - -#include -#include -#include - -#include - -// pbproxy/pbproxy.h -extern int xpbproxy_run (void); - -#define DEFAULTS_FILE X11LIBDIR"/X11/xserver/Xquartz.plist" - -#ifndef XSERVER_VERSION -#define XSERVER_VERSION "?" -#endif - -/* Stuck modifier / button state... force release when we context switch */ -static NSEventType keyState[NUM_KEYCODES]; - -extern Bool noTestExtensions; - -#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050 -static TISInputSourceRef last_key_layout; -#else -static KeyboardLayoutRef last_key_layout; -#endif - -extern int darwinFakeButtons; - -/* Store the mouse location while in the background, and update X11's pointer - * location when we become the foreground application - */ -static NSPoint bgMouseLocation; -static BOOL bgMouseLocationUpdated = FALSE; - -X11Application *X11App; - -CFStringRef app_prefs_domain_cfstr = NULL; - -#define ALL_KEY_MASKS (NSShiftKeyMask | NSControlKeyMask | NSAlternateKeyMask | NSCommandKeyMask) - -@interface X11Application (Private) -- (void) sendX11NSEvent:(NSEvent *)e; -@end - -@implementation X11Application - -typedef struct message_struct message; -struct message_struct { - mach_msg_header_t hdr; - SEL selector; - NSObject *arg; -}; - -static mach_port_t _port; - -/* Quartz mode initialization routine. This is often dynamically loaded - but is statically linked into this X server. */ -Bool QuartzModeBundleInit(void); - -static void init_ports (void) { - kern_return_t r; - NSPort *p; - - if (_port != MACH_PORT_NULL) return; - - r = mach_port_allocate (mach_task_self (), MACH_PORT_RIGHT_RECEIVE, &_port); - if (r != KERN_SUCCESS) return; - - p = [NSMachPort portWithMachPort:_port]; - [p setDelegate:NSApp]; - [p scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; -} - -static void message_kit_thread (SEL selector, NSObject *arg) { - message msg; - kern_return_t r; - - msg.hdr.msgh_bits = MACH_MSGH_BITS (MACH_MSG_TYPE_MAKE_SEND, 0); - msg.hdr.msgh_size = sizeof (msg); - msg.hdr.msgh_remote_port = _port; - msg.hdr.msgh_local_port = MACH_PORT_NULL; - msg.hdr.msgh_reserved = 0; - msg.hdr.msgh_id = 0; - - msg.selector = selector; - msg.arg = [arg retain]; - - r = mach_msg (&msg.hdr, MACH_SEND_MSG, msg.hdr.msgh_size, - 0, MACH_PORT_NULL, 0, MACH_PORT_NULL); - if (r != KERN_SUCCESS) - ErrorF("%s: mach_msg failed: %x\n", __FUNCTION__, r); -} - -- (void) handleMachMessage:(void *)_msg { - message *msg = _msg; - - [self performSelector:msg->selector withObject:msg->arg]; - [msg->arg release]; -} - -- (void) set_controller:obj { - if (_controller == nil) _controller = [obj retain]; -} - -- (void) dealloc { - if (_controller != nil) [_controller release]; - - if (_port != MACH_PORT_NULL) - mach_port_deallocate (mach_task_self (), _port); - - [super dealloc]; -} - -- (void) orderFrontStandardAboutPanel: (id) sender { - NSMutableDictionary *dict; - NSDictionary *infoDict; - NSString *tem; - - dict = [NSMutableDictionary dictionaryWithCapacity:3]; - infoDict = [[NSBundle mainBundle] infoDictionary]; - - [dict setObject: NSLocalizedString (@"The X Window System", @"About panel") - forKey:@"ApplicationName"]; - - tem = [infoDict objectForKey:@"CFBundleShortVersionString"]; - - [dict setObject:[NSString stringWithFormat:@"XQuartz %@", tem] - forKey:@"ApplicationVersion"]; - - [dict setObject:[NSString stringWithFormat:@"xorg-server %s", XSERVER_VERSION] - forKey:@"Version"]; - - [self orderFrontStandardAboutPanelWithOptions: dict]; -} - -- (void) activateX:(OSX_BOOL)state { - size_t i; - DEBUG_LOG("state=%d, _x_active=%d, \n", state, _x_active) - if (state) { - if(bgMouseLocationUpdated) { - DarwinSendPointerEvents(darwinPointer, MotionNotify, 0, bgMouseLocation.x, bgMouseLocation.y, 0.0, 0.0, 0.0); - bgMouseLocationUpdated = FALSE; - } - DarwinSendDDXEvent(kXquartzActivate, 0); - } else { - - if(darwin_all_modifier_flags) - DarwinUpdateModKeys(0); - for(i=0; i < NUM_KEYCODES; i++) { - if(keyState[i] == NSKeyDown) { - DarwinSendKeyboardEvents(KeyRelease, i); - keyState[i] = NSKeyUp; - } - } - - DarwinSendDDXEvent(kXquartzDeactivate, 0); - } - - _x_active = state; -} - -- (void) became_key:(NSWindow *)win { - [self activateX:NO]; -} - -- (void) sendEvent:(NSEvent *)e { - OSX_BOOL for_appkit, for_x; - - /* By default pass down the responder chain and to X. */ - for_appkit = YES; - for_x = YES; - - switch ([e type]) { - case NSLeftMouseDown: case NSRightMouseDown: case NSOtherMouseDown: - case NSLeftMouseUp: case NSRightMouseUp: case NSOtherMouseUp: - if ([e window] != nil) { - /* Pointer event has an (AppKit) window. Probably something for the kit. */ - for_x = NO; - if (_x_active) [self activateX:NO]; - } else if ([self modalWindow] == nil) { - /* Must be an X window. Tell appkit it doesn't have focus. */ - for_appkit = NO; - - if ([self isActive]) { - [self deactivate]; - if (!_x_active && quartzProcs->IsX11Window([e window], - [e windowNumber])) - [self activateX:YES]; - } - } - - /* We want to force sending to appkit if we're over the menu bar */ - if(!for_appkit) { - NSPoint NSlocation = [e locationInWindow]; - NSWindow *window = [e window]; - NSRect NSframe, NSvisibleFrame; - CGRect CGframe, CGvisibleFrame; - CGPoint CGlocation; - - if (window != nil) { - NSRect frame = [window frame]; - NSlocation.x += frame.origin.x; - NSlocation.y += frame.origin.y; - } - - NSframe = [[NSScreen mainScreen] frame]; - NSvisibleFrame = [[NSScreen mainScreen] visibleFrame]; - - CGframe = CGRectMake(NSframe.origin.x, NSframe.origin.y, - NSframe.size.width, NSframe.size.height); - CGvisibleFrame = CGRectMake(NSvisibleFrame.origin.x, - NSvisibleFrame.origin.y, - NSvisibleFrame.size.width, - NSvisibleFrame.size.height); - CGlocation = CGPointMake(NSlocation.x, NSlocation.y); - - if(CGRectContainsPoint(CGframe, CGlocation) && - !CGRectContainsPoint(CGvisibleFrame, CGlocation)) - for_appkit = YES; - } - - break; - - case NSKeyDown: case NSKeyUp: - - if(_x_active) { - static BOOL do_swallow = NO; - static int swallow_keycode; - - if([e type] == NSKeyDown) { - /* Before that though, see if there are any global - * shortcuts bound to it. */ - - if(darwinAppKitModMask & [e modifierFlags]) { - /* Override to force sending to Appkit */ - swallow_keycode = [e keyCode]; - do_swallow = YES; - for_x = NO; -#if XPLUGIN_VERSION >= 1 - } else if(XQuartzEnableKeyEquivalents && - xp_is_symbolic_hotkey_event([e eventRef])) { - swallow_keycode = [e keyCode]; - do_swallow = YES; - for_x = NO; -#endif - } else if(XQuartzEnableKeyEquivalents && - [[self mainMenu] performKeyEquivalent:e]) { - swallow_keycode = [e keyCode]; - do_swallow = YES; - for_appkit = NO; - for_x = NO; - } else if(!XQuartzIsRootless - && ([e modifierFlags] & ALL_KEY_MASKS) == (NSCommandKeyMask | NSAlternateKeyMask) - && ([e keyCode] == 0 /*a*/ || [e keyCode] == 53 /*Esc*/)) { - /* We have this here to force processing fullscreen - * toggle even if XQuartzEnableKeyEquivalents is disabled */ - swallow_keycode = [e keyCode]; - do_swallow = YES; - for_x = NO; - for_appkit = NO; - DarwinSendDDXEvent(kXquartzToggleFullscreen, 0); - } else { - /* No kit window is focused, so send it to X. */ - for_appkit = NO; - } - } else { /* KeyUp */ - /* If we saw a key equivalent on the down, don't pass - * the up through to X. */ - if (do_swallow && [e keyCode] == swallow_keycode) { - do_swallow = NO; - for_x = NO; - } - } - } else { /* !_x_active */ - for_x = NO; - } - break; - - case NSFlagsChanged: - /* Don't tell X11 about modifiers changing while it's not active */ - if (!_x_active) - for_x = NO; - break; - - case NSAppKitDefined: - switch ([e subtype]) { - case NSApplicationActivatedEventType: - for_x = NO; - if ([self modalWindow] == nil) { - BOOL order_all_windows = YES, workspaces, ok; - for_appkit = NO; - - /* FIXME: hack to avoid having to pass the event to appkit, - which would cause it to raise one of its windows. */ - _appFlags._active = YES; - - [self activateX:YES]; - - /* Get the Spaces preference for SwitchOnActivate */ - (void)CFPreferencesAppSynchronize(CFSTR("com.apple.dock")); - workspaces = CFPreferencesGetAppBooleanValue(CFSTR("workspaces"), CFSTR("com.apple.dock"), &ok); - if (!ok) - workspaces = NO; - - if (workspaces) { - (void)CFPreferencesAppSynchronize(CFSTR(".GlobalPreferences")); - order_all_windows = CFPreferencesGetAppBooleanValue(CFSTR("AppleSpacesSwitchOnActivate"), CFSTR(".GlobalPreferences"), &ok); - if (!ok) - order_all_windows = YES; - } - - /* TODO: In the workspaces && !AppleSpacesSwitchOnActivate case, the windows are ordered - * correctly, but we need to activate the top window on this space if there is - * none active. - * - * If there are no active windows, and there are minimized windows, we should - * be restoring one of them. - */ - if ([e data2] & 0x10) // 0x10 is set when we use cmd-tab or the dock icon - DarwinSendDDXEvent(kXquartzBringAllToFront, 1, order_all_windows); - } - break; - - case 18: /* ApplicationDidReactivate */ - if (XQuartzFullscreenVisible) for_appkit = NO; - break; - - case NSApplicationDeactivatedEventType: - for_x = NO; - [self activateX:NO]; - break; - } - break; - - default: break; /* for gcc */ - } - - if (for_appkit) [super sendEvent:e]; - - if (for_x) [self sendX11NSEvent:e]; -} - -- (void) set_window_menu:(NSArray *)list { - [_controller set_window_menu:list]; -} - -- (void) set_window_menu_check:(NSNumber *)n { - [_controller set_window_menu_check:n]; -} - -- (void) set_apps_menu:(NSArray *)list { - [_controller set_apps_menu:list]; -} - -- (void) set_front_process:unused { - [NSApp activateIgnoringOtherApps:YES]; - - if ([self modalWindow] == nil) - [self activateX:YES]; -} - -- (void) set_can_quit:(NSNumber *)state { - [_controller set_can_quit:[state boolValue]]; -} - -- (void) server_ready:unused { - [_controller server_ready]; -} - -- (void) show_hide_menubar:(NSNumber *)state { - /* Also shows/hides the dock */ - if ([state boolValue]) - SetSystemUIMode(kUIModeNormal, 0); - else - SetSystemUIMode(kUIModeAllHidden, XQuartzFullscreenMenu ? kUIOptionAutoShowMenuBar : 0); // kUIModeAllSuppressed or kUIOptionAutoShowMenuBar can be used to allow "mouse-activation" -} - -- (void) launch_client:(NSString *)cmd { - (void)[_controller application:self openFile:cmd]; -} - -/* user preferences */ - -/* Note that these functions only work for arrays whose elements - can be toll-free-bridged between NS and CF worlds. */ - -static const void *cfretain (CFAllocatorRef a, const void *b) { - return CFRetain (b); -} - -static void cfrelease (CFAllocatorRef a, const void *b) { - CFRelease (b); -} - -static CFMutableArrayRef nsarray_to_cfarray (NSArray *in) { - CFMutableArrayRef out; - CFArrayCallBacks cb; - NSObject *ns; - const CFTypeRef *cf; - int i, count; - - memset (&cb, 0, sizeof (cb)); - cb.version = 0; - cb.retain = cfretain; - cb.release = cfrelease; - - count = [in count]; - out = CFArrayCreateMutable (NULL, count, &cb); - - for (i = 0; i < count; i++) { - ns = [in objectAtIndex:i]; - - if ([ns isKindOfClass:[NSArray class]]) - cf = (CFTypeRef) nsarray_to_cfarray ((NSArray *) ns); - else - cf = CFRetain ((CFTypeRef) ns); - - CFArrayAppendValue (out, cf); - CFRelease (cf); - } - - return out; -} - -static NSMutableArray * cfarray_to_nsarray (CFArrayRef in) { - NSMutableArray *out; - const CFTypeRef *cf; - NSObject *ns; - int i, count; - - count = CFArrayGetCount (in); - out = [[NSMutableArray alloc] initWithCapacity:count]; - - for (i = 0; i < count; i++) { - cf = CFArrayGetValueAtIndex (in, i); - - if (CFGetTypeID (cf) == CFArrayGetTypeID ()) - ns = cfarray_to_nsarray ((CFArrayRef) cf); - else - ns = [(id)cf retain]; - - [out addObject:ns]; - [ns release]; - } - - return out; -} - -- (CFPropertyListRef) prefs_get_copy:(NSString *)key { - CFPropertyListRef value; - - value = CFPreferencesCopyAppValue ((CFStringRef) key, app_prefs_domain_cfstr); - - if (value == NULL) { - static CFDictionaryRef defaults; - - if (defaults == NULL) { - CFStringRef error = NULL; - CFDataRef data; - CFURLRef url; - SInt32 error_code; - - url = (CFURLCreateFromFileSystemRepresentation - (NULL, (unsigned char *)DEFAULTS_FILE, strlen (DEFAULTS_FILE), false)); - if (CFURLCreateDataAndPropertiesFromResource (NULL, url, &data, - NULL, NULL, &error_code)) { - defaults = (CFPropertyListCreateFromXMLData - (NULL, data, kCFPropertyListMutableContainersAndLeaves, &error)); - if (error != NULL) CFRelease (error); - CFRelease (data); - } - CFRelease (url); - - if (defaults != NULL) { - NSMutableArray *apps, *elt; - int count, i; - NSString *name, *nname; - - /* Localize the names in the default apps menu. */ - - apps = [(NSDictionary *)defaults objectForKey:@PREFS_APPSMENU]; - if (apps != nil) { - count = [apps count]; - for (i = 0; i < count; i++) { - elt = [apps objectAtIndex:i]; - if (elt != nil && [elt isKindOfClass:[NSArray class]]) { - name = [elt objectAtIndex:0]; - if (name != nil) { - nname = NSLocalizedString (name, nil); - if (nname != nil && nname != name) - [elt replaceObjectAtIndex:0 withObject:nname]; - } - } - } - } - } - } - - if (defaults != NULL) value = CFDictionaryGetValue (defaults, key); - if (value != NULL) CFRetain (value); - } - - return value; -} - -- (int) prefs_get_integer:(NSString *)key default:(int)def { - CFPropertyListRef value; - int ret; - - value = [self prefs_get_copy:key]; - - if (value != NULL && CFGetTypeID (value) == CFNumberGetTypeID ()) - CFNumberGetValue (value, kCFNumberIntType, &ret); - else if (value != NULL && CFGetTypeID (value) == CFStringGetTypeID ()) - ret = CFStringGetIntValue (value); - else - ret = def; - - if (value != NULL) CFRelease (value); - - return ret; -} - -- (const char *) prefs_get_string:(NSString *)key default:(const char *)def { - CFPropertyListRef value; - const char *ret = NULL; - - value = [self prefs_get_copy:key]; - - if (value != NULL && CFGetTypeID (value) == CFStringGetTypeID ()) { - NSString *s = (NSString *) value; - - ret = [s UTF8String]; - } - - if (value != NULL) CFRelease (value); - - return ret != NULL ? ret : def; -} - -- (NSURL *) prefs_copy_url:(NSString *)key default:(NSURL *)def { - CFPropertyListRef value; - NSURL *ret = NULL; - - value = [self prefs_get_copy:key]; - - if (value != NULL && CFGetTypeID (value) == CFStringGetTypeID ()) { - NSString *s = (NSString *) value; - - ret = [NSURL URLWithString:s]; - [ret retain]; - } - - if (value != NULL) CFRelease (value); - - return ret != NULL ? ret : def; -} - -- (float) prefs_get_float:(NSString *)key default:(float)def { - CFPropertyListRef value; - float ret = def; - - value = [self prefs_get_copy:key]; - - if (value != NULL - && CFGetTypeID (value) == CFNumberGetTypeID () - && CFNumberIsFloatType (value)) - CFNumberGetValue (value, kCFNumberFloatType, &ret); - else if (value != NULL && CFGetTypeID (value) == CFStringGetTypeID ()) - ret = CFStringGetDoubleValue (value); - - if (value != NULL) CFRelease (value); - - return ret; -} - -- (int) prefs_get_boolean:(NSString *)key default:(int)def { - CFPropertyListRef value; - int ret = def; - - value = [self prefs_get_copy:key]; - - if (value != NULL) { - if (CFGetTypeID (value) == CFNumberGetTypeID ()) - CFNumberGetValue (value, kCFNumberIntType, &ret); - else if (CFGetTypeID (value) == CFBooleanGetTypeID ()) - ret = CFBooleanGetValue (value); - else if (CFGetTypeID (value) == CFStringGetTypeID ()) { - const char *tem = [(NSString *) value UTF8String]; - if (strcasecmp (tem, "true") == 0 || strcasecmp (tem, "yes") == 0) - ret = YES; - else - ret = NO; - } - - CFRelease (value); - } - return ret; -} - -- (NSArray *) prefs_get_array:(NSString *)key { - NSArray *ret = nil; - CFPropertyListRef value; - - value = [self prefs_get_copy:key]; - - if (value != NULL) { - if (CFGetTypeID (value) == CFArrayGetTypeID ()) - ret = [cfarray_to_nsarray (value) autorelease]; - - CFRelease (value); - } - - return ret; -} - -- (void) prefs_set_integer:(NSString *)key value:(int)value { - CFNumberRef x; - - x = CFNumberCreate (NULL, kCFNumberIntType, &value); - - CFPreferencesSetValue ((CFStringRef) key, (CFTypeRef) x, app_prefs_domain_cfstr, - kCFPreferencesCurrentUser, kCFPreferencesAnyHost); - - CFRelease (x); -} - -- (void) prefs_set_float:(NSString *)key value:(float)value { - CFNumberRef x; - - x = CFNumberCreate (NULL, kCFNumberFloatType, &value); - - CFPreferencesSetValue ((CFStringRef) key, (CFTypeRef) x, app_prefs_domain_cfstr, - kCFPreferencesCurrentUser, kCFPreferencesAnyHost); - - CFRelease (x); -} - -- (void) prefs_set_boolean:(NSString *)key value:(int)value { - CFPreferencesSetValue ((CFStringRef) key, - (CFTypeRef) (value ? kCFBooleanTrue - : kCFBooleanFalse), app_prefs_domain_cfstr, - kCFPreferencesCurrentUser, kCFPreferencesAnyHost); - -} - -- (void) prefs_set_array:(NSString *)key value:(NSArray *)value { - CFArrayRef cfarray; - - cfarray = nsarray_to_cfarray (value); - CFPreferencesSetValue ((CFStringRef) key, - (CFTypeRef) cfarray, - app_prefs_domain_cfstr, - kCFPreferencesCurrentUser, kCFPreferencesAnyHost); - CFRelease (cfarray); -} - -- (void) prefs_set_string:(NSString *)key value:(NSString *)value { - CFPreferencesSetValue ((CFStringRef) key, (CFTypeRef) value, - app_prefs_domain_cfstr, kCFPreferencesCurrentUser, - kCFPreferencesAnyHost); -} - -- (void) prefs_synchronize { - CFPreferencesAppSynchronize (kCFPreferencesCurrentApplication); -} - -- (void) read_defaults -{ - NSString *nsstr; - const char *tem; - - XQuartzUseSysBeep = [self prefs_get_boolean:@PREFS_SYSBEEP - default:XQuartzUseSysBeep]; - XQuartzRootlessDefault = [self prefs_get_boolean:@PREFS_ROOTLESS - default:XQuartzRootlessDefault]; - XQuartzFullscreenMenu = [self prefs_get_boolean:@PREFS_FULLSCREEN_MENU - default:XQuartzFullscreenMenu]; - XQuartzFullscreenDisableHotkeys = ![self prefs_get_boolean:@PREFS_FULLSCREEN_HOTKEYS - default:!XQuartzFullscreenDisableHotkeys]; - darwinFakeButtons = [self prefs_get_boolean:@PREFS_FAKEBUTTONS - default:darwinFakeButtons]; - XQuartzOptionSendsAlt = [self prefs_get_boolean:@PREFS_OPTION_SENDS_ALT - default:XQuartzOptionSendsAlt]; - - if (darwinFakeButtons) { - const char *fake2, *fake3; - - fake2 = [self prefs_get_string:@PREFS_FAKE_BUTTON2 default:NULL]; - fake3 = [self prefs_get_string:@PREFS_FAKE_BUTTON3 default:NULL]; - - if (fake2 != NULL) darwinFakeMouse2Mask = DarwinParseModifierList(fake2, TRUE); - if (fake3 != NULL) darwinFakeMouse3Mask = DarwinParseModifierList(fake3, TRUE); - } - - tem = [self prefs_get_string:@PREFS_APPKIT_MODIFIERS default:NULL]; - if (tem != NULL) darwinAppKitModMask = DarwinParseModifierList(tem, TRUE); - - tem = [self prefs_get_string:@PREFS_WINDOW_ITEM_MODIFIERS default:NULL]; - if (tem != NULL) { - windowItemModMask = DarwinParseModifierList(tem, FALSE); - } else { - nsstr = NSLocalizedString (@"window item modifiers", @"window item modifiers"); - if(nsstr != NULL) { - tem = [nsstr UTF8String]; - if((tem != NULL) && strcmp(tem, "window item modifiers")) { - windowItemModMask = DarwinParseModifierList(tem, FALSE); - } - } - } - - XQuartzEnableKeyEquivalents = [self prefs_get_boolean:@PREFS_KEYEQUIVS - default:XQuartzEnableKeyEquivalents]; - - darwinSyncKeymap = [self prefs_get_boolean:@PREFS_SYNC_KEYMAP - default:darwinSyncKeymap]; - - darwinDesiredDepth = [self prefs_get_integer:@PREFS_DEPTH - default:darwinDesiredDepth]; - - noTestExtensions = ![self prefs_get_boolean:@PREFS_TEST_EXTENSIONS - default:FALSE]; - -#if XQUARTZ_SPARKLE - NSURL *url = [self prefs_copy_url:@PREFS_UPDATE_FEED default:nil]; - if(url) { - [[SUUpdater sharedUpdater] setFeedURL:url]; - [url release]; - } -#endif -} - -/* This will end up at the end of the responder chain. */ -- (void) copy:sender { - DarwinSendDDXEvent(kXquartzPasteboardNotify, 1, - AppleWMCopyToPasteboard); -} - -- (X11Controller *) controller { - return _controller; -} - -- (OSX_BOOL) x_active { - return _x_active; -} - -@end - -static NSArray * -array_with_strings_and_numbers (int nitems, const char **items, - const char *numbers) { - NSMutableArray *array, *subarray; - NSString *string, *number; - int i; - - /* (Can't autorelease on the X server thread) */ - - array = [[NSMutableArray alloc] initWithCapacity:nitems]; - - for (i = 0; i < nitems; i++) { - subarray = [[NSMutableArray alloc] initWithCapacity:2]; - - string = [[NSString alloc] initWithUTF8String:items[i]]; - [subarray addObject:string]; - [string release]; - - if (numbers[i] != 0) { - number = [[NSString alloc] initWithFormat:@"%d", numbers[i]]; - [subarray addObject:number]; - [number release]; - } else - [subarray addObject:@""]; - - [array addObject:subarray]; - [subarray release]; - } - - return array; -} - -void X11ApplicationSetWindowMenu (int nitems, const char **items, - const char *shortcuts) { - NSArray *array; - array = array_with_strings_and_numbers (nitems, items, shortcuts); - - /* Send the array of strings over to the appkit thread */ - - message_kit_thread (@selector (set_window_menu:), array); - [array release]; -} - -void X11ApplicationSetWindowMenuCheck (int idx) { - NSNumber *n; - - n = [[NSNumber alloc] initWithInt:idx]; - - message_kit_thread (@selector (set_window_menu_check:), n); - - [n release]; -} - -void X11ApplicationSetFrontProcess (void) { - message_kit_thread (@selector (set_front_process:), nil); -} - -void X11ApplicationSetCanQuit (int state) { - NSNumber *n; - - n = [[NSNumber alloc] initWithBool:state]; - - message_kit_thread (@selector (set_can_quit:), n); - - [n release]; -} - -void X11ApplicationServerReady (void) { - message_kit_thread (@selector (server_ready:), nil); -} - -void X11ApplicationShowHideMenubar (int state) { - NSNumber *n; - - n = [[NSNumber alloc] initWithBool:state]; - - message_kit_thread (@selector (show_hide_menubar:), n); - - [n release]; -} - -void X11ApplicationLaunchClient (const char *cmd) { - NSString *string; - - string = [[NSString alloc] initWithUTF8String:cmd]; - - message_kit_thread (@selector (launch_client:), string); - - [string release]; -} - -static void check_xinitrc (void) { - char *tem, buf[1024]; - NSString *msg; - - if ([X11App prefs_get_boolean:@PREFS_DONE_XINIT_CHECK default:NO]) - return; - - tem = getenv ("HOME"); - if (tem == NULL) goto done; - - snprintf (buf, sizeof (buf), "%s/.xinitrc", tem); - if (access (buf, F_OK) != 0) - goto done; - - msg = NSLocalizedString (@"You have an existing ~/.xinitrc file.\n\n\ -Windows displayed by X11 applications may not have titlebars, or may look \ -different to windows displayed by native applications.\n\n\ -Would you like to move aside the existing file and use the standard X11 \ -environment the next time you start X11?", @"Startup xinitrc dialog"); - - if(NSAlertDefaultReturn == NSRunAlertPanel (nil, msg, NSLocalizedString (@"Yes", @""), - NSLocalizedString (@"No", @""), nil)) { - char buf2[1024]; - int i = -1; - - snprintf (buf2, sizeof (buf2), "%s.old", buf); - - for(i = 1; access (buf2, F_OK) == 0; i++) - snprintf (buf2, sizeof (buf2), "%s.old.%d", buf, i); - - rename (buf, buf2); - } - - done: - [X11App prefs_set_boolean:@PREFS_DONE_XINIT_CHECK value:YES]; - [X11App prefs_synchronize]; -} - -static inline pthread_t create_thread(void *func, void *arg) { - pthread_attr_t attr; - pthread_t tid; - - pthread_attr_init(&attr); - pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - pthread_create(&tid, &attr, func, arg); - pthread_attr_destroy(&attr); - - return tid; -} - -static void *xpbproxy_x_thread(void *args) { - xpbproxy_run(); - - fprintf(stderr, "xpbproxy thread is terminating unexpectedly.\n"); - return NULL; -} - -void X11ApplicationMain (int argc, char **argv, char **envp) { - NSAutoreleasePool *pool; - -#ifdef DEBUG - while (access ("/tmp/x11-block", F_OK) == 0) sleep (1); -#endif - - pool = [[NSAutoreleasePool alloc] init]; - X11App = (X11Application *) [X11Application sharedApplication]; - init_ports (); - - app_prefs_domain_cfstr = (CFStringRef)[[NSBundle mainBundle] bundleIdentifier]; - - [NSApp read_defaults]; - [NSBundle loadNibNamed:@"main" owner:NSApp]; - [[NSNotificationCenter defaultCenter] addObserver:NSApp - selector:@selector (became_key:) - name:NSWindowDidBecomeKeyNotification object:nil]; - - /* - * The xpr Quartz mode is statically linked into this server. - * Initialize all the Quartz functions. - */ - QuartzModeBundleInit(); - - /* Calculate the height of the menubar so we can avoid it. */ - aquaMenuBarHeight = NSHeight([[NSScreen mainScreen] frame]) - - NSMaxY([[NSScreen mainScreen] visibleFrame]); - - /* Set the key layout seed before we start the server */ -#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050 - last_key_layout = TISCopyCurrentKeyboardLayoutInputSource(); - - if(!last_key_layout) - fprintf(stderr, "X11ApplicationMain: Unable to determine TISCopyCurrentKeyboardLayoutInputSource() at startup.\n"); -#else - KLGetCurrentKeyboardLayout(&last_key_layout); - if(!last_key_layout) - fprintf(stderr, "X11ApplicationMain: Unable to determine KLGetCurrentKeyboardLayout() at startup.\n"); -#endif - - if (!QuartsResyncKeymap(FALSE)) { - fprintf(stderr, "X11ApplicationMain: Could not build a valid keymap.\n"); - } - - /* Tell the server thread that it can proceed */ - QuartzInitServer(argc, argv, envp); - - /* This must be done after QuartzInitServer because it can result in - * an mieqEnqueue() - - */ - check_xinitrc(); - - create_thread(xpbproxy_x_thread, NULL); - -#if XQUARTZ_SPARKLE - [[X11App controller] setup_sparkle]; - [[SUUpdater sharedUpdater] resetUpdateCycle]; -// [[SUUpdater sharedUpdater] checkForUpdates:X11App]; -#endif - - [pool release]; - [NSApp run]; - /* not reached */ -} - -@implementation X11Application (Private) - -#ifdef NX_DEVICELCMDKEYMASK -/* This is to workaround a bug in the VNC server where we sometimes see the L - * modifier and sometimes see no "side" - */ -static inline int ensure_flag(int flags, int device_independent, int device_dependents, int device_dependent_default) { - if( (flags & device_independent) && - !(flags & device_dependents)) - flags |= device_dependent_default; - return flags; -} -#endif - -#ifdef DEBUG_UNTRUSTED_POINTER_DELTA -static const char *untrusted_str(NSEvent *e) { - switch([e type]) { - case NSScrollWheel: - return "NSScrollWheel"; - case NSTabletPoint: - return "NSTabletPoint"; - case NSOtherMouseDown: - return "NSOtherMouseDown"; - case NSOtherMouseUp: - return "NSOtherMouseUp"; - case NSLeftMouseDown: - return "NSLeftMouseDown"; - case NSLeftMouseUp: - return "NSLeftMouseUp"; - default: - switch([e subtype]) { - case NSTabletPointEventSubtype: - return "NSTabletPointEventSubtype"; - case NSTabletProximityEventSubtype: - return "NSTabletProximityEventSubtype"; - default: - return "Other"; - } - } -} -#endif - -- (void) sendX11NSEvent:(NSEvent *)e { - NSPoint location = NSZeroPoint, tilt = NSZeroPoint; - int ev_button, ev_type; - float pressure = 0.0; - DeviceIntPtr pDev; - int modifierFlags; - BOOL isMouseOrTabletEvent, isTabletEvent; - - isMouseOrTabletEvent = [e type] == NSLeftMouseDown || [e type] == NSOtherMouseDown || [e type] == NSRightMouseDown || - [e type] == NSLeftMouseUp || [e type] == NSOtherMouseUp || [e type] == NSRightMouseUp || - [e type] == NSLeftMouseDragged || [e type] == NSOtherMouseDragged || [e type] == NSRightMouseDragged || - [e type] == NSMouseMoved || [e type] == NSTabletPoint || [e type] == NSScrollWheel; - - isTabletEvent = ([e type] == NSTabletPoint) || - (isMouseOrTabletEvent && ([e subtype] == NSTabletPointEventSubtype || [e subtype] == NSTabletProximityEventSubtype)); - - if(isMouseOrTabletEvent) { - static NSPoint lastpt; - NSWindow *window = [e window]; - NSRect screen = [[[NSScreen screens] objectAtIndex:0] frame]; - BOOL hasUntrustedPointerDelta; - - // NSEvents for tablets are not consistent wrt deltaXY between events, so we cannot rely on that - // Thus tablets will be subject to the warp-pointer bug worked around by the delta, but tablets - // are not normally used in cases where that bug would present itself, so this is a fair tradeoff - // deltaX and deltaY are incorrect for NSMouseMoved, NSTabletPointEventSubtype - // http://xquartz.macosforge.org/trac/ticket/288 - hasUntrustedPointerDelta = isTabletEvent; - - // The deltaXY for middle click events also appear erroneous after fast user switching - // deltaX and deltaY are incorrect for NSOtherMouseDown and NSOtherMouseUp after FUS - // http://xquartz.macosforge.org/trac/ticket/389 - hasUntrustedPointerDelta = hasUntrustedPointerDelta || [e type] == NSOtherMouseDown || [e type] == NSOtherMouseUp; - - // The deltaXY for scroll events correspond to the scroll delta, not the pointer delta - // deltaXY for wheel events are being sent as mouse movement - hasUntrustedPointerDelta = hasUntrustedPointerDelta || [e type] == NSScrollWheel; - -#ifdef DEBUG_UNTRUSTED_POINTER_DELTA - hasUntrustedPointerDelta = hasUntrustedPointerDelta || [e type] == NSLeftMouseDown || [e type] == NSLeftMouseUp; -#endif - - if (window != nil) { - NSRect frame = [window frame]; - location = [e locationInWindow]; - location.x += frame.origin.x; - location.y += frame.origin.y; - lastpt = location; - } else if(hasUntrustedPointerDelta) { -#ifdef DEBUG_UNTRUSTED_POINTER_DELTA - ErrorF("--- Begin Event Debug ---\n"); - ErrorF("Event type: %s\n", untrusted_str(e)); - ErrorF("old lastpt: (%0.2f, %0.2f)\n", lastpt.x, lastpt.y); - ErrorF(" delta: (%0.2f, %0.2f)\n", [e deltaX], -[e deltaY]); - ErrorF(" location: (%0.2f, %0.2f)\n", lastpt.x + [e deltaX], lastpt.y - [e deltaY]); - ErrorF("workaround: (%0.2f, %0.2f)\n", [e locationInWindow].x, [e locationInWindow].y); - ErrorF("--- End Event Debug ---\n"); - - location.x = lastpt.x + [e deltaX]; - location.y = lastpt.y - [e deltaY]; - lastpt = [e locationInWindow]; -#else - location = [e locationInWindow]; - lastpt = location; -#endif - } else { - location.x = lastpt.x + [e deltaX]; - location.y = lastpt.y - [e deltaY]; - lastpt = [e locationInWindow]; - } - - /* Convert coordinate system */ - location.y = (screen.origin.y + screen.size.height) - location.y; - } - - modifierFlags = [e modifierFlags]; - -#ifdef NX_DEVICELCMDKEYMASK - /* This is to workaround a bug in the VNC server where we sometimes see the L - * modifier and sometimes see no "side" - */ - modifierFlags = ensure_flag(modifierFlags, NX_CONTROLMASK, NX_DEVICELCTLKEYMASK | NX_DEVICERCTLKEYMASK, NX_DEVICELCTLKEYMASK); - modifierFlags = ensure_flag(modifierFlags, NX_SHIFTMASK, NX_DEVICELSHIFTKEYMASK | NX_DEVICERSHIFTKEYMASK, NX_DEVICELSHIFTKEYMASK); - modifierFlags = ensure_flag(modifierFlags, NX_COMMANDMASK, NX_DEVICELCMDKEYMASK | NX_DEVICERCMDKEYMASK, NX_DEVICELCMDKEYMASK); - modifierFlags = ensure_flag(modifierFlags, NX_ALTERNATEMASK, NX_DEVICELALTKEYMASK | NX_DEVICERALTKEYMASK, NX_DEVICELALTKEYMASK); -#endif - - modifierFlags &= darwin_all_modifier_mask; - - /* We don't receive modifier key events while out of focus, and 3button - * emulation mucks this up, so we need to check our modifier flag state - * on every event... ugg - */ - - if(darwin_all_modifier_flags != modifierFlags) - DarwinUpdateModKeys(modifierFlags); - - switch ([e type]) { - case NSLeftMouseDown: ev_button=1; ev_type=ButtonPress; goto handle_mouse; - case NSOtherMouseDown: ev_button=2; ev_type=ButtonPress; goto handle_mouse; - case NSRightMouseDown: ev_button=3; ev_type=ButtonPress; goto handle_mouse; - case NSLeftMouseUp: ev_button=1; ev_type=ButtonRelease; goto handle_mouse; - case NSOtherMouseUp: ev_button=2; ev_type=ButtonRelease; goto handle_mouse; - case NSRightMouseUp: ev_button=3; ev_type=ButtonRelease; goto handle_mouse; - case NSLeftMouseDragged: ev_button=1; ev_type=MotionNotify; goto handle_mouse; - case NSOtherMouseDragged: ev_button=2; ev_type=MotionNotify; goto handle_mouse; - case NSRightMouseDragged: ev_button=3; ev_type=MotionNotify; goto handle_mouse; - case NSMouseMoved: ev_button=0; ev_type=MotionNotify; goto handle_mouse; - case NSTabletPoint: ev_button=0; ev_type=MotionNotify; goto handle_mouse; - - handle_mouse: - pDev = darwinPointer; - - /* NSTabletPoint can have no subtype */ - if([e type] != NSTabletPoint && - [e subtype] == NSTabletProximityEventSubtype) { - switch([e pointingDeviceType]) { - case NSEraserPointingDevice: - darwinTabletCurrent=darwinTabletEraser; - break; - case NSPenPointingDevice: - darwinTabletCurrent=darwinTabletStylus; - break; - case NSCursorPointingDevice: - case NSUnknownPointingDevice: - default: - darwinTabletCurrent=darwinTabletCursor; - break; - } - - /* NSTabletProximityEventSubtype doesn't encode pressure ant tilt - * So we just pretend the motion was caused by the mouse. Hopefully - * we'll have a better solution for this in the future (like maybe - * NSTabletProximityEventSubtype will come from NSTabletPoint - * rather than NSMouseMoved. - pressure = [e pressure]; - tilt = [e tilt]; - pDev = darwinTabletCurrent; - */ - - DarwinSendProximityEvents([e isEnteringProximity] ? ProximityIn : ProximityOut, - location.x, location.y); - } - - if ([e type] == NSTabletPoint || [e subtype] == NSTabletPointEventSubtype) { - pressure = [e pressure]; - tilt = [e tilt]; - - pDev = darwinTabletCurrent; - } - - if(!XQuartzServerVisible && noTestExtensions) { -#if defined(XPLUGIN_VERSION) && XPLUGIN_VERSION > 0 -/* Older libXplugin (Tiger/"Stock" Leopard) aren't thread safe, so we can't call xp_find_window from the Appkit thread */ - xp_window_id wid = 0; - xp_error e; - - /* Sigh. Need to check that we're really over one of - * our windows. (We need to receive pointer events while - * not in the foreground, but we don't want to receive them - * when another window is over us or we might show a tooltip) - */ - - e = xp_find_window(location.x, location.y, 0, &wid); - - if (e != XP_Success || (e == XP_Success && wid == 0)) -#endif - { - bgMouseLocation = location; - bgMouseLocationUpdated = TRUE; - return; - } - } - - if(bgMouseLocationUpdated) { - if(!(ev_type == MotionNotify && ev_button == 0)) { - DarwinSendPointerEvents(pDev, MotionNotify, 0, location.x, - location.y, pressure, tilt.x, tilt.y); - } - bgMouseLocationUpdated = FALSE; - } - - DarwinSendPointerEvents(pDev, ev_type, ev_button, location.x, location.y, - pressure, tilt.x, tilt.y); - - break; - - case NSTabletProximity: - switch([e pointingDeviceType]) { - case NSEraserPointingDevice: - darwinTabletCurrent=darwinTabletEraser; - break; - case NSPenPointingDevice: - darwinTabletCurrent=darwinTabletStylus; - break; - case NSCursorPointingDevice: - case NSUnknownPointingDevice: - default: - darwinTabletCurrent=darwinTabletCursor; - break; - } - - DarwinSendProximityEvents([e isEnteringProximity] ? ProximityIn : ProximityOut, - location.x, location.y); - break; - - case NSScrollWheel: -#if !defined(XPLUGIN_VERSION) || XPLUGIN_VERSION == 0 - /* If we're in the background, we need to send a MotionNotify event - * first, since we aren't getting them on background mouse motion - */ - if(!XQuartzServerVisible && noTestExtensions) { - bgMouseLocationUpdated = FALSE; - DarwinSendPointerEvents(darwinPointer, MotionNotify, 0, location.x, - location.y, pressure, tilt.x, tilt.y); - } -#endif - DarwinSendScrollEvents([e deltaX], [e deltaY], location.x, location.y, - pressure, tilt.x, tilt.y); - break; - - case NSKeyDown: case NSKeyUp: - { - /* XKB clobbers our keymap at startup, so we need to force it on the first keypress. - * TODO: Make this less of a kludge. - */ - static int force_resync_keymap = YES; - if(force_resync_keymap) { - DarwinSendDDXEvent(kXquartzReloadKeymap, 0); - force_resync_keymap = NO; - } - } - - if(darwinSyncKeymap) { -#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050 - TISInputSourceRef key_layout = TISCopyCurrentKeyboardLayoutInputSource(); - TISInputSourceRef clear; - if (CFEqual(key_layout, last_key_layout)) { - CFRelease(key_layout); - } else { - /* Swap/free thread-safely */ - clear = last_key_layout; - last_key_layout = key_layout; - CFRelease(clear); -#else - KeyboardLayoutRef key_layout; - KLGetCurrentKeyboardLayout(&key_layout); - if(key_layout != last_key_layout) { - last_key_layout = key_layout; -#endif - /* Update keyInfo */ - if (!QuartsResyncKeymap(TRUE)) { - fprintf(stderr, "sendX11NSEvent: Could not build a valid keymap.\n"); - } - } - } - - /* Avoid stuck keys on context switch */ - if(keyState[[e keyCode]] == [e type]) - return; - keyState[[e keyCode]] = [e type]; - - DarwinSendKeyboardEvents(([e type] == NSKeyDown) ? KeyPress : KeyRelease, [e keyCode]); - break; - - default: break; /* for gcc */ - } -} -@end +/* X11Application.m -- subclass of NSApplication to multiplex events + + Copyright (c) 2002-2008 Apple Inc. + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation files + (the "Software"), to deal in the Software without restriction, + including without limitation the rights to use, copy, modify, merge, + publish, distribute, sublicense, and/or sell copies of the Software, + and to permit persons to whom the Software is furnished to do so, + subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT + HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the name(s) of the above + copyright holders shall not be used in advertising or otherwise to + promote the sale, use or other dealings in this Software without + prior written authorization. */ + +#include "sanitizedCarbon.h" + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include "quartzCommon.h" + +#import "X11Application.h" + +#include "darwin.h" +#include "quartz.h" +#include "darwinEvents.h" +#include "quartzKeyboard.h" +#include "quartz.h" +#include +#include "micmap.h" +#include "exglobals.h" + +#include +#include +#include + +#include + +// pbproxy/pbproxy.h +extern int xpbproxy_run (void); + +#define DEFAULTS_FILE X11LIBDIR"/X11/xserver/Xquartz.plist" + +#ifndef XSERVER_VERSION +#define XSERVER_VERSION "?" +#endif + +/* Stuck modifier / button state... force release when we context switch */ +static NSEventType keyState[NUM_KEYCODES]; + +extern Bool noTestExtensions; + +#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050 +static TISInputSourceRef last_key_layout; +#else +static KeyboardLayoutRef last_key_layout; +#endif + +extern int darwinFakeButtons; + +/* Store the mouse location while in the background, and update X11's pointer + * location when we become the foreground application + */ +static NSPoint bgMouseLocation; +static BOOL bgMouseLocationUpdated = FALSE; + +X11Application *X11App; + +CFStringRef app_prefs_domain_cfstr = NULL; + +#define ALL_KEY_MASKS (NSShiftKeyMask | NSControlKeyMask | NSAlternateKeyMask | NSCommandKeyMask) + +@interface X11Application (Private) +- (void) sendX11NSEvent:(NSEvent *)e; +@end + +@implementation X11Application + +typedef struct message_struct message; +struct message_struct { + mach_msg_header_t hdr; + SEL selector; + NSObject *arg; +}; + +static mach_port_t _port; + +/* Quartz mode initialization routine. This is often dynamically loaded + but is statically linked into this X server. */ +Bool QuartzModeBundleInit(void); + +static void init_ports (void) { + kern_return_t r; + NSPort *p; + + if (_port != MACH_PORT_NULL) return; + + r = mach_port_allocate (mach_task_self (), MACH_PORT_RIGHT_RECEIVE, &_port); + if (r != KERN_SUCCESS) return; + + p = [NSMachPort portWithMachPort:_port]; + [p setDelegate:NSApp]; + [p scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; +} + +static void message_kit_thread (SEL selector, NSObject *arg) { + message msg; + kern_return_t r; + + msg.hdr.msgh_bits = MACH_MSGH_BITS (MACH_MSG_TYPE_MAKE_SEND, 0); + msg.hdr.msgh_size = sizeof (msg); + msg.hdr.msgh_remote_port = _port; + msg.hdr.msgh_local_port = MACH_PORT_NULL; + msg.hdr.msgh_reserved = 0; + msg.hdr.msgh_id = 0; + + msg.selector = selector; + msg.arg = [arg retain]; + + r = mach_msg (&msg.hdr, MACH_SEND_MSG, msg.hdr.msgh_size, + 0, MACH_PORT_NULL, 0, MACH_PORT_NULL); + if (r != KERN_SUCCESS) + ErrorF("%s: mach_msg failed: %x\n", __FUNCTION__, r); +} + +- (void) handleMachMessage:(void *)_msg { + message *msg = _msg; + + [self performSelector:msg->selector withObject:msg->arg]; + [msg->arg release]; +} + +- (void) set_controller:obj { + if (_controller == nil) _controller = [obj retain]; +} + +- (void) dealloc { + if (_controller != nil) [_controller release]; + + if (_port != MACH_PORT_NULL) + mach_port_deallocate (mach_task_self (), _port); + + [super dealloc]; +} + +- (void) orderFrontStandardAboutPanel: (id) sender { + NSMutableDictionary *dict; + NSDictionary *infoDict; + NSString *tem; + + dict = [NSMutableDictionary dictionaryWithCapacity:3]; + infoDict = [[NSBundle mainBundle] infoDictionary]; + + [dict setObject: NSLocalizedString (@"The X Window System", @"About panel") + forKey:@"ApplicationName"]; + + tem = [infoDict objectForKey:@"CFBundleShortVersionString"]; + + [dict setObject:[NSString stringWithFormat:@"XQuartz %@", tem] + forKey:@"ApplicationVersion"]; + + [dict setObject:[NSString stringWithFormat:@"xorg-server %s", XSERVER_VERSION] + forKey:@"Version"]; + + [self orderFrontStandardAboutPanelWithOptions: dict]; +} + +- (void) activateX:(OSX_BOOL)state { + size_t i; + DEBUG_LOG("state=%d, _x_active=%d, \n", state, _x_active) + if (state) { + if(bgMouseLocationUpdated) { + DarwinSendPointerEvents(darwinPointer, MotionNotify, 0, bgMouseLocation.x, bgMouseLocation.y, 0.0, 0.0, 0.0); + bgMouseLocationUpdated = FALSE; + } + DarwinSendDDXEvent(kXquartzActivate, 0); + } else { + + if(darwin_all_modifier_flags) + DarwinUpdateModKeys(0); + for(i=0; i < NUM_KEYCODES; i++) { + if(keyState[i] == NSKeyDown) { + DarwinSendKeyboardEvents(KeyRelease, i); + keyState[i] = NSKeyUp; + } + } + + DarwinSendDDXEvent(kXquartzDeactivate, 0); + } + + _x_active = state; +} + +- (void) became_key:(NSWindow *)win { + [self activateX:NO]; +} + +- (void) sendEvent:(NSEvent *)e { + OSX_BOOL for_appkit, for_x; + + /* By default pass down the responder chain and to X. */ + for_appkit = YES; + for_x = YES; + + switch ([e type]) { + case NSLeftMouseDown: case NSRightMouseDown: case NSOtherMouseDown: + case NSLeftMouseUp: case NSRightMouseUp: case NSOtherMouseUp: + if ([e window] != nil) { + /* Pointer event has an (AppKit) window. Probably something for the kit. */ + for_x = NO; + if (_x_active) [self activateX:NO]; + } else if ([self modalWindow] == nil) { + /* Must be an X window. Tell appkit it doesn't have focus. */ + for_appkit = NO; + + if ([self isActive]) { + [self deactivate]; + if (!_x_active && quartzProcs->IsX11Window([e window], + [e windowNumber])) + [self activateX:YES]; + } + } + + /* We want to force sending to appkit if we're over the menu bar */ + if(!for_appkit) { + NSPoint NSlocation = [e locationInWindow]; + NSWindow *window = [e window]; + NSRect NSframe, NSvisibleFrame; + CGRect CGframe, CGvisibleFrame; + CGPoint CGlocation; + + if (window != nil) { + NSRect frame = [window frame]; + NSlocation.x += frame.origin.x; + NSlocation.y += frame.origin.y; + } + + NSframe = [[NSScreen mainScreen] frame]; + NSvisibleFrame = [[NSScreen mainScreen] visibleFrame]; + + CGframe = CGRectMake(NSframe.origin.x, NSframe.origin.y, + NSframe.size.width, NSframe.size.height); + CGvisibleFrame = CGRectMake(NSvisibleFrame.origin.x, + NSvisibleFrame.origin.y, + NSvisibleFrame.size.width, + NSvisibleFrame.size.height); + CGlocation = CGPointMake(NSlocation.x, NSlocation.y); + + if(CGRectContainsPoint(CGframe, CGlocation) && + !CGRectContainsPoint(CGvisibleFrame, CGlocation)) + for_appkit = YES; + } + + break; + + case NSKeyDown: case NSKeyUp: + + if(_x_active) { + static BOOL do_swallow = NO; + static int swallow_keycode; + + if([e type] == NSKeyDown) { + /* Before that though, see if there are any global + * shortcuts bound to it. */ + + if(darwinAppKitModMask & [e modifierFlags]) { + /* Override to force sending to Appkit */ + swallow_keycode = [e keyCode]; + do_swallow = YES; + for_x = NO; +#if XPLUGIN_VERSION >= 1 + } else if(XQuartzEnableKeyEquivalents && + xp_is_symbolic_hotkey_event([e eventRef])) { + swallow_keycode = [e keyCode]; + do_swallow = YES; + for_x = NO; +#endif + } else if(XQuartzEnableKeyEquivalents && + [[self mainMenu] performKeyEquivalent:e]) { + swallow_keycode = [e keyCode]; + do_swallow = YES; + for_appkit = NO; + for_x = NO; + } else if(!XQuartzIsRootless + && ([e modifierFlags] & ALL_KEY_MASKS) == (NSCommandKeyMask | NSAlternateKeyMask) + && ([e keyCode] == 0 /*a*/ || [e keyCode] == 53 /*Esc*/)) { + /* We have this here to force processing fullscreen + * toggle even if XQuartzEnableKeyEquivalents is disabled */ + swallow_keycode = [e keyCode]; + do_swallow = YES; + for_x = NO; + for_appkit = NO; + DarwinSendDDXEvent(kXquartzToggleFullscreen, 0); + } else { + /* No kit window is focused, so send it to X. */ + for_appkit = NO; + } + } else { /* KeyUp */ + /* If we saw a key equivalent on the down, don't pass + * the up through to X. */ + if (do_swallow && [e keyCode] == swallow_keycode) { + do_swallow = NO; + for_x = NO; + } + } + } else { /* !_x_active */ + for_x = NO; + } + break; + + case NSFlagsChanged: + /* Don't tell X11 about modifiers changing while it's not active */ + if (!_x_active) + for_x = NO; + break; + + case NSAppKitDefined: + switch ([e subtype]) { + case NSApplicationActivatedEventType: + for_x = NO; + if ([self modalWindow] == nil) { + BOOL order_all_windows = YES, workspaces, ok; + for_appkit = NO; + + /* FIXME: hack to avoid having to pass the event to appkit, + which would cause it to raise one of its windows. */ + _appFlags._active = YES; + + [self activateX:YES]; + + /* Get the Spaces preference for SwitchOnActivate */ + (void)CFPreferencesAppSynchronize(CFSTR("com.apple.dock")); + workspaces = CFPreferencesGetAppBooleanValue(CFSTR("workspaces"), CFSTR("com.apple.dock"), &ok); + if (!ok) + workspaces = NO; + + if (workspaces) { + (void)CFPreferencesAppSynchronize(CFSTR(".GlobalPreferences")); + order_all_windows = CFPreferencesGetAppBooleanValue(CFSTR("AppleSpacesSwitchOnActivate"), CFSTR(".GlobalPreferences"), &ok); + if (!ok) + order_all_windows = YES; + } + + /* TODO: In the workspaces && !AppleSpacesSwitchOnActivate case, the windows are ordered + * correctly, but we need to activate the top window on this space if there is + * none active. + * + * If there are no active windows, and there are minimized windows, we should + * be restoring one of them. + */ + if ([e data2] & 0x10) // 0x10 is set when we use cmd-tab or the dock icon + DarwinSendDDXEvent(kXquartzBringAllToFront, 1, order_all_windows); + } + break; + + case 18: /* ApplicationDidReactivate */ + if (XQuartzFullscreenVisible) for_appkit = NO; + break; + + case NSApplicationDeactivatedEventType: + for_x = NO; + [self activateX:NO]; + break; + } + break; + + default: break; /* for gcc */ + } + + if (for_appkit) [super sendEvent:e]; + + if (for_x) [self sendX11NSEvent:e]; +} + +- (void) set_window_menu:(NSArray *)list { + [_controller set_window_menu:list]; +} + +- (void) set_window_menu_check:(NSNumber *)n { + [_controller set_window_menu_check:n]; +} + +- (void) set_apps_menu:(NSArray *)list { + [_controller set_apps_menu:list]; +} + +- (void) set_front_process:unused { + [NSApp activateIgnoringOtherApps:YES]; + + if ([self modalWindow] == nil) + [self activateX:YES]; +} + +- (void) set_can_quit:(NSNumber *)state { + [_controller set_can_quit:[state boolValue]]; +} + +- (void) server_ready:unused { + [_controller server_ready]; +} + +- (void) show_hide_menubar:(NSNumber *)state { + /* Also shows/hides the dock */ + if ([state boolValue]) + SetSystemUIMode(kUIModeNormal, 0); + else + SetSystemUIMode(kUIModeAllHidden, XQuartzFullscreenMenu ? kUIOptionAutoShowMenuBar : 0); // kUIModeAllSuppressed or kUIOptionAutoShowMenuBar can be used to allow "mouse-activation" +} + +- (void) launch_client:(NSString *)cmd { + (void)[_controller application:self openFile:cmd]; +} + +/* user preferences */ + +/* Note that these functions only work for arrays whose elements + can be toll-free-bridged between NS and CF worlds. */ + +static const void *cfretain (CFAllocatorRef a, const void *b) { + return CFRetain (b); +} + +static void cfrelease (CFAllocatorRef a, const void *b) { + CFRelease (b); +} + +static CFMutableArrayRef nsarray_to_cfarray (NSArray *in) { + CFMutableArrayRef out; + CFArrayCallBacks cb; + NSObject *ns; + const CFTypeRef *cf; + int i, count; + + memset (&cb, 0, sizeof (cb)); + cb.version = 0; + cb.retain = cfretain; + cb.release = cfrelease; + + count = [in count]; + out = CFArrayCreateMutable (NULL, count, &cb); + + for (i = 0; i < count; i++) { + ns = [in objectAtIndex:i]; + + if ([ns isKindOfClass:[NSArray class]]) + cf = (CFTypeRef) nsarray_to_cfarray ((NSArray *) ns); + else + cf = CFRetain ((CFTypeRef) ns); + + CFArrayAppendValue (out, cf); + CFRelease (cf); + } + + return out; +} + +static NSMutableArray * cfarray_to_nsarray (CFArrayRef in) { + NSMutableArray *out; + const CFTypeRef *cf; + NSObject *ns; + int i, count; + + count = CFArrayGetCount (in); + out = [[NSMutableArray alloc] initWithCapacity:count]; + + for (i = 0; i < count; i++) { + cf = CFArrayGetValueAtIndex (in, i); + + if (CFGetTypeID (cf) == CFArrayGetTypeID ()) + ns = cfarray_to_nsarray ((CFArrayRef) cf); + else + ns = [(id)cf retain]; + + [out addObject:ns]; + [ns release]; + } + + return out; +} + +- (CFPropertyListRef) prefs_get_copy:(NSString *)key { + CFPropertyListRef value; + + value = CFPreferencesCopyAppValue ((CFStringRef) key, app_prefs_domain_cfstr); + + if (value == NULL) { + static CFDictionaryRef defaults; + + if (defaults == NULL) { + CFStringRef error = NULL; + CFDataRef data; + CFURLRef url; + SInt32 error_code; + + url = (CFURLCreateFromFileSystemRepresentation + (NULL, (unsigned char *)DEFAULTS_FILE, strlen (DEFAULTS_FILE), false)); + if (CFURLCreateDataAndPropertiesFromResource (NULL, url, &data, + NULL, NULL, &error_code)) { + defaults = (CFPropertyListCreateFromXMLData + (NULL, data, kCFPropertyListMutableContainersAndLeaves, &error)); + if (error != NULL) CFRelease (error); + CFRelease (data); + } + CFRelease (url); + + if (defaults != NULL) { + NSMutableArray *apps, *elt; + int count, i; + NSString *name, *nname; + + /* Localize the names in the default apps menu. */ + + apps = [(NSDictionary *)defaults objectForKey:@PREFS_APPSMENU]; + if (apps != nil) { + count = [apps count]; + for (i = 0; i < count; i++) { + elt = [apps objectAtIndex:i]; + if (elt != nil && [elt isKindOfClass:[NSArray class]]) { + name = [elt objectAtIndex:0]; + if (name != nil) { + nname = NSLocalizedString (name, nil); + if (nname != nil && nname != name) + [elt replaceObjectAtIndex:0 withObject:nname]; + } + } + } + } + } + } + + if (defaults != NULL) value = CFDictionaryGetValue (defaults, key); + if (value != NULL) CFRetain (value); + } + + return value; +} + +- (int) prefs_get_integer:(NSString *)key default:(int)def { + CFPropertyListRef value; + int ret; + + value = [self prefs_get_copy:key]; + + if (value != NULL && CFGetTypeID (value) == CFNumberGetTypeID ()) + CFNumberGetValue (value, kCFNumberIntType, &ret); + else if (value != NULL && CFGetTypeID (value) == CFStringGetTypeID ()) + ret = CFStringGetIntValue (value); + else + ret = def; + + if (value != NULL) CFRelease (value); + + return ret; +} + +- (const char *) prefs_get_string:(NSString *)key default:(const char *)def { + CFPropertyListRef value; + const char *ret = NULL; + + value = [self prefs_get_copy:key]; + + if (value != NULL && CFGetTypeID (value) == CFStringGetTypeID ()) { + NSString *s = (NSString *) value; + + ret = [s UTF8String]; + } + + if (value != NULL) CFRelease (value); + + return ret != NULL ? ret : def; +} + +- (NSURL *) prefs_copy_url:(NSString *)key default:(NSURL *)def { + CFPropertyListRef value; + NSURL *ret = NULL; + + value = [self prefs_get_copy:key]; + + if (value != NULL && CFGetTypeID (value) == CFStringGetTypeID ()) { + NSString *s = (NSString *) value; + + ret = [NSURL URLWithString:s]; + [ret retain]; + } + + if (value != NULL) CFRelease (value); + + return ret != NULL ? ret : def; +} + +- (float) prefs_get_float:(NSString *)key default:(float)def { + CFPropertyListRef value; + float ret = def; + + value = [self prefs_get_copy:key]; + + if (value != NULL + && CFGetTypeID (value) == CFNumberGetTypeID () + && CFNumberIsFloatType (value)) + CFNumberGetValue (value, kCFNumberFloatType, &ret); + else if (value != NULL && CFGetTypeID (value) == CFStringGetTypeID ()) + ret = CFStringGetDoubleValue (value); + + if (value != NULL) CFRelease (value); + + return ret; +} + +- (int) prefs_get_boolean:(NSString *)key default:(int)def { + CFPropertyListRef value; + int ret = def; + + value = [self prefs_get_copy:key]; + + if (value != NULL) { + if (CFGetTypeID (value) == CFNumberGetTypeID ()) + CFNumberGetValue (value, kCFNumberIntType, &ret); + else if (CFGetTypeID (value) == CFBooleanGetTypeID ()) + ret = CFBooleanGetValue (value); + else if (CFGetTypeID (value) == CFStringGetTypeID ()) { + const char *tem = [(NSString *) value UTF8String]; + if (strcasecmp (tem, "true") == 0 || strcasecmp (tem, "yes") == 0) + ret = YES; + else + ret = NO; + } + + CFRelease (value); + } + return ret; +} + +- (NSArray *) prefs_get_array:(NSString *)key { + NSArray *ret = nil; + CFPropertyListRef value; + + value = [self prefs_get_copy:key]; + + if (value != NULL) { + if (CFGetTypeID (value) == CFArrayGetTypeID ()) + ret = [cfarray_to_nsarray (value) autorelease]; + + CFRelease (value); + } + + return ret; +} + +- (void) prefs_set_integer:(NSString *)key value:(int)value { + CFNumberRef x; + + x = CFNumberCreate (NULL, kCFNumberIntType, &value); + + CFPreferencesSetValue ((CFStringRef) key, (CFTypeRef) x, app_prefs_domain_cfstr, + kCFPreferencesCurrentUser, kCFPreferencesAnyHost); + + CFRelease (x); +} + +- (void) prefs_set_float:(NSString *)key value:(float)value { + CFNumberRef x; + + x = CFNumberCreate (NULL, kCFNumberFloatType, &value); + + CFPreferencesSetValue ((CFStringRef) key, (CFTypeRef) x, app_prefs_domain_cfstr, + kCFPreferencesCurrentUser, kCFPreferencesAnyHost); + + CFRelease (x); +} + +- (void) prefs_set_boolean:(NSString *)key value:(int)value { + CFPreferencesSetValue ((CFStringRef) key, + (CFTypeRef) (value ? kCFBooleanTrue + : kCFBooleanFalse), app_prefs_domain_cfstr, + kCFPreferencesCurrentUser, kCFPreferencesAnyHost); + +} + +- (void) prefs_set_array:(NSString *)key value:(NSArray *)value { + CFArrayRef cfarray; + + cfarray = nsarray_to_cfarray (value); + CFPreferencesSetValue ((CFStringRef) key, + (CFTypeRef) cfarray, + app_prefs_domain_cfstr, + kCFPreferencesCurrentUser, kCFPreferencesAnyHost); + CFRelease (cfarray); +} + +- (void) prefs_set_string:(NSString *)key value:(NSString *)value { + CFPreferencesSetValue ((CFStringRef) key, (CFTypeRef) value, + app_prefs_domain_cfstr, kCFPreferencesCurrentUser, + kCFPreferencesAnyHost); +} + +- (void) prefs_synchronize { + CFPreferencesAppSynchronize (kCFPreferencesCurrentApplication); +} + +- (void) read_defaults +{ + NSString *nsstr; + const char *tem; + + XQuartzRootlessDefault = [self prefs_get_boolean:@PREFS_ROOTLESS + default:XQuartzRootlessDefault]; + XQuartzFullscreenMenu = [self prefs_get_boolean:@PREFS_FULLSCREEN_MENU + default:XQuartzFullscreenMenu]; + XQuartzFullscreenDisableHotkeys = ![self prefs_get_boolean:@PREFS_FULLSCREEN_HOTKEYS + default:!XQuartzFullscreenDisableHotkeys]; + darwinFakeButtons = [self prefs_get_boolean:@PREFS_FAKEBUTTONS + default:darwinFakeButtons]; + XQuartzOptionSendsAlt = [self prefs_get_boolean:@PREFS_OPTION_SENDS_ALT + default:XQuartzOptionSendsAlt]; + + if (darwinFakeButtons) { + const char *fake2, *fake3; + + fake2 = [self prefs_get_string:@PREFS_FAKE_BUTTON2 default:NULL]; + fake3 = [self prefs_get_string:@PREFS_FAKE_BUTTON3 default:NULL]; + + if (fake2 != NULL) darwinFakeMouse2Mask = DarwinParseModifierList(fake2, TRUE); + if (fake3 != NULL) darwinFakeMouse3Mask = DarwinParseModifierList(fake3, TRUE); + } + + tem = [self prefs_get_string:@PREFS_APPKIT_MODIFIERS default:NULL]; + if (tem != NULL) darwinAppKitModMask = DarwinParseModifierList(tem, TRUE); + + tem = [self prefs_get_string:@PREFS_WINDOW_ITEM_MODIFIERS default:NULL]; + if (tem != NULL) { + windowItemModMask = DarwinParseModifierList(tem, FALSE); + } else { + nsstr = NSLocalizedString (@"window item modifiers", @"window item modifiers"); + if(nsstr != NULL) { + tem = [nsstr UTF8String]; + if((tem != NULL) && strcmp(tem, "window item modifiers")) { + windowItemModMask = DarwinParseModifierList(tem, FALSE); + } + } + } + + XQuartzEnableKeyEquivalents = [self prefs_get_boolean:@PREFS_KEYEQUIVS + default:XQuartzEnableKeyEquivalents]; + + darwinSyncKeymap = [self prefs_get_boolean:@PREFS_SYNC_KEYMAP + default:darwinSyncKeymap]; + + darwinDesiredDepth = [self prefs_get_integer:@PREFS_DEPTH + default:darwinDesiredDepth]; + + noTestExtensions = ![self prefs_get_boolean:@PREFS_TEST_EXTENSIONS + default:FALSE]; + +#if XQUARTZ_SPARKLE + NSURL *url = [self prefs_copy_url:@PREFS_UPDATE_FEED default:nil]; + if(url) { + [[SUUpdater sharedUpdater] setFeedURL:url]; + [url release]; + } +#endif +} + +/* This will end up at the end of the responder chain. */ +- (void) copy:sender { + DarwinSendDDXEvent(kXquartzPasteboardNotify, 1, + AppleWMCopyToPasteboard); +} + +- (X11Controller *) controller { + return _controller; +} + +- (OSX_BOOL) x_active { + return _x_active; +} + +@end + +static NSArray * +array_with_strings_and_numbers (int nitems, const char **items, + const char *numbers) { + NSMutableArray *array, *subarray; + NSString *string, *number; + int i; + + /* (Can't autorelease on the X server thread) */ + + array = [[NSMutableArray alloc] initWithCapacity:nitems]; + + for (i = 0; i < nitems; i++) { + subarray = [[NSMutableArray alloc] initWithCapacity:2]; + + string = [[NSString alloc] initWithUTF8String:items[i]]; + [subarray addObject:string]; + [string release]; + + if (numbers[i] != 0) { + number = [[NSString alloc] initWithFormat:@"%d", numbers[i]]; + [subarray addObject:number]; + [number release]; + } else + [subarray addObject:@""]; + + [array addObject:subarray]; + [subarray release]; + } + + return array; +} + +void X11ApplicationSetWindowMenu (int nitems, const char **items, + const char *shortcuts) { + NSArray *array; + array = array_with_strings_and_numbers (nitems, items, shortcuts); + + /* Send the array of strings over to the appkit thread */ + + message_kit_thread (@selector (set_window_menu:), array); + [array release]; +} + +void X11ApplicationSetWindowMenuCheck (int idx) { + NSNumber *n; + + n = [[NSNumber alloc] initWithInt:idx]; + + message_kit_thread (@selector (set_window_menu_check:), n); + + [n release]; +} + +void X11ApplicationSetFrontProcess (void) { + message_kit_thread (@selector (set_front_process:), nil); +} + +void X11ApplicationSetCanQuit (int state) { + NSNumber *n; + + n = [[NSNumber alloc] initWithBool:state]; + + message_kit_thread (@selector (set_can_quit:), n); + + [n release]; +} + +void X11ApplicationServerReady (void) { + message_kit_thread (@selector (server_ready:), nil); +} + +void X11ApplicationShowHideMenubar (int state) { + NSNumber *n; + + n = [[NSNumber alloc] initWithBool:state]; + + message_kit_thread (@selector (show_hide_menubar:), n); + + [n release]; +} + +void X11ApplicationLaunchClient (const char *cmd) { + NSString *string; + + string = [[NSString alloc] initWithUTF8String:cmd]; + + message_kit_thread (@selector (launch_client:), string); + + [string release]; +} + +static void check_xinitrc (void) { + char *tem, buf[1024]; + NSString *msg; + + if ([X11App prefs_get_boolean:@PREFS_DONE_XINIT_CHECK default:NO]) + return; + + tem = getenv ("HOME"); + if (tem == NULL) goto done; + + snprintf (buf, sizeof (buf), "%s/.xinitrc", tem); + if (access (buf, F_OK) != 0) + goto done; + + msg = NSLocalizedString (@"You have an existing ~/.xinitrc file.\n\n\ +Windows displayed by X11 applications may not have titlebars, or may look \ +different to windows displayed by native applications.\n\n\ +Would you like to move aside the existing file and use the standard X11 \ +environment the next time you start X11?", @"Startup xinitrc dialog"); + + if(NSAlertDefaultReturn == NSRunAlertPanel (nil, msg, NSLocalizedString (@"Yes", @""), + NSLocalizedString (@"No", @""), nil)) { + char buf2[1024]; + int i = -1; + + snprintf (buf2, sizeof (buf2), "%s.old", buf); + + for(i = 1; access (buf2, F_OK) == 0; i++) + snprintf (buf2, sizeof (buf2), "%s.old.%d", buf, i); + + rename (buf, buf2); + } + + done: + [X11App prefs_set_boolean:@PREFS_DONE_XINIT_CHECK value:YES]; + [X11App prefs_synchronize]; +} + +static inline pthread_t create_thread(void *func, void *arg) { + pthread_attr_t attr; + pthread_t tid; + + pthread_attr_init(&attr); + pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + pthread_create(&tid, &attr, func, arg); + pthread_attr_destroy(&attr); + + return tid; +} + +static void *xpbproxy_x_thread(void *args) { + xpbproxy_run(); + + fprintf(stderr, "xpbproxy thread is terminating unexpectedly.\n"); + return NULL; +} + +void X11ApplicationMain (int argc, char **argv, char **envp) { + NSAutoreleasePool *pool; + +#ifdef DEBUG + while (access ("/tmp/x11-block", F_OK) == 0) sleep (1); +#endif + + pool = [[NSAutoreleasePool alloc] init]; + X11App = (X11Application *) [X11Application sharedApplication]; + init_ports (); + + app_prefs_domain_cfstr = (CFStringRef)[[NSBundle mainBundle] bundleIdentifier]; + + [NSApp read_defaults]; + [NSBundle loadNibNamed:@"main" owner:NSApp]; + [[NSNotificationCenter defaultCenter] addObserver:NSApp + selector:@selector (became_key:) + name:NSWindowDidBecomeKeyNotification object:nil]; + + /* + * The xpr Quartz mode is statically linked into this server. + * Initialize all the Quartz functions. + */ + QuartzModeBundleInit(); + + /* Calculate the height of the menubar so we can avoid it. */ + aquaMenuBarHeight = NSHeight([[NSScreen mainScreen] frame]) - + NSMaxY([[NSScreen mainScreen] visibleFrame]); + + /* Set the key layout seed before we start the server */ +#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050 + last_key_layout = TISCopyCurrentKeyboardLayoutInputSource(); + + if(!last_key_layout) + fprintf(stderr, "X11ApplicationMain: Unable to determine TISCopyCurrentKeyboardLayoutInputSource() at startup.\n"); +#else + KLGetCurrentKeyboardLayout(&last_key_layout); + if(!last_key_layout) + fprintf(stderr, "X11ApplicationMain: Unable to determine KLGetCurrentKeyboardLayout() at startup.\n"); +#endif + + if (!QuartsResyncKeymap(FALSE)) { + fprintf(stderr, "X11ApplicationMain: Could not build a valid keymap.\n"); + } + + /* Tell the server thread that it can proceed */ + QuartzInitServer(argc, argv, envp); + + /* This must be done after QuartzInitServer because it can result in + * an mieqEnqueue() - + */ + check_xinitrc(); + + create_thread(xpbproxy_x_thread, NULL); + +#if XQUARTZ_SPARKLE + [[X11App controller] setup_sparkle]; + [[SUUpdater sharedUpdater] resetUpdateCycle]; +// [[SUUpdater sharedUpdater] checkForUpdates:X11App]; +#endif + + [pool release]; + [NSApp run]; + /* not reached */ +} + +@implementation X11Application (Private) + +#ifdef NX_DEVICELCMDKEYMASK +/* This is to workaround a bug in the VNC server where we sometimes see the L + * modifier and sometimes see no "side" + */ +static inline int ensure_flag(int flags, int device_independent, int device_dependents, int device_dependent_default) { + if( (flags & device_independent) && + !(flags & device_dependents)) + flags |= device_dependent_default; + return flags; +} +#endif + +#ifdef DEBUG_UNTRUSTED_POINTER_DELTA +static const char *untrusted_str(NSEvent *e) { + switch([e type]) { + case NSScrollWheel: + return "NSScrollWheel"; + case NSTabletPoint: + return "NSTabletPoint"; + case NSOtherMouseDown: + return "NSOtherMouseDown"; + case NSOtherMouseUp: + return "NSOtherMouseUp"; + case NSLeftMouseDown: + return "NSLeftMouseDown"; + case NSLeftMouseUp: + return "NSLeftMouseUp"; + default: + switch([e subtype]) { + case NSTabletPointEventSubtype: + return "NSTabletPointEventSubtype"; + case NSTabletProximityEventSubtype: + return "NSTabletProximityEventSubtype"; + default: + return "Other"; + } + } +} +#endif + +- (void) sendX11NSEvent:(NSEvent *)e { + NSPoint location = NSZeroPoint, tilt = NSZeroPoint; + int ev_button, ev_type; + float pressure = 0.0; + DeviceIntPtr pDev; + int modifierFlags; + BOOL isMouseOrTabletEvent, isTabletEvent; + + isMouseOrTabletEvent = [e type] == NSLeftMouseDown || [e type] == NSOtherMouseDown || [e type] == NSRightMouseDown || + [e type] == NSLeftMouseUp || [e type] == NSOtherMouseUp || [e type] == NSRightMouseUp || + [e type] == NSLeftMouseDragged || [e type] == NSOtherMouseDragged || [e type] == NSRightMouseDragged || + [e type] == NSMouseMoved || [e type] == NSTabletPoint || [e type] == NSScrollWheel; + + isTabletEvent = ([e type] == NSTabletPoint) || + (isMouseOrTabletEvent && ([e subtype] == NSTabletPointEventSubtype || [e subtype] == NSTabletProximityEventSubtype)); + + if(isMouseOrTabletEvent) { + static NSPoint lastpt; + NSWindow *window = [e window]; + NSRect screen = [[[NSScreen screens] objectAtIndex:0] frame]; + BOOL hasUntrustedPointerDelta; + + // NSEvents for tablets are not consistent wrt deltaXY between events, so we cannot rely on that + // Thus tablets will be subject to the warp-pointer bug worked around by the delta, but tablets + // are not normally used in cases where that bug would present itself, so this is a fair tradeoff + // deltaX and deltaY are incorrect for NSMouseMoved, NSTabletPointEventSubtype + // http://xquartz.macosforge.org/trac/ticket/288 + hasUntrustedPointerDelta = isTabletEvent; + + // The deltaXY for middle click events also appear erroneous after fast user switching + // deltaX and deltaY are incorrect for NSOtherMouseDown and NSOtherMouseUp after FUS + // http://xquartz.macosforge.org/trac/ticket/389 + hasUntrustedPointerDelta = hasUntrustedPointerDelta || [e type] == NSOtherMouseDown || [e type] == NSOtherMouseUp; + + // The deltaXY for scroll events correspond to the scroll delta, not the pointer delta + // deltaXY for wheel events are being sent as mouse movement + hasUntrustedPointerDelta = hasUntrustedPointerDelta || [e type] == NSScrollWheel; + +#ifdef DEBUG_UNTRUSTED_POINTER_DELTA + hasUntrustedPointerDelta = hasUntrustedPointerDelta || [e type] == NSLeftMouseDown || [e type] == NSLeftMouseUp; +#endif + + if (window != nil) { + NSRect frame = [window frame]; + location = [e locationInWindow]; + location.x += frame.origin.x; + location.y += frame.origin.y; + lastpt = location; + } else if(hasUntrustedPointerDelta) { +#ifdef DEBUG_UNTRUSTED_POINTER_DELTA + ErrorF("--- Begin Event Debug ---\n"); + ErrorF("Event type: %s\n", untrusted_str(e)); + ErrorF("old lastpt: (%0.2f, %0.2f)\n", lastpt.x, lastpt.y); + ErrorF(" delta: (%0.2f, %0.2f)\n", [e deltaX], -[e deltaY]); + ErrorF(" location: (%0.2f, %0.2f)\n", lastpt.x + [e deltaX], lastpt.y - [e deltaY]); + ErrorF("workaround: (%0.2f, %0.2f)\n", [e locationInWindow].x, [e locationInWindow].y); + ErrorF("--- End Event Debug ---\n"); + + location.x = lastpt.x + [e deltaX]; + location.y = lastpt.y - [e deltaY]; + lastpt = [e locationInWindow]; +#else + location = [e locationInWindow]; + lastpt = location; +#endif + } else { + location.x = lastpt.x + [e deltaX]; + location.y = lastpt.y - [e deltaY]; + lastpt = [e locationInWindow]; + } + + /* Convert coordinate system */ + location.y = (screen.origin.y + screen.size.height) - location.y; + } + + modifierFlags = [e modifierFlags]; + +#ifdef NX_DEVICELCMDKEYMASK + /* This is to workaround a bug in the VNC server where we sometimes see the L + * modifier and sometimes see no "side" + */ + modifierFlags = ensure_flag(modifierFlags, NX_CONTROLMASK, NX_DEVICELCTLKEYMASK | NX_DEVICERCTLKEYMASK, NX_DEVICELCTLKEYMASK); + modifierFlags = ensure_flag(modifierFlags, NX_SHIFTMASK, NX_DEVICELSHIFTKEYMASK | NX_DEVICERSHIFTKEYMASK, NX_DEVICELSHIFTKEYMASK); + modifierFlags = ensure_flag(modifierFlags, NX_COMMANDMASK, NX_DEVICELCMDKEYMASK | NX_DEVICERCMDKEYMASK, NX_DEVICELCMDKEYMASK); + modifierFlags = ensure_flag(modifierFlags, NX_ALTERNATEMASK, NX_DEVICELALTKEYMASK | NX_DEVICERALTKEYMASK, NX_DEVICELALTKEYMASK); +#endif + + modifierFlags &= darwin_all_modifier_mask; + + /* We don't receive modifier key events while out of focus, and 3button + * emulation mucks this up, so we need to check our modifier flag state + * on every event... ugg + */ + + if(darwin_all_modifier_flags != modifierFlags) + DarwinUpdateModKeys(modifierFlags); + + switch ([e type]) { + case NSLeftMouseDown: ev_button=1; ev_type=ButtonPress; goto handle_mouse; + case NSOtherMouseDown: ev_button=2; ev_type=ButtonPress; goto handle_mouse; + case NSRightMouseDown: ev_button=3; ev_type=ButtonPress; goto handle_mouse; + case NSLeftMouseUp: ev_button=1; ev_type=ButtonRelease; goto handle_mouse; + case NSOtherMouseUp: ev_button=2; ev_type=ButtonRelease; goto handle_mouse; + case NSRightMouseUp: ev_button=3; ev_type=ButtonRelease; goto handle_mouse; + case NSLeftMouseDragged: ev_button=1; ev_type=MotionNotify; goto handle_mouse; + case NSOtherMouseDragged: ev_button=2; ev_type=MotionNotify; goto handle_mouse; + case NSRightMouseDragged: ev_button=3; ev_type=MotionNotify; goto handle_mouse; + case NSMouseMoved: ev_button=0; ev_type=MotionNotify; goto handle_mouse; + case NSTabletPoint: ev_button=0; ev_type=MotionNotify; goto handle_mouse; + + handle_mouse: + pDev = darwinPointer; + + /* NSTabletPoint can have no subtype */ + if([e type] != NSTabletPoint && + [e subtype] == NSTabletProximityEventSubtype) { + switch([e pointingDeviceType]) { + case NSEraserPointingDevice: + darwinTabletCurrent=darwinTabletEraser; + break; + case NSPenPointingDevice: + darwinTabletCurrent=darwinTabletStylus; + break; + case NSCursorPointingDevice: + case NSUnknownPointingDevice: + default: + darwinTabletCurrent=darwinTabletCursor; + break; + } + + /* NSTabletProximityEventSubtype doesn't encode pressure ant tilt + * So we just pretend the motion was caused by the mouse. Hopefully + * we'll have a better solution for this in the future (like maybe + * NSTabletProximityEventSubtype will come from NSTabletPoint + * rather than NSMouseMoved. + pressure = [e pressure]; + tilt = [e tilt]; + pDev = darwinTabletCurrent; + */ + + DarwinSendProximityEvents([e isEnteringProximity] ? ProximityIn : ProximityOut, + location.x, location.y); + } + + if ([e type] == NSTabletPoint || [e subtype] == NSTabletPointEventSubtype) { + pressure = [e pressure]; + tilt = [e tilt]; + + pDev = darwinTabletCurrent; + } + + if(!XQuartzServerVisible && noTestExtensions) { +#if defined(XPLUGIN_VERSION) && XPLUGIN_VERSION > 0 +/* Older libXplugin (Tiger/"Stock" Leopard) aren't thread safe, so we can't call xp_find_window from the Appkit thread */ + xp_window_id wid = 0; + xp_error e; + + /* Sigh. Need to check that we're really over one of + * our windows. (We need to receive pointer events while + * not in the foreground, but we don't want to receive them + * when another window is over us or we might show a tooltip) + */ + + e = xp_find_window(location.x, location.y, 0, &wid); + + if (e != XP_Success || (e == XP_Success && wid == 0)) +#endif + { + bgMouseLocation = location; + bgMouseLocationUpdated = TRUE; + return; + } + } + + if(bgMouseLocationUpdated) { + if(!(ev_type == MotionNotify && ev_button == 0)) { + DarwinSendPointerEvents(pDev, MotionNotify, 0, location.x, + location.y, pressure, tilt.x, tilt.y); + } + bgMouseLocationUpdated = FALSE; + } + + DarwinSendPointerEvents(pDev, ev_type, ev_button, location.x, location.y, + pressure, tilt.x, tilt.y); + + break; + + case NSTabletProximity: + switch([e pointingDeviceType]) { + case NSEraserPointingDevice: + darwinTabletCurrent=darwinTabletEraser; + break; + case NSPenPointingDevice: + darwinTabletCurrent=darwinTabletStylus; + break; + case NSCursorPointingDevice: + case NSUnknownPointingDevice: + default: + darwinTabletCurrent=darwinTabletCursor; + break; + } + + DarwinSendProximityEvents([e isEnteringProximity] ? ProximityIn : ProximityOut, + location.x, location.y); + break; + + case NSScrollWheel: +#if !defined(XPLUGIN_VERSION) || XPLUGIN_VERSION == 0 + /* If we're in the background, we need to send a MotionNotify event + * first, since we aren't getting them on background mouse motion + */ + if(!XQuartzServerVisible && noTestExtensions) { + bgMouseLocationUpdated = FALSE; + DarwinSendPointerEvents(darwinPointer, MotionNotify, 0, location.x, + location.y, pressure, tilt.x, tilt.y); + } +#endif + DarwinSendScrollEvents([e deltaX], [e deltaY], location.x, location.y, + pressure, tilt.x, tilt.y); + break; + + case NSKeyDown: case NSKeyUp: + { + /* XKB clobbers our keymap at startup, so we need to force it on the first keypress. + * TODO: Make this less of a kludge. + */ + static int force_resync_keymap = YES; + if(force_resync_keymap) { + DarwinSendDDXEvent(kXquartzReloadKeymap, 0); + force_resync_keymap = NO; + } + } + + if(darwinSyncKeymap) { +#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050 + TISInputSourceRef key_layout = TISCopyCurrentKeyboardLayoutInputSource(); + TISInputSourceRef clear; + if (CFEqual(key_layout, last_key_layout)) { + CFRelease(key_layout); + } else { + /* Swap/free thread-safely */ + clear = last_key_layout; + last_key_layout = key_layout; + CFRelease(clear); +#else + KeyboardLayoutRef key_layout; + KLGetCurrentKeyboardLayout(&key_layout); + if(key_layout != last_key_layout) { + last_key_layout = key_layout; +#endif + /* Update keyInfo */ + if (!QuartsResyncKeymap(TRUE)) { + fprintf(stderr, "sendX11NSEvent: Could not build a valid keymap.\n"); + } + } + } + + /* Avoid stuck keys on context switch */ + if(keyState[[e keyCode]] == [e type]) + return; + keyState[[e keyCode]] = [e type]; + + DarwinSendKeyboardEvents(([e type] == NSKeyDown) ? KeyPress : KeyRelease, [e keyCode]); + break; + + default: break; /* for gcc */ + } +} +@end diff --git a/xorg-server/hw/xquartz/X11Controller.h b/xorg-server/hw/xquartz/X11Controller.h index 65a09b8d5..9edaacdd5 100644 --- a/xorg-server/hw/xquartz/X11Controller.h +++ b/xorg-server/hw/xquartz/X11Controller.h @@ -65,7 +65,6 @@ typedef unsigned int NSUInteger; IBOutlet NSButton *fake_buttons; IBOutlet NSButton *enable_fullscreen; IBOutlet NSButton *enable_fullscreen_menu; - IBOutlet NSButton *use_sysbeep; IBOutlet NSButton *enable_keyequivs; IBOutlet NSButton *sync_keymap; IBOutlet NSButton *option_sends_alt; diff --git a/xorg-server/hw/xquartz/X11Controller.m b/xorg-server/hw/xquartz/X11Controller.m index 5502999e3..2edfb185e 100644 --- a/xorg-server/hw/xquartz/X11Controller.m +++ b/xorg-server/hw/xquartz/X11Controller.m @@ -1,844 +1,840 @@ -/* X11Controller.m -- connect the IB ui, also the NSApp delegate - - Copyright (c) 2002-2008 Apple Inc. All rights reserved. - - Permission is hereby granted, free of charge, to any person - obtaining a copy of this software and associated documentation files - (the "Software"), to deal in the Software without restriction, - including without limitation the rights to use, copy, modify, merge, - publish, distribute, sublicense, and/or sell copies of the Software, - and to permit persons to whom the Software is furnished to do so, - subject to the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT - HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name(s) of the above - copyright holders shall not be used in advertising or otherwise to - promote the sale, use or other dealings in this Software without - prior written authorization. */ - -#include "sanitizedCarbon.h" -#include - -#ifdef HAVE_DIX_CONFIG_H -#include -#endif - -#include "quartzCommon.h" - -#import "X11Controller.h" -#import "X11Application.h" - -#include "opaque.h" -#include "darwin.h" -#include "darwinEvents.h" -#include "quartz.h" -#include "quartzKeyboard.h" -#include -#include "applewmExt.h" - -#include -#include -#include -#include -#include - -@implementation X11Controller - -- (void) awakeFromNib -{ - X11Application *xapp = NSApp; - NSArray *array; - - /* Point X11Application at ourself. */ - [xapp set_controller:self]; - - array = [xapp prefs_get_array:@PREFS_APPSMENU]; - if (array != nil) - { - int count; - - /* convert from [TITLE1 COMMAND1 TITLE2 COMMAND2 ...] - to [[TITLE1 COMMAND1] [TITLE2 COMMAND2] ...] format. */ - - count = [array count]; - if (count > 0 - && ![[array objectAtIndex:0] isKindOfClass:[NSArray class]]) - { - int i; - NSMutableArray *copy, *sub; - - copy = [NSMutableArray arrayWithCapacity:(count / 2)]; - - for (i = 0; i < count / 2; i++) - { - sub = [[NSMutableArray alloc] initWithCapacity:3]; - [sub addObject:[array objectAtIndex:i*2]]; - [sub addObject:[array objectAtIndex:i*2+1]]; - [sub addObject:@""]; - [copy addObject:sub]; - [sub release]; - } - - array = copy; - } - - [self set_apps_menu:array]; - } - - [[NSNotificationCenter defaultCenter] - addObserver: self - selector: @selector(apps_table_done:) - name: NSWindowWillCloseNotification - object: [apps_table window]]; - - // Setup data about our Windows menu - if(window_separator) { - [[window_separator menu] removeItem:window_separator]; - window_separator = nil; - } - - windows_menu_start = [[X11App windowsMenu] numberOfItems]; -} - -- (void) item_selected:sender -{ - [NSApp activateIgnoringOtherApps:YES]; - - DarwinSendDDXEvent(kXquartzControllerNotify, 2, - AppleWMWindowMenuItem, [sender tag]); -} - -- (void) remove_window_menu -{ - NSMenu *menu; - int count, i; - - /* Work backwards so we don't mess up the indices */ - menu = [X11App windowsMenu]; - count = [menu numberOfItems]; - for (i = count - 1; i >= windows_menu_start; i--) - [menu removeItemAtIndex:i]; - - count = [dock_menu indexOfItem:dock_window_separator]; - for (i = 0; i < count; i++) - [dock_menu removeItemAtIndex:0]; -} - -- (void) install_window_menu:(NSArray *)list -{ - NSMenu *menu; - NSMenuItem *item; - int first, count, i; - - menu = [X11App windowsMenu]; - first = windows_menu_start + 1; - count = [list count]; - - // Push a Separator - if(count) { - [menu addItem:[NSMenuItem separatorItem]]; - } - - for (i = 0; i < count; i++) - { - NSString *name, *shortcut; - - name = [[list objectAtIndex:i] objectAtIndex:0]; - shortcut = [[list objectAtIndex:i] objectAtIndex:1]; - - if(windowItemModMask == 0 || windowItemModMask == -1) - shortcut = @""; - - item = (NSMenuItem *) [menu addItemWithTitle:name action:@selector - (item_selected:) keyEquivalent:shortcut]; - [item setKeyEquivalentModifierMask:(NSUInteger) windowItemModMask]; - [item setTarget:self]; - [item setTag:i]; - [item setEnabled:YES]; - - item = (NSMenuItem *) [dock_menu insertItemWithTitle:name - action:@selector - (item_selected:) keyEquivalent:shortcut - atIndex:i]; - [item setKeyEquivalentModifierMask:(NSUInteger) windowItemModMask]; - [item setTarget:self]; - [item setTag:i]; - [item setEnabled:YES]; - } - - if (checked_window_item >= 0 && checked_window_item < count) - { - item = (NSMenuItem *) [menu itemAtIndex:first + checked_window_item]; - [item setState:NSOnState]; - item = (NSMenuItem *) [dock_menu itemAtIndex:checked_window_item]; - [item setState:NSOnState]; - } -} - -- (void) remove_apps_menu -{ - NSMenu *menu; - NSMenuItem *item; - int i; - - if (apps == nil || apps_separator == nil) return; - - menu = [apps_separator menu]; - - if (menu != nil) - { - for (i = [menu numberOfItems] - 1; i >= 0; i--) - { - item = (NSMenuItem *) [menu itemAtIndex:i]; - if ([item tag] != 0) - [menu removeItemAtIndex:i]; - } - } - - if (dock_apps_menu != nil) - { - for (i = [dock_apps_menu numberOfItems] - 1; i >= 0; i--) - { - item = (NSMenuItem *) [dock_apps_menu itemAtIndex:i]; - if ([item tag] != 0) - [dock_apps_menu removeItemAtIndex:i]; - } - } - - [apps release]; - apps = nil; -} - -- (void) prepend_apps_item:(NSArray *)list index:(int)i menu:(NSMenu *)menu -{ - NSString *title, *shortcut = @""; - NSArray *group; - NSMenuItem *item; - - group = [list objectAtIndex:i]; - title = [group objectAtIndex:0]; - if ([group count] >= 3) - shortcut = [group objectAtIndex:2]; - - if ([title length] != 0) - { - item = (NSMenuItem *) [menu insertItemWithTitle:title - action:@selector (app_selected:) - keyEquivalent:shortcut atIndex:0]; - [item setTarget:self]; - [item setEnabled:YES]; - } - else - { - item = (NSMenuItem *) [NSMenuItem separatorItem]; - [menu insertItem:item atIndex:0]; - } - - [item setTag:i+1]; /* can't be zero, so add one */ -} - -- (void) install_apps_menu:(NSArray *)list -{ - NSMenu *menu; - int i, count; - - count = [list count]; - - if (count == 0 || apps_separator == nil) return; - - menu = [apps_separator menu]; - - for (i = count - 1; i >= 0; i--) - { - if (menu != nil) - [self prepend_apps_item:list index:i menu:menu]; - if (dock_apps_menu != nil) - [self prepend_apps_item:list index:i menu:dock_apps_menu]; - } - - apps = [list retain]; -} - -- (void) set_window_menu:(NSArray *)list -{ - [self remove_window_menu]; - [self install_window_menu:list]; - - DarwinSendDDXEvent(kXquartzControllerNotify, 1, - AppleWMWindowMenuNotify); -} - -- (void) set_window_menu_check:(NSNumber *)nn -{ - NSMenu *menu; - NSMenuItem *item; - int first, count; - int n = [nn intValue]; - - menu = [X11App windowsMenu]; - first = windows_menu_start + 1; - count = [menu numberOfItems] - first; - - if (checked_window_item >= 0 && checked_window_item < count) - { - item = (NSMenuItem *) [menu itemAtIndex:first + checked_window_item]; - [item setState:NSOffState]; - item = (NSMenuItem *) [dock_menu itemAtIndex:checked_window_item]; - [item setState:NSOffState]; - } - if (n >= 0 && n < count) - { - item = (NSMenuItem *) [menu itemAtIndex:first + n]; - [item setState:NSOnState]; - item = (NSMenuItem *) [dock_menu itemAtIndex:n]; - [item setState:NSOnState]; - } - checked_window_item = n; -} - -- (void) set_apps_menu:(NSArray *)list -{ - [self remove_apps_menu]; - [self install_apps_menu:list]; -} - -#ifdef XQUARTZ_SPARKLE -- (void) setup_sparkle { - if(check_for_updates_item) - return; // already did it... - - NSMenu *menu = [x11_about_item menu]; - - check_for_updates_item = [menu insertItemWithTitle:NSLocalizedString(@"Check for X11 Updates...", @"Check for X11 Updates...") - action:@selector (checkForUpdates:) - keyEquivalent:@"" - atIndex:1]; - [check_for_updates_item setTarget:[SUUpdater sharedUpdater]]; - [check_for_updates_item setEnabled:YES]; - - // Set X11Controller as the delegate for the updater. - [[SUUpdater sharedUpdater] setDelegate:self]; -} - -// Sent immediately before installing the specified update. -- (void)updater:(SUUpdater *)updater willInstallUpdate:(SUAppcastItem *)update { - //[self set_can_quit:YES]; -} - -#endif - -- (void) launch_client:(NSString *)filename -{ - int child1, child2 = 0; - int status; - const char *newargv[4]; - char buf[128]; - char *s; - - newargv[0] = [X11App prefs_get_string:@PREFS_LOGIN_SHELL default:"/bin/sh"]; - newargv[1] = "-c"; - newargv[2] = [filename UTF8String]; - newargv[3] = NULL; - - s = getenv("DISPLAY"); - if (s == NULL || s[0] == 0) { - snprintf(buf, sizeof(buf), ":%s", display); - setenv("DISPLAY", buf, TRUE); - } - - /* Do the fork-twice trick to avoid having to reap zombies */ - child1 = fork(); - switch (child1) { - case -1: /* error */ - break; - - case 0: /* child1 */ - child2 = fork(); - - switch (child2) { - int max_files, i; - - case -1: /* error */ - _exit(1); - - case 0: /* child2 */ - /* close all open files except for standard streams */ - max_files = sysconf(_SC_OPEN_MAX); - for(i = 3; i < max_files; i++) - close(i); - - /* ensure stdin is on /dev/null */ - close(0); - open("/dev/null", O_RDONLY); - - execvp(newargv[0], (char **const) newargv); - _exit(2); - - default: /* parent (child1) */ - _exit(0); - } - break; - - default: /* parent */ - waitpid(child1, &status, 0); - } -} - -- (void) app_selected:sender -{ - int tag; - NSString *item; - - tag = [sender tag] - 1; - if (apps == nil || tag < 0 || tag >= [apps count]) - return; - - item = [[apps objectAtIndex:tag] objectAtIndex:1]; - - [self launch_client:item]; -} - -- (IBAction) apps_table_show:sender -{ - NSArray *columns; - NSMutableArray *oldapps = nil; - - if (table_apps != nil) - oldapps = table_apps; - - table_apps = [[NSMutableArray alloc] initWithCapacity:1]; - if(apps != nil) - [table_apps addObjectsFromArray:apps]; - - columns = [apps_table tableColumns]; - [[columns objectAtIndex:0] setIdentifier:@"0"]; - [[columns objectAtIndex:1] setIdentifier:@"1"]; - [[columns objectAtIndex:2] setIdentifier:@"2"]; - - [apps_table setDataSource:self]; - [apps_table selectRowIndexes:[NSIndexSet indexSetWithIndex:0] byExtendingSelection:NO]; - - [[apps_table window] makeKeyAndOrderFront:sender]; - [apps_table reloadData]; - if(oldapps != nil) - [oldapps release]; -} - -- (IBAction) apps_table_done:sender -{ - [apps_table deselectAll:sender]; /* flush edits? */ - - [self remove_apps_menu]; - [self install_apps_menu:table_apps]; - - [NSApp prefs_set_array:@PREFS_APPSMENU value:table_apps]; - [NSApp prefs_synchronize]; - - [[apps_table window] orderOut:sender]; - - [table_apps release]; - table_apps = nil; -} - -- (IBAction) apps_table_new:sender -{ - NSMutableArray *item; - - int row = [apps_table selectedRow], i; - - if (row < 0) row = 0; - else row = row + 1; - - i = row; - if (i > [table_apps count]) - return; /* avoid exceptions */ - - [apps_table deselectAll:sender]; - - item = [[NSMutableArray alloc] initWithCapacity:3]; - [item addObject:@""]; - [item addObject:@""]; - [item addObject:@""]; - - [table_apps insertObject:item atIndex:i]; - [item release]; - - [apps_table reloadData]; - [apps_table selectRowIndexes:[NSIndexSet indexSetWithIndex:row] byExtendingSelection:NO]; -} - -- (IBAction) apps_table_duplicate:sender -{ - int row = [apps_table selectedRow], i; - NSObject *item; - - if (row < 0) { - [self apps_table_new:sender]; - return; - } - - i = row; - if (i > [table_apps count] - 1) return; /* avoid exceptions */ - - [apps_table deselectAll:sender]; - - item = [[table_apps objectAtIndex:i] mutableCopy]; - [table_apps insertObject:item atIndex:i]; - [item release]; - - [apps_table reloadData]; - [apps_table selectRowIndexes:[NSIndexSet indexSetWithIndex:row+1] byExtendingSelection:NO]; -} - -- (IBAction) apps_table_delete:sender -{ - int row = [apps_table selectedRow]; - - if (row >= 0) - { - int i = row; - - if (i > [table_apps count] - 1) return; /* avoid exceptions */ - - [apps_table deselectAll:sender]; - - [table_apps removeObjectAtIndex:i]; - } - - [apps_table reloadData]; - - row = MIN (row, [table_apps count] - 1); - if (row >= 0) - [apps_table selectRowIndexes:[NSIndexSet indexSetWithIndex:row] byExtendingSelection:NO]; -} - -- (NSInteger) numberOfRowsInTableView:(NSTableView *)tableView -{ - if (table_apps == nil) return 0; - - return [table_apps count]; -} - -- (id) tableView:(NSTableView *)tableView -objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row -{ - NSArray *item; - int col; - - if (table_apps == nil) return nil; - - col = [[tableColumn identifier] intValue]; - - item = [table_apps objectAtIndex:row]; - if ([item count] > col) - return [item objectAtIndex:col]; - else - return @""; -} - -- (void) tableView:(NSTableView *)tableView setObjectValue:(id)object - forTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row -{ - NSMutableArray *item; - int col; - - if (table_apps == nil) return; - - col = [[tableColumn identifier] intValue]; - - item = [table_apps objectAtIndex:row]; - [item replaceObjectAtIndex:col withObject:object]; -} - -- (void) hide_window:sender -{ - if ([X11App x_active]) - DarwinSendDDXEvent(kXquartzControllerNotify, 1, AppleWMHideWindow); - else - NSBeep (); /* FIXME: something here */ -} - -- (IBAction)bring_to_front:sender -{ - DarwinSendDDXEvent(kXquartzControllerNotify, 1, AppleWMBringAllToFront); -} - -- (IBAction)close_window:sender -{ - if ([X11App x_active]) - DarwinSendDDXEvent(kXquartzControllerNotify, 1, AppleWMCloseWindow); - else - [[NSApp keyWindow] performClose:sender]; -} - -- (IBAction)minimize_window:sender -{ - if ([X11App x_active]) - DarwinSendDDXEvent(kXquartzControllerNotify, 1, AppleWMMinimizeWindow); - else - [[NSApp keyWindow] performMiniaturize:sender]; -} - -- (IBAction)zoom_window:sender -{ - if ([X11App x_active]) - DarwinSendDDXEvent(kXquartzControllerNotify, 1, AppleWMZoomWindow); - else - [[NSApp keyWindow] performZoom:sender]; -} - -- (IBAction) next_window:sender -{ - DarwinSendDDXEvent(kXquartzControllerNotify, 1, AppleWMNextWindow); -} - -- (IBAction) previous_window:sender -{ - DarwinSendDDXEvent(kXquartzControllerNotify, 1, AppleWMPreviousWindow); -} - -- (IBAction) enable_fullscreen_changed:sender { - XQuartzRootlessDefault = ![enable_fullscreen intValue]; - - [enable_fullscreen_menu setEnabled:!XQuartzRootlessDefault]; - - DarwinSendDDXEvent(kXquartzSetRootless, 1, XQuartzRootlessDefault); - - [NSApp prefs_set_boolean:@PREFS_ROOTLESS value:XQuartzRootlessDefault]; - [NSApp prefs_synchronize]; -} - -- (IBAction) toggle_fullscreen:sender -{ - DarwinSendDDXEvent(kXquartzToggleFullscreen, 0); -} - -- (void) set_can_quit:(OSX_BOOL)state -{ - can_quit = state; -} - -- (IBAction)prefs_changed:sender -{ - if(!sender) - return; - - if(sender == fake_buttons) { - darwinFakeButtons = [fake_buttons intValue]; - [NSApp prefs_set_boolean:@PREFS_FAKEBUTTONS value:darwinFakeButtons]; - } else if(sender == use_sysbeep) { - XQuartzUseSysBeep = [use_sysbeep intValue]; - [NSApp prefs_set_boolean:@PREFS_SYSBEEP value:XQuartzUseSysBeep]; - } else if(sender == enable_keyequivs) { - XQuartzEnableKeyEquivalents = [enable_keyequivs intValue]; - [NSApp prefs_set_boolean:@PREFS_KEYEQUIVS value:XQuartzEnableKeyEquivalents]; - } else if(sender == sync_keymap) { - darwinSyncKeymap = [sync_keymap intValue]; - [NSApp prefs_set_boolean:@PREFS_SYNC_KEYMAP value:darwinSyncKeymap]; - } else if(sender == enable_fullscreen_menu) { - XQuartzFullscreenMenu = [enable_fullscreen_menu intValue]; - [NSApp prefs_set_boolean:@PREFS_FULLSCREEN_MENU value:XQuartzFullscreenMenu]; - } else if(sender == option_sends_alt) { - BOOL prev_opt_sends_alt = XQuartzOptionSendsAlt; - - XQuartzOptionSendsAlt = [option_sends_alt intValue]; - [NSApp prefs_set_boolean:@PREFS_OPTION_SENDS_ALT value:XQuartzOptionSendsAlt]; - - if(prev_opt_sends_alt != XQuartzOptionSendsAlt) - QuartsResyncKeymap(TRUE); - } else if(sender == click_through) { - [NSApp prefs_set_boolean:@PREFS_CLICK_THROUGH value:[click_through intValue]]; - } else if(sender == focus_follows_mouse) { - [NSApp prefs_set_boolean:@PREFS_FFM value:[focus_follows_mouse intValue]]; - } else if(sender == focus_on_new_window) { - [NSApp prefs_set_boolean:@PREFS_FOCUS_ON_NEW_WINDOW value:[focus_on_new_window intValue]]; - } else if(sender == enable_auth) { - [NSApp prefs_set_boolean:@PREFS_NO_AUTH value:![enable_auth intValue]]; - } else if(sender == enable_tcp) { - [NSApp prefs_set_boolean:@PREFS_NO_TCP value:![enable_tcp intValue]]; - } else if(sender == depth) { - [NSApp prefs_set_integer:@PREFS_DEPTH value:[depth selectedTag]]; - } else if(sender == sync_pasteboard) { - BOOL pbproxy_active = [sync_pasteboard intValue]; - [NSApp prefs_set_boolean:@PREFS_SYNC_PB value:pbproxy_active]; - - [sync_pasteboard_to_clipboard setEnabled:pbproxy_active]; - [sync_pasteboard_to_primary setEnabled:pbproxy_active]; - [sync_clipboard_to_pasteboard setEnabled:pbproxy_active]; - [sync_primary_immediately setEnabled:pbproxy_active]; - - // setEnabled doesn't do this... - [sync_text1 setTextColor:pbproxy_active ? [NSColor controlTextColor] : [NSColor disabledControlTextColor]]; - [sync_text2 setTextColor:pbproxy_active ? [NSColor controlTextColor] : [NSColor disabledControlTextColor]]; - } else if(sender == sync_pasteboard_to_clipboard) { - [NSApp prefs_set_boolean:@PREFS_SYNC_PB_TO_CLIPBOARD value:[sync_pasteboard_to_clipboard intValue]]; - } else if(sender == sync_pasteboard_to_primary) { - [NSApp prefs_set_boolean:@PREFS_SYNC_PB_TO_PRIMARY value:[sync_pasteboard_to_primary intValue]]; - } else if(sender == sync_clipboard_to_pasteboard) { - [NSApp prefs_set_boolean:@PREFS_SYNC_CLIPBOARD_TO_PB value:[sync_clipboard_to_pasteboard intValue]]; - } else if(sender == sync_primary_immediately) { - [NSApp prefs_set_boolean:@PREFS_SYNC_PRIMARY_ON_SELECT value:[sync_primary_immediately intValue]]; - } - - [NSApp prefs_synchronize]; - - DarwinSendDDXEvent(kXquartzReloadPreferences, 0); -} - -- (IBAction) prefs_show:sender -{ - BOOL pbproxy_active = [NSApp prefs_get_boolean:@PREFS_SYNC_PB default:YES]; - - [fake_buttons setIntValue:darwinFakeButtons]; - [use_sysbeep setIntValue:XQuartzUseSysBeep]; - [enable_keyequivs setIntValue:XQuartzEnableKeyEquivalents]; - [sync_keymap setIntValue:darwinSyncKeymap]; - [option_sends_alt setIntValue:XQuartzOptionSendsAlt]; - [click_through setIntValue:[NSApp prefs_get_boolean:@PREFS_CLICK_THROUGH default:NO]]; - [focus_follows_mouse setIntValue:[NSApp prefs_get_boolean:@PREFS_FFM default:NO]]; - [focus_on_new_window setIntValue:[NSApp prefs_get_boolean:@PREFS_FOCUS_ON_NEW_WINDOW default:YES]]; - - [enable_auth setIntValue:![NSApp prefs_get_boolean:@PREFS_NO_AUTH default:NO]]; - [enable_tcp setIntValue:![NSApp prefs_get_boolean:@PREFS_NO_TCP default:NO]]; - - [depth selectItemAtIndex:[depth indexOfItemWithTag:[NSApp prefs_get_integer:@PREFS_DEPTH default:-1]]]; - - [sync_pasteboard setIntValue:pbproxy_active]; - [sync_pasteboard_to_clipboard setIntValue:[NSApp prefs_get_boolean:@PREFS_SYNC_PB_TO_CLIPBOARD default:YES]]; - [sync_pasteboard_to_primary setIntValue:[NSApp prefs_get_boolean:@PREFS_SYNC_PB_TO_PRIMARY default:YES]]; - [sync_clipboard_to_pasteboard setIntValue:[NSApp prefs_get_boolean:@PREFS_SYNC_CLIPBOARD_TO_PB default:YES]]; - [sync_primary_immediately setIntValue:[NSApp prefs_get_boolean:@PREFS_SYNC_PRIMARY_ON_SELECT default:NO]]; - - [sync_pasteboard_to_clipboard setEnabled:pbproxy_active]; - [sync_pasteboard_to_primary setEnabled:pbproxy_active]; - [sync_clipboard_to_pasteboard setEnabled:pbproxy_active]; - [sync_primary_immediately setEnabled:pbproxy_active]; - - // setEnabled doesn't do this... - [sync_text1 setTextColor:pbproxy_active ? [NSColor controlTextColor] : [NSColor disabledControlTextColor]]; - [sync_text2 setTextColor:pbproxy_active ? [NSColor controlTextColor] : [NSColor disabledControlTextColor]]; - - [enable_fullscreen setIntValue:!XQuartzRootlessDefault]; - [enable_fullscreen_menu setEnabled:!XQuartzRootlessDefault]; - [enable_fullscreen_menu setIntValue:XQuartzFullscreenMenu]; - - [prefs_panel makeKeyAndOrderFront:sender]; -} - -- (IBAction) quit:sender { - DarwinSendDDXEvent(kXquartzQuit, 0); -} - -- (IBAction) x11_help:sender { -#if MAC_OS_X_VERSION_MIN_REQUIRED < 1060 - AHLookupAnchor((CFStringRef)NSLocalizedString(@"Mac Help", no comment), CFSTR("mchlp2276")); -#else - AHLookupAnchor(CFSTR("com.apple.machelp"), CFSTR("mchlp2276")); -#endif -} - -- (OSX_BOOL) validateMenuItem:(NSMenuItem *)item { - NSMenu *menu = [item menu]; - - if (item == toggle_fullscreen_item) - return !XQuartzIsRootless; - else if (menu == [X11App windowsMenu] || menu == dock_menu - || (menu == [x11_about_item menu] && [item tag] == 42)) - return (AppleWMSelectedEvents () & AppleWMControllerNotifyMask) != 0; - else - return TRUE; -} - -- (void) applicationDidHide:(NSNotification *)notify -{ - DarwinSendDDXEvent(kXquartzControllerNotify, 1, AppleWMHideAll); -} - -- (void) applicationDidUnhide:(NSNotification *)notify -{ - DarwinSendDDXEvent(kXquartzControllerNotify, 1, AppleWMShowAll); -} - -- (NSApplicationTerminateReply) applicationShouldTerminate:sender { - NSString *msg; - NSString *title; - - if (can_quit || [X11App prefs_get_boolean:@PREFS_NO_QUIT_ALERT default:NO]) - return NSTerminateNow; - - /* Make sure we're frontmost. */ - [NSApp activateIgnoringOtherApps:YES]; - - title = NSLocalizedString(@"Do you really want to quit X11?", @"Dialog title when quitting"); - msg = NSLocalizedString(@"Any open X11 applications will stop immediately, and you will lose any unsaved changes.", @"Dialog when quitting"); - - /* FIXME: safe to run the alert in here? Or should we return Later - * and then run the alert on a timer? It seems to work here, so.. - */ - - return (NSRunAlertPanel (title, msg, NSLocalizedString (@"Quit", @""), - NSLocalizedString (@"Cancel", @""), nil) - == NSAlertDefaultReturn) ? NSTerminateNow : NSTerminateCancel; -} - -- (void) applicationWillTerminate:(NSNotification *)aNotification -{ - unsigned remain; - [X11App prefs_synchronize]; - - /* shutdown the X server, it will exit () for us. */ - DarwinSendDDXEvent(kXquartzQuit, 0); - - /* In case it doesn't, exit anyway after a while. */ - remain = 10000000; - while((remain = usleep(remain)) > 0); - - exit (1); -} - -- (void) server_ready -{ - x_list *node; - - finished_launching = YES; - - for (node = pending_apps; node != NULL; node = node->next) - { - NSString *filename = node->data; - [self launch_client:filename]; - [filename release]; - } - - x_list_free (pending_apps); - pending_apps = NULL; -} - -- (OSX_BOOL) application:(NSApplication *)app openFile:(NSString *)filename -{ - const char *name = [filename UTF8String]; - - if (finished_launching) - [self launch_client:filename]; - else if (name[0] != ':') /* ignore display names */ - pending_apps = x_list_prepend (pending_apps, [filename retain]); - - /* FIXME: report failures. */ - return YES; -} - -@end - -void X11ControllerMain(int argc, char **argv, char **envp) { - X11ApplicationMain (argc, argv, envp); -} +/* X11Controller.m -- connect the IB ui, also the NSApp delegate + + Copyright (c) 2002-2008 Apple Inc. All rights reserved. + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation files + (the "Software"), to deal in the Software without restriction, + including without limitation the rights to use, copy, modify, merge, + publish, distribute, sublicense, and/or sell copies of the Software, + and to permit persons to whom the Software is furnished to do so, + subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT + HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the name(s) of the above + copyright holders shall not be used in advertising or otherwise to + promote the sale, use or other dealings in this Software without + prior written authorization. */ + +#include "sanitizedCarbon.h" +#include + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include "quartzCommon.h" + +#import "X11Controller.h" +#import "X11Application.h" + +#include "opaque.h" +#include "darwin.h" +#include "darwinEvents.h" +#include "quartz.h" +#include "quartzKeyboard.h" +#include +#include "applewmExt.h" + +#include +#include +#include +#include +#include + +@implementation X11Controller + +- (void) awakeFromNib +{ + X11Application *xapp = NSApp; + NSArray *array; + + /* Point X11Application at ourself. */ + [xapp set_controller:self]; + + array = [xapp prefs_get_array:@PREFS_APPSMENU]; + if (array != nil) + { + int count; + + /* convert from [TITLE1 COMMAND1 TITLE2 COMMAND2 ...] + to [[TITLE1 COMMAND1] [TITLE2 COMMAND2] ...] format. */ + + count = [array count]; + if (count > 0 + && ![[array objectAtIndex:0] isKindOfClass:[NSArray class]]) + { + int i; + NSMutableArray *copy, *sub; + + copy = [NSMutableArray arrayWithCapacity:(count / 2)]; + + for (i = 0; i < count / 2; i++) + { + sub = [[NSMutableArray alloc] initWithCapacity:3]; + [sub addObject:[array objectAtIndex:i*2]]; + [sub addObject:[array objectAtIndex:i*2+1]]; + [sub addObject:@""]; + [copy addObject:sub]; + [sub release]; + } + + array = copy; + } + + [self set_apps_menu:array]; + } + + [[NSNotificationCenter defaultCenter] + addObserver: self + selector: @selector(apps_table_done:) + name: NSWindowWillCloseNotification + object: [apps_table window]]; + + // Setup data about our Windows menu + if(window_separator) { + [[window_separator menu] removeItem:window_separator]; + window_separator = nil; + } + + windows_menu_start = [[X11App windowsMenu] numberOfItems]; +} + +- (void) item_selected:sender +{ + [NSApp activateIgnoringOtherApps:YES]; + + DarwinSendDDXEvent(kXquartzControllerNotify, 2, + AppleWMWindowMenuItem, [sender tag]); +} + +- (void) remove_window_menu +{ + NSMenu *menu; + int count, i; + + /* Work backwards so we don't mess up the indices */ + menu = [X11App windowsMenu]; + count = [menu numberOfItems]; + for (i = count - 1; i >= windows_menu_start; i--) + [menu removeItemAtIndex:i]; + + count = [dock_menu indexOfItem:dock_window_separator]; + for (i = 0; i < count; i++) + [dock_menu removeItemAtIndex:0]; +} + +- (void) install_window_menu:(NSArray *)list +{ + NSMenu *menu; + NSMenuItem *item; + int first, count, i; + + menu = [X11App windowsMenu]; + first = windows_menu_start + 1; + count = [list count]; + + // Push a Separator + if(count) { + [menu addItem:[NSMenuItem separatorItem]]; + } + + for (i = 0; i < count; i++) + { + NSString *name, *shortcut; + + name = [[list objectAtIndex:i] objectAtIndex:0]; + shortcut = [[list objectAtIndex:i] objectAtIndex:1]; + + if(windowItemModMask == 0 || windowItemModMask == -1) + shortcut = @""; + + item = (NSMenuItem *) [menu addItemWithTitle:name action:@selector + (item_selected:) keyEquivalent:shortcut]; + [item setKeyEquivalentModifierMask:(NSUInteger) windowItemModMask]; + [item setTarget:self]; + [item setTag:i]; + [item setEnabled:YES]; + + item = (NSMenuItem *) [dock_menu insertItemWithTitle:name + action:@selector + (item_selected:) keyEquivalent:shortcut + atIndex:i]; + [item setKeyEquivalentModifierMask:(NSUInteger) windowItemModMask]; + [item setTarget:self]; + [item setTag:i]; + [item setEnabled:YES]; + } + + if (checked_window_item >= 0 && checked_window_item < count) + { + item = (NSMenuItem *) [menu itemAtIndex:first + checked_window_item]; + [item setState:NSOnState]; + item = (NSMenuItem *) [dock_menu itemAtIndex:checked_window_item]; + [item setState:NSOnState]; + } +} + +- (void) remove_apps_menu +{ + NSMenu *menu; + NSMenuItem *item; + int i; + + if (apps == nil || apps_separator == nil) return; + + menu = [apps_separator menu]; + + if (menu != nil) + { + for (i = [menu numberOfItems] - 1; i >= 0; i--) + { + item = (NSMenuItem *) [menu itemAtIndex:i]; + if ([item tag] != 0) + [menu removeItemAtIndex:i]; + } + } + + if (dock_apps_menu != nil) + { + for (i = [dock_apps_menu numberOfItems] - 1; i >= 0; i--) + { + item = (NSMenuItem *) [dock_apps_menu itemAtIndex:i]; + if ([item tag] != 0) + [dock_apps_menu removeItemAtIndex:i]; + } + } + + [apps release]; + apps = nil; +} + +- (void) prepend_apps_item:(NSArray *)list index:(int)i menu:(NSMenu *)menu +{ + NSString *title, *shortcut = @""; + NSArray *group; + NSMenuItem *item; + + group = [list objectAtIndex:i]; + title = [group objectAtIndex:0]; + if ([group count] >= 3) + shortcut = [group objectAtIndex:2]; + + if ([title length] != 0) + { + item = (NSMenuItem *) [menu insertItemWithTitle:title + action:@selector (app_selected:) + keyEquivalent:shortcut atIndex:0]; + [item setTarget:self]; + [item setEnabled:YES]; + } + else + { + item = (NSMenuItem *) [NSMenuItem separatorItem]; + [menu insertItem:item atIndex:0]; + } + + [item setTag:i+1]; /* can't be zero, so add one */ +} + +- (void) install_apps_menu:(NSArray *)list +{ + NSMenu *menu; + int i, count; + + count = [list count]; + + if (count == 0 || apps_separator == nil) return; + + menu = [apps_separator menu]; + + for (i = count - 1; i >= 0; i--) + { + if (menu != nil) + [self prepend_apps_item:list index:i menu:menu]; + if (dock_apps_menu != nil) + [self prepend_apps_item:list index:i menu:dock_apps_menu]; + } + + apps = [list retain]; +} + +- (void) set_window_menu:(NSArray *)list +{ + [self remove_window_menu]; + [self install_window_menu:list]; + + DarwinSendDDXEvent(kXquartzControllerNotify, 1, + AppleWMWindowMenuNotify); +} + +- (void) set_window_menu_check:(NSNumber *)nn +{ + NSMenu *menu; + NSMenuItem *item; + int first, count; + int n = [nn intValue]; + + menu = [X11App windowsMenu]; + first = windows_menu_start + 1; + count = [menu numberOfItems] - first; + + if (checked_window_item >= 0 && checked_window_item < count) + { + item = (NSMenuItem *) [menu itemAtIndex:first + checked_window_item]; + [item setState:NSOffState]; + item = (NSMenuItem *) [dock_menu itemAtIndex:checked_window_item]; + [item setState:NSOffState]; + } + if (n >= 0 && n < count) + { + item = (NSMenuItem *) [menu itemAtIndex:first + n]; + [item setState:NSOnState]; + item = (NSMenuItem *) [dock_menu itemAtIndex:n]; + [item setState:NSOnState]; + } + checked_window_item = n; +} + +- (void) set_apps_menu:(NSArray *)list +{ + [self remove_apps_menu]; + [self install_apps_menu:list]; +} + +#ifdef XQUARTZ_SPARKLE +- (void) setup_sparkle { + if(check_for_updates_item) + return; // already did it... + + NSMenu *menu = [x11_about_item menu]; + + check_for_updates_item = [menu insertItemWithTitle:NSLocalizedString(@"Check for X11 Updates...", @"Check for X11 Updates...") + action:@selector (checkForUpdates:) + keyEquivalent:@"" + atIndex:1]; + [check_for_updates_item setTarget:[SUUpdater sharedUpdater]]; + [check_for_updates_item setEnabled:YES]; + + // Set X11Controller as the delegate for the updater. + [[SUUpdater sharedUpdater] setDelegate:self]; +} + +// Sent immediately before installing the specified update. +- (void)updater:(SUUpdater *)updater willInstallUpdate:(SUAppcastItem *)update { + //[self set_can_quit:YES]; +} + +#endif + +- (void) launch_client:(NSString *)filename +{ + int child1, child2 = 0; + int status; + const char *newargv[4]; + char buf[128]; + char *s; + + newargv[0] = [X11App prefs_get_string:@PREFS_LOGIN_SHELL default:"/bin/sh"]; + newargv[1] = "-c"; + newargv[2] = [filename UTF8String]; + newargv[3] = NULL; + + s = getenv("DISPLAY"); + if (s == NULL || s[0] == 0) { + snprintf(buf, sizeof(buf), ":%s", display); + setenv("DISPLAY", buf, TRUE); + } + + /* Do the fork-twice trick to avoid having to reap zombies */ + child1 = fork(); + switch (child1) { + case -1: /* error */ + break; + + case 0: /* child1 */ + child2 = fork(); + + switch (child2) { + int max_files, i; + + case -1: /* error */ + _exit(1); + + case 0: /* child2 */ + /* close all open files except for standard streams */ + max_files = sysconf(_SC_OPEN_MAX); + for(i = 3; i < max_files; i++) + close(i); + + /* ensure stdin is on /dev/null */ + close(0); + open("/dev/null", O_RDONLY); + + execvp(newargv[0], (char **const) newargv); + _exit(2); + + default: /* parent (child1) */ + _exit(0); + } + break; + + default: /* parent */ + waitpid(child1, &status, 0); + } +} + +- (void) app_selected:sender +{ + int tag; + NSString *item; + + tag = [sender tag] - 1; + if (apps == nil || tag < 0 || tag >= [apps count]) + return; + + item = [[apps objectAtIndex:tag] objectAtIndex:1]; + + [self launch_client:item]; +} + +- (IBAction) apps_table_show:sender +{ + NSArray *columns; + NSMutableArray *oldapps = nil; + + if (table_apps != nil) + oldapps = table_apps; + + table_apps = [[NSMutableArray alloc] initWithCapacity:1]; + if(apps != nil) + [table_apps addObjectsFromArray:apps]; + + columns = [apps_table tableColumns]; + [[columns objectAtIndex:0] setIdentifier:@"0"]; + [[columns objectAtIndex:1] setIdentifier:@"1"]; + [[columns objectAtIndex:2] setIdentifier:@"2"]; + + [apps_table setDataSource:self]; + [apps_table selectRowIndexes:[NSIndexSet indexSetWithIndex:0] byExtendingSelection:NO]; + + [[apps_table window] makeKeyAndOrderFront:sender]; + [apps_table reloadData]; + if(oldapps != nil) + [oldapps release]; +} + +- (IBAction) apps_table_done:sender +{ + [apps_table deselectAll:sender]; /* flush edits? */ + + [self remove_apps_menu]; + [self install_apps_menu:table_apps]; + + [NSApp prefs_set_array:@PREFS_APPSMENU value:table_apps]; + [NSApp prefs_synchronize]; + + [[apps_table window] orderOut:sender]; + + [table_apps release]; + table_apps = nil; +} + +- (IBAction) apps_table_new:sender +{ + NSMutableArray *item; + + int row = [apps_table selectedRow], i; + + if (row < 0) row = 0; + else row = row + 1; + + i = row; + if (i > [table_apps count]) + return; /* avoid exceptions */ + + [apps_table deselectAll:sender]; + + item = [[NSMutableArray alloc] initWithCapacity:3]; + [item addObject:@""]; + [item addObject:@""]; + [item addObject:@""]; + + [table_apps insertObject:item atIndex:i]; + [item release]; + + [apps_table reloadData]; + [apps_table selectRowIndexes:[NSIndexSet indexSetWithIndex:row] byExtendingSelection:NO]; +} + +- (IBAction) apps_table_duplicate:sender +{ + int row = [apps_table selectedRow], i; + NSObject *item; + + if (row < 0) { + [self apps_table_new:sender]; + return; + } + + i = row; + if (i > [table_apps count] - 1) return; /* avoid exceptions */ + + [apps_table deselectAll:sender]; + + item = [[table_apps objectAtIndex:i] mutableCopy]; + [table_apps insertObject:item atIndex:i]; + [item release]; + + [apps_table reloadData]; + [apps_table selectRowIndexes:[NSIndexSet indexSetWithIndex:row+1] byExtendingSelection:NO]; +} + +- (IBAction) apps_table_delete:sender +{ + int row = [apps_table selectedRow]; + + if (row >= 0) + { + int i = row; + + if (i > [table_apps count] - 1) return; /* avoid exceptions */ + + [apps_table deselectAll:sender]; + + [table_apps removeObjectAtIndex:i]; + } + + [apps_table reloadData]; + + row = MIN (row, [table_apps count] - 1); + if (row >= 0) + [apps_table selectRowIndexes:[NSIndexSet indexSetWithIndex:row] byExtendingSelection:NO]; +} + +- (NSInteger) numberOfRowsInTableView:(NSTableView *)tableView +{ + if (table_apps == nil) return 0; + + return [table_apps count]; +} + +- (id) tableView:(NSTableView *)tableView +objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row +{ + NSArray *item; + int col; + + if (table_apps == nil) return nil; + + col = [[tableColumn identifier] intValue]; + + item = [table_apps objectAtIndex:row]; + if ([item count] > col) + return [item objectAtIndex:col]; + else + return @""; +} + +- (void) tableView:(NSTableView *)tableView setObjectValue:(id)object + forTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row +{ + NSMutableArray *item; + int col; + + if (table_apps == nil) return; + + col = [[tableColumn identifier] intValue]; + + item = [table_apps objectAtIndex:row]; + [item replaceObjectAtIndex:col withObject:object]; +} + +- (void) hide_window:sender +{ + if ([X11App x_active]) + DarwinSendDDXEvent(kXquartzControllerNotify, 1, AppleWMHideWindow); + else + NSBeep (); /* FIXME: something here */ +} + +- (IBAction)bring_to_front:sender +{ + DarwinSendDDXEvent(kXquartzControllerNotify, 1, AppleWMBringAllToFront); +} + +- (IBAction)close_window:sender +{ + if ([X11App x_active]) + DarwinSendDDXEvent(kXquartzControllerNotify, 1, AppleWMCloseWindow); + else + [[NSApp keyWindow] performClose:sender]; +} + +- (IBAction)minimize_window:sender +{ + if ([X11App x_active]) + DarwinSendDDXEvent(kXquartzControllerNotify, 1, AppleWMMinimizeWindow); + else + [[NSApp keyWindow] performMiniaturize:sender]; +} + +- (IBAction)zoom_window:sender +{ + if ([X11App x_active]) + DarwinSendDDXEvent(kXquartzControllerNotify, 1, AppleWMZoomWindow); + else + [[NSApp keyWindow] performZoom:sender]; +} + +- (IBAction) next_window:sender +{ + DarwinSendDDXEvent(kXquartzControllerNotify, 1, AppleWMNextWindow); +} + +- (IBAction) previous_window:sender +{ + DarwinSendDDXEvent(kXquartzControllerNotify, 1, AppleWMPreviousWindow); +} + +- (IBAction) enable_fullscreen_changed:sender { + XQuartzRootlessDefault = ![enable_fullscreen intValue]; + + [enable_fullscreen_menu setEnabled:!XQuartzRootlessDefault]; + + DarwinSendDDXEvent(kXquartzSetRootless, 1, XQuartzRootlessDefault); + + [NSApp prefs_set_boolean:@PREFS_ROOTLESS value:XQuartzRootlessDefault]; + [NSApp prefs_synchronize]; +} + +- (IBAction) toggle_fullscreen:sender +{ + DarwinSendDDXEvent(kXquartzToggleFullscreen, 0); +} + +- (void) set_can_quit:(OSX_BOOL)state +{ + can_quit = state; +} + +- (IBAction)prefs_changed:sender +{ + if(!sender) + return; + + if(sender == fake_buttons) { + darwinFakeButtons = [fake_buttons intValue]; + [NSApp prefs_set_boolean:@PREFS_FAKEBUTTONS value:darwinFakeButtons]; + } else if(sender == enable_keyequivs) { + XQuartzEnableKeyEquivalents = [enable_keyequivs intValue]; + [NSApp prefs_set_boolean:@PREFS_KEYEQUIVS value:XQuartzEnableKeyEquivalents]; + } else if(sender == sync_keymap) { + darwinSyncKeymap = [sync_keymap intValue]; + [NSApp prefs_set_boolean:@PREFS_SYNC_KEYMAP value:darwinSyncKeymap]; + } else if(sender == enable_fullscreen_menu) { + XQuartzFullscreenMenu = [enable_fullscreen_menu intValue]; + [NSApp prefs_set_boolean:@PREFS_FULLSCREEN_MENU value:XQuartzFullscreenMenu]; + } else if(sender == option_sends_alt) { + BOOL prev_opt_sends_alt = XQuartzOptionSendsAlt; + + XQuartzOptionSendsAlt = [option_sends_alt intValue]; + [NSApp prefs_set_boolean:@PREFS_OPTION_SENDS_ALT value:XQuartzOptionSendsAlt]; + + if(prev_opt_sends_alt != XQuartzOptionSendsAlt) + QuartsResyncKeymap(TRUE); + } else if(sender == click_through) { + [NSApp prefs_set_boolean:@PREFS_CLICK_THROUGH value:[click_through intValue]]; + } else if(sender == focus_follows_mouse) { + [NSApp prefs_set_boolean:@PREFS_FFM value:[focus_follows_mouse intValue]]; + } else if(sender == focus_on_new_window) { + [NSApp prefs_set_boolean:@PREFS_FOCUS_ON_NEW_WINDOW value:[focus_on_new_window intValue]]; + } else if(sender == enable_auth) { + [NSApp prefs_set_boolean:@PREFS_NO_AUTH value:![enable_auth intValue]]; + } else if(sender == enable_tcp) { + [NSApp prefs_set_boolean:@PREFS_NO_TCP value:![enable_tcp intValue]]; + } else if(sender == depth) { + [NSApp prefs_set_integer:@PREFS_DEPTH value:[depth selectedTag]]; + } else if(sender == sync_pasteboard) { + BOOL pbproxy_active = [sync_pasteboard intValue]; + [NSApp prefs_set_boolean:@PREFS_SYNC_PB value:pbproxy_active]; + + [sync_pasteboard_to_clipboard setEnabled:pbproxy_active]; + [sync_pasteboard_to_primary setEnabled:pbproxy_active]; + [sync_clipboard_to_pasteboard setEnabled:pbproxy_active]; + [sync_primary_immediately setEnabled:pbproxy_active]; + + // setEnabled doesn't do this... + [sync_text1 setTextColor:pbproxy_active ? [NSColor controlTextColor] : [NSColor disabledControlTextColor]]; + [sync_text2 setTextColor:pbproxy_active ? [NSColor controlTextColor] : [NSColor disabledControlTextColor]]; + } else if(sender == sync_pasteboard_to_clipboard) { + [NSApp prefs_set_boolean:@PREFS_SYNC_PB_TO_CLIPBOARD value:[sync_pasteboard_to_clipboard intValue]]; + } else if(sender == sync_pasteboard_to_primary) { + [NSApp prefs_set_boolean:@PREFS_SYNC_PB_TO_PRIMARY value:[sync_pasteboard_to_primary intValue]]; + } else if(sender == sync_clipboard_to_pasteboard) { + [NSApp prefs_set_boolean:@PREFS_SYNC_CLIPBOARD_TO_PB value:[sync_clipboard_to_pasteboard intValue]]; + } else if(sender == sync_primary_immediately) { + [NSApp prefs_set_boolean:@PREFS_SYNC_PRIMARY_ON_SELECT value:[sync_primary_immediately intValue]]; + } + + [NSApp prefs_synchronize]; + + DarwinSendDDXEvent(kXquartzReloadPreferences, 0); +} + +- (IBAction) prefs_show:sender +{ + BOOL pbproxy_active = [NSApp prefs_get_boolean:@PREFS_SYNC_PB default:YES]; + + [fake_buttons setIntValue:darwinFakeButtons]; + [enable_keyequivs setIntValue:XQuartzEnableKeyEquivalents]; + [sync_keymap setIntValue:darwinSyncKeymap]; + [option_sends_alt setIntValue:XQuartzOptionSendsAlt]; + [click_through setIntValue:[NSApp prefs_get_boolean:@PREFS_CLICK_THROUGH default:NO]]; + [focus_follows_mouse setIntValue:[NSApp prefs_get_boolean:@PREFS_FFM default:NO]]; + [focus_on_new_window setIntValue:[NSApp prefs_get_boolean:@PREFS_FOCUS_ON_NEW_WINDOW default:YES]]; + + [enable_auth setIntValue:![NSApp prefs_get_boolean:@PREFS_NO_AUTH default:NO]]; + [enable_tcp setIntValue:![NSApp prefs_get_boolean:@PREFS_NO_TCP default:NO]]; + + [depth selectItemAtIndex:[depth indexOfItemWithTag:[NSApp prefs_get_integer:@PREFS_DEPTH default:-1]]]; + + [sync_pasteboard setIntValue:pbproxy_active]; + [sync_pasteboard_to_clipboard setIntValue:[NSApp prefs_get_boolean:@PREFS_SYNC_PB_TO_CLIPBOARD default:YES]]; + [sync_pasteboard_to_primary setIntValue:[NSApp prefs_get_boolean:@PREFS_SYNC_PB_TO_PRIMARY default:YES]]; + [sync_clipboard_to_pasteboard setIntValue:[NSApp prefs_get_boolean:@PREFS_SYNC_CLIPBOARD_TO_PB default:YES]]; + [sync_primary_immediately setIntValue:[NSApp prefs_get_boolean:@PREFS_SYNC_PRIMARY_ON_SELECT default:NO]]; + + [sync_pasteboard_to_clipboard setEnabled:pbproxy_active]; + [sync_pasteboard_to_primary setEnabled:pbproxy_active]; + [sync_clipboard_to_pasteboard setEnabled:pbproxy_active]; + [sync_primary_immediately setEnabled:pbproxy_active]; + + // setEnabled doesn't do this... + [sync_text1 setTextColor:pbproxy_active ? [NSColor controlTextColor] : [NSColor disabledControlTextColor]]; + [sync_text2 setTextColor:pbproxy_active ? [NSColor controlTextColor] : [NSColor disabledControlTextColor]]; + + [enable_fullscreen setIntValue:!XQuartzRootlessDefault]; + [enable_fullscreen_menu setEnabled:!XQuartzRootlessDefault]; + [enable_fullscreen_menu setIntValue:XQuartzFullscreenMenu]; + + [prefs_panel makeKeyAndOrderFront:sender]; +} + +- (IBAction) quit:sender { + DarwinSendDDXEvent(kXquartzQuit, 0); +} + +- (IBAction) x11_help:sender { +#if MAC_OS_X_VERSION_MIN_REQUIRED < 1060 + AHLookupAnchor((CFStringRef)NSLocalizedString(@"Mac Help", no comment), CFSTR("mchlp2276")); +#else + AHLookupAnchor(CFSTR("com.apple.machelp"), CFSTR("mchlp2276")); +#endif +} + +- (OSX_BOOL) validateMenuItem:(NSMenuItem *)item { + NSMenu *menu = [item menu]; + + if (item == toggle_fullscreen_item) + return !XQuartzIsRootless; + else if (menu == [X11App windowsMenu] || menu == dock_menu + || (menu == [x11_about_item menu] && [item tag] == 42)) + return (AppleWMSelectedEvents () & AppleWMControllerNotifyMask) != 0; + else + return TRUE; +} + +- (void) applicationDidHide:(NSNotification *)notify +{ + DarwinSendDDXEvent(kXquartzControllerNotify, 1, AppleWMHideAll); +} + +- (void) applicationDidUnhide:(NSNotification *)notify +{ + DarwinSendDDXEvent(kXquartzControllerNotify, 1, AppleWMShowAll); +} + +- (NSApplicationTerminateReply) applicationShouldTerminate:sender { + NSString *msg; + NSString *title; + + if (can_quit || [X11App prefs_get_boolean:@PREFS_NO_QUIT_ALERT default:NO]) + return NSTerminateNow; + + /* Make sure we're frontmost. */ + [NSApp activateIgnoringOtherApps:YES]; + + title = NSLocalizedString(@"Do you really want to quit X11?", @"Dialog title when quitting"); + msg = NSLocalizedString(@"Any open X11 applications will stop immediately, and you will lose any unsaved changes.", @"Dialog when quitting"); + + /* FIXME: safe to run the alert in here? Or should we return Later + * and then run the alert on a timer? It seems to work here, so.. + */ + + return (NSRunAlertPanel (title, msg, NSLocalizedString (@"Quit", @""), + NSLocalizedString (@"Cancel", @""), nil) + == NSAlertDefaultReturn) ? NSTerminateNow : NSTerminateCancel; +} + +- (void) applicationWillTerminate:(NSNotification *)aNotification +{ + unsigned remain; + [X11App prefs_synchronize]; + + /* shutdown the X server, it will exit () for us. */ + DarwinSendDDXEvent(kXquartzQuit, 0); + + /* In case it doesn't, exit anyway after a while. */ + remain = 10000000; + while((remain = usleep(remain)) > 0); + + exit (1); +} + +- (void) server_ready +{ + x_list *node; + + finished_launching = YES; + + for (node = pending_apps; node != NULL; node = node->next) + { + NSString *filename = node->data; + [self launch_client:filename]; + [filename release]; + } + + x_list_free (pending_apps); + pending_apps = NULL; +} + +- (OSX_BOOL) application:(NSApplication *)app openFile:(NSString *)filename +{ + const char *name = [filename UTF8String]; + + if (finished_launching) + [self launch_client:filename]; + else if (name[0] != ':') /* ignore display names */ + pending_apps = x_list_prepend (pending_apps, [filename retain]); + + /* FIXME: report failures. */ + return YES; +} + +@end + +void X11ControllerMain(int argc, char **argv, char **envp) { + X11ApplicationMain (argc, argv, envp); +} diff --git a/xorg-server/hw/xquartz/bundle/Resources/English.lproj/main.nib/designable.nib b/xorg-server/hw/xquartz/bundle/Resources/English.lproj/main.nib/designable.nib index 7609393ba..bbf7eda62 100644 --- a/xorg-server/hw/xquartz/bundle/Resources/English.lproj/main.nib/designable.nib +++ b/xorg-server/hw/xquartz/bundle/Resources/English.lproj/main.nib/designable.nib @@ -2,19 +2,22 @@ 1040 - 10D573 - 761 - 1038.29 - 460.00 + 10J541 + 850 + 1038.35 + 462.00 com.apple.InterfaceBuilder.CocoaPlugin - 761 + 850 com.apple.InterfaceBuilder.CocoaPlugin - + + PluginDependencyRecalculationVersion + + @@ -388,7 +391,7 @@ 1 - + 256 @@ -396,7 +399,6 @@ 256 {{18, 210}, {402, 18}} - YES 67239424 @@ -424,7 +426,6 @@ 256 {{36, 60}, {385, 31}} - YES 67239424 @@ -461,7 +462,6 @@ 256 {{36, 162}, {385, 42}} - YES 67239424 @@ -479,7 +479,6 @@ IG9yIHJpZ2h0IG1vdXNlIGJ1dHRvbnMuCg 256 {{18, 97}, {402, 18}} - YES 67239424 @@ -501,7 +500,6 @@ IG9yIHJpZ2h0IG1vdXNlIGJ1dHRvbnMuCg 256 {{36, 126}, {385, 14}} - YES 67239424 @@ -518,7 +516,6 @@ IG9yIHJpZ2h0IG1vdXNlIGJ1dHRvbnMuCg 256 {{18, 146}, {402, 18}} - YES 67239424 @@ -540,7 +537,6 @@ IG9yIHJpZ2h0IG1vdXNlIGJ1dHRvbnMuCg 256 {{36, -1}, {385, 31}} - YES 67239424 @@ -557,7 +553,6 @@ IG9yIHJpZ2h0IG1vdXNlIGJ1dHRvbnMuCg 256 {{18, 36}, {402, 18}} - YES 67239424 @@ -576,8 +571,6 @@ IG9yIHJpZ2h0IG1vdXNlIGJ1dHRvbnMuCg {{10, 33}, {438, 246}} - - Input @@ -588,51 +581,15 @@ IG9yIHJpZ2h0IG1vdXNlIGJ1dHRvbnMuCg 2 - + 256 - - - 256 - {{18, 63}, {402, 18}} - - YES - - 67239424 - 0 - Use system alert effect - - - 1211912703 - 2 - - - - 200 - 25 - - - - - 256 - {{36, 29}, {385, 28}} - - YES - - 67239424 - 4194304 - X11 beeps will use the standard system alert, as defined in the Sound Effects system preferences panel. - - - - - - 256 {{74, 202}, {128, 26}} + YES -2076049856 @@ -723,6 +680,7 @@ IG9yIHJpZ2h0IG1vdXNlIGJ1dHRvbnMuCg 256 {{17, 205}, {55, 20}} + YES 67239424 @@ -739,6 +697,7 @@ IG9yIHJpZ2h0IG1vdXNlIGJ1dHRvbnMuCg 256 {{36, 183}, {392, 14}} + YES 67239424 @@ -755,6 +714,7 @@ IG9yIHJpZ2h0IG1vdXNlIGJ1dHRvbnMuCg 256 {{18, 149}, {409, 23}} + YES 67239424 @@ -776,6 +736,7 @@ IG9yIHJpZ2h0IG1vdXNlIGJ1dHRvbnMuCg 256 {{37, 83}, {409, 23}} + YES 67239424 @@ -797,6 +758,7 @@ IG9yIHJpZ2h0IG1vdXNlIGJ1dHRvbnMuCg 256 {{36, 112}, {385, 31}} + YES 67239424 @@ -810,6 +772,8 @@ IG9yIHJpZ2h0IG1vdXNlIGJ1dHRvbnMuCg {{10, 33}, {438, 246}} + + Output @@ -1212,13 +1176,13 @@ IG9yIHJpZ2h0IG1vdXNlIGJ1dHRvbnMuCg - + 0 YES YES - + @@ -1732,14 +1696,6 @@ IG9yIHJpZ2h0IG1vdXNlIGJ1dHRvbnMuCg 389 - - - use_sysbeep - - - - 390 - fake_buttons @@ -1788,14 +1744,6 @@ IG9yIHJpZ2h0IG1vdXNlIGJ1dHRvbnMuCg 396 - - - prefs_changed: - - - - 397 - prefs_changed: @@ -2547,27 +2495,9 @@ IG9yIHJpZ2h0IG1vdXNlIGJ1dHRvbnMuCg - - - - 371 - - - - - - - - 372 - - - - - - 382 @@ -2760,16 +2690,6 @@ IG9yIHJpZ2h0IG1vdXNlIGJ1dHRvbnMuCg - - 100371 - - - - - 100372 - - - 100382 @@ -3249,8 +3169,6 @@ IG9yIHJpZ2h0IG1vdXNlIGJ1dHRvbnMuCg com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin @@ -3443,10 +3361,6 @@ IG9yIHJpZ2h0IG1vdXNlIGJ1dHRvbnMuCg com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin @@ -3582,6 +3496,76 @@ IG9yIHJpZ2h0IG1vdXNlIGJ1dHRvbnMuCg id id + + + apps_table_delete: + id + + + apps_table_done: + id + + + apps_table_duplicate: + id + + + apps_table_new: + id + + + apps_table_show: + id + + + bring_to_front: + id + + + close_window: + id + + + enable_fullscreen_changed: + id + + + minimize_window: + id + + + next_window: + id + + + prefs_changed: + id + + + prefs_show: + id + + + previous_window: + id + + + quit: + id + + + toggle_fullscreen: + id + + + x11_help: + id + + + zoom_window: + id + + NSMenuItem NSTableView @@ -3614,6 +3598,128 @@ IG9yIHJpZ2h0IG1vdXNlIGJ1dHRvbnMuCg NSMenuItem NSMenuItem + + + apps_separator + NSMenuItem + + + apps_table + NSTableView + + + click_through + NSButton + + + copy_menu_item + NSMenuItem + + + depth + NSPopUpButton + + + dock_apps_menu + NSMenu + + + dock_menu + NSMenu + + + dock_window_separator + NSMenuItem + + + enable_auth + NSButton + + + enable_fullscreen + NSButton + + + enable_fullscreen_menu + NSButton + + + enable_keyequivs + NSButton + + + enable_tcp + NSButton + + + fake_buttons + NSButton + + + focus_follows_mouse + NSButton + + + focus_on_new_window + NSButton + + + option_sends_alt + NSButton + + + prefs_panel + NSPanel + + + sync_clipboard_to_pasteboard + NSButton + + + sync_keymap + NSButton + + + sync_pasteboard + NSButton + + + sync_pasteboard_to_clipboard + NSButton + + + sync_pasteboard_to_primary + NSButton + + + sync_primary_immediately + NSButton + + + sync_text1 + NSTextField + + + sync_text2 + NSTextField + + + toggle_fullscreen_item + NSMenuItem + + + use_sysbeep + NSButton + + + window_separator + NSMenuItem + + + x11_about_item + NSMenuItem + + IBDocumentRelativeSource ../../../X11Controller.h diff --git a/xorg-server/hw/xquartz/bundle/Resources/English.lproj/main.nib/keyedobjects.nib b/xorg-server/hw/xquartz/bundle/Resources/English.lproj/main.nib/keyedobjects.nib index 888424dfc..836d59532 100644 Binary files a/xorg-server/hw/xquartz/bundle/Resources/English.lproj/main.nib/keyedobjects.nib and b/xorg-server/hw/xquartz/bundle/Resources/English.lproj/main.nib/keyedobjects.nib differ diff --git a/xorg-server/hw/xquartz/quartz.c b/xorg-server/hw/xquartz/quartz.c index aed063489..6c185a8eb 100644 --- a/xorg-server/hw/xquartz/quartz.c +++ b/xorg-server/hw/xquartz/quartz.c @@ -1,448 +1,457 @@ -/* - * - * Quartz-specific support for the Darwin X Server - * - * Copyright (c) 2001-2004 Greg Parker and Torrey T. Lyons. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Except as contained in this notice, the name(s) of the above copyright - * holders shall not be used in advertising or otherwise to promote the sale, - * use or other dealings in this Software without prior written authorization. - */ - -#include "sanitizedCarbon.h" - -#ifdef HAVE_DIX_CONFIG_H -#include -#endif - -#include "quartzCommon.h" -#include "quartzRandR.h" -#include "inputstr.h" -#include "quartz.h" -#include "darwin.h" -#include "darwinEvents.h" -#include "pseudoramiX.h" -#define _APPLEWM_SERVER_ -#include "applewmExt.h" - -#include "X11Application.h" - -#include - -// X headers -#include "scrnintstr.h" -#include "windowstr.h" -#include "colormapst.h" -#include "globals.h" -#include "mi.h" - -// System headers -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -DevPrivateKeyRec quartzScreenKeyRec; -int aquaMenuBarHeight = 0; -QuartzModeProcsPtr quartzProcs = NULL; -const char *quartzOpenGLBundle = NULL; - -Bool XQuartzFullscreenDisableHotkeys = TRUE; -Bool XQuartzOptionSendsAlt = FALSE; -Bool XQuartzEnableKeyEquivalents = TRUE; -Bool XQuartzFullscreenVisible = FALSE; -Bool XQuartzRootlessDefault = TRUE; -Bool XQuartzIsRootless = TRUE; -Bool XQuartzServerVisible = FALSE; -Bool XQuartzFullscreenMenu = FALSE; -Bool XQuartzUseSysBeep = FALSE; - -/* -=========================================================================== - - Screen functions - -=========================================================================== -*/ - -/* - * QuartzAddScreen - * Do mode dependent initialization of each screen for Quartz. - */ -Bool QuartzAddScreen( - int index, - ScreenPtr pScreen) -{ - // allocate space for private per screen Quartz specific storage - QuartzScreenPtr displayInfo = calloc(sizeof(QuartzScreenRec), 1); - - // QUARTZ_PRIV(pScreen) = displayInfo; - dixSetPrivate(&pScreen->devPrivates, quartzScreenKey, displayInfo); - - // do Quartz mode specific initialization - return quartzProcs->AddScreen(index, pScreen); -} - - -/* - * QuartzSetupScreen - * Finalize mode specific setup of each screen. - */ -Bool QuartzSetupScreen( - int index, - ScreenPtr pScreen) -{ - // do Quartz mode specific setup - if (! quartzProcs->SetupScreen(index, pScreen)) - return FALSE; - - // setup cursor support - if (! quartzProcs->InitCursor(pScreen)) - return FALSE; - -#if defined(RANDR) - if(!QuartzRandRInit(pScreen)) { - DEBUG_LOG("Failed to init RandR extension.\n"); - return FALSE; - } -#endif - - return TRUE; -} - - -/* - * QuartzInitOutput - * Quartz display initialization. - */ -void QuartzInitOutput( - int argc, - char **argv ) -{ - if (!RegisterBlockAndWakeupHandlers(QuartzBlockHandler, - QuartzWakeupHandler, - NULL)) - { - FatalError("Could not register block and wakeup handlers."); - } - - if (!dixRegisterPrivateKey(&quartzScreenKeyRec, PRIVATE_SCREEN, 0)) - FatalError("Failed to alloc quartz screen private.\n"); - - // Do display mode specific initialization - quartzProcs->DisplayInit(); -} - - -/* - * QuartzInitInput - * Inform the main thread the X server is ready to handle events. - */ -void QuartzInitInput( - int argc, - char **argv ) -{ - X11ApplicationSetCanQuit(0); - X11ApplicationServerReady(); - // Do final display mode specific initialization before handling events - if (quartzProcs->InitInput) - quartzProcs->InitInput(argc, argv); -} - - -void QuartzUpdateScreens(void) { - ScreenPtr pScreen; - WindowPtr pRoot; - int x, y, width, height, sx, sy; - xEvent e; - BoxRec bounds; - - if (noPseudoramiXExtension || screenInfo.numScreens != 1) - { - /* FIXME: if not using Xinerama, we have multiple screens, and - to do this properly may need to add or remove screens. Which - isn't possible. So don't do anything. Another reason why - we default to running with Xinerama. */ - - return; - } - - pScreen = screenInfo.screens[0]; - - PseudoramiXResetScreens(); - quartzProcs->AddPseudoramiXScreens(&x, &y, &width, &height, pScreen); - - pScreen->x = x; - pScreen->y = y; - pScreen->mmWidth = pScreen->mmWidth * ((double) width / pScreen->width); - pScreen->mmHeight = pScreen->mmHeight * ((double) height / pScreen->height); - pScreen->width = width; - pScreen->height = height; - - DarwinAdjustScreenOrigins(&screenInfo); - - /* DarwinAdjustScreenOrigins or UpdateScreen may change pScreen->x/y, - * so use it rather than x/y - */ - sx = pScreen->x + darwinMainScreenX; - sy = pScreen->y + darwinMainScreenY; - - /* Adjust the root window. */ - pRoot = pScreen->root; - AppleWMSetScreenOrigin(pRoot); - pScreen->ResizeWindow(pRoot, x - sx, y - sy, width, height, NULL); - - miPaintWindow(pRoot, &pRoot->borderClip, PW_BACKGROUND); - - /* pointer events are clipped to old display region after display reconfiguration - * http://xquartz.macosforge.org/trac/ticket/346 - */ - bounds.x1 = 0; - bounds.x2 = width; - bounds.y1 = 0; - bounds.y2 = height; - pScreen->ConstrainCursor(inputInfo.pointer, pScreen, &bounds); - inputInfo.pointer->spriteInfo->sprite->physLimits = bounds; - inputInfo.pointer->spriteInfo->sprite->hotLimits = bounds; - - DEBUG_LOG("Root Window: %dx%d @ (%d, %d) darwinMainScreen (%d, %d) xy (%d, %d) dixScreenOrigins (%d, %d)\n", width, height, x - sx, y - sy, darwinMainScreenX, darwinMainScreenY, x, y, pScreen->x, pScreen->y); - - /* Send an event for the root reconfigure */ - e.u.u.type = ConfigureNotify; - e.u.configureNotify.window = pRoot->drawable.id; - e.u.configureNotify.aboveSibling = None; - e.u.configureNotify.x = x - sx; - e.u.configureNotify.y = y - sy; - e.u.configureNotify.width = width; - e.u.configureNotify.height = height; - e.u.configureNotify.borderWidth = wBorderWidth(pRoot); - e.u.configureNotify.override = pRoot->overrideRedirect; - DeliverEvents(pRoot, &e, 1, NullWindow); - - quartzProcs->UpdateScreen(pScreen); -} - -static void pokeActivityCallback(CFRunLoopTimerRef timer, void *info) { - UpdateSystemActivity(OverallAct); -} - -static void QuartzScreenSaver(int state) { - static CFRunLoopTimerRef pokeActivityTimer = NULL; - static CFRunLoopTimerContext pokeActivityContext = { 0, NULL, NULL, NULL, NULL }; - static pthread_mutex_t pokeActivityMutex = PTHREAD_MUTEX_INITIALIZER; - - pthread_mutex_lock(&pokeActivityMutex); - - if(state) { - if(pokeActivityTimer == NULL) - goto QuartzScreenSaverEnd; - - CFRunLoopTimerInvalidate(pokeActivityTimer); - CFRelease(pokeActivityTimer); - pokeActivityTimer = NULL; - } else { - if(pokeActivityTimer != NULL) - goto QuartzScreenSaverEnd; - - pokeActivityTimer = CFRunLoopTimerCreate(NULL, CFAbsoluteTimeGetCurrent(), 30, 0, 0, pokeActivityCallback, &pokeActivityContext); - if(pokeActivityTimer == NULL) { - ErrorF("Unable to create pokeActivityTimer.\n"); - goto QuartzScreenSaverEnd; - } - - CFRunLoopAddTimer(CFRunLoopGetMain(), pokeActivityTimer, kCFRunLoopCommonModes); - } -QuartzScreenSaverEnd: - pthread_mutex_unlock(&pokeActivityMutex); -} - -void QuartzShowFullscreen(int state) { - int i; - - DEBUG_LOG("QuartzShowFullscreen: state=%d\n", state); - - if(XQuartzIsRootless) { - ErrorF("QuartzShowFullscreen called while in rootless mode.\n"); - return; - } - - QuartzScreenSaver(!state); - - if(XQuartzFullscreenVisible == state) - return; - - XQuartzFullscreenVisible = state; - - xp_disable_update (); - - if (!XQuartzFullscreenVisible) - RootlessHideAllWindows(); - - RootlessUpdateRooted(XQuartzFullscreenVisible); - - if (XQuartzFullscreenVisible) { - RootlessShowAllWindows (); - for (i=0; i < screenInfo.numScreens; i++) { - ScreenPtr pScreen = screenInfo.screens[i]; - RootlessRepositionWindows(pScreen); - // JH: I don't think this is necessary, but keeping it here as a reminder - //RootlessUpdateScreenPixmap(pScreen); - } - } - - /* Somehow the menubar manages to interfere with our event stream - * in fullscreen mode, even though it's not visible. - */ - X11ApplicationShowHideMenubar(!XQuartzFullscreenVisible); - - xp_reenable_update (); - - if (XQuartzFullscreenDisableHotkeys) - xp_disable_hot_keys(XQuartzFullscreenVisible); -} - -void QuartzSetRootless(Bool state) { - DEBUG_LOG("QuartzSetRootless state=%d\n", state); - - if(XQuartzIsRootless == state) - return; - - if(state) - QuartzShowFullscreen(FALSE); - - XQuartzIsRootless = state; - - xp_disable_update(); - - /* When in rootless, the menubar is not part of the screen, so we need to update our screens on toggle */ - QuartzUpdateScreens(); - - if(XQuartzIsRootless) { - RootlessShowAllWindows(); - } else { - RootlessHideAllWindows(); - } - - X11ApplicationShowHideMenubar(TRUE); - - xp_reenable_update(); - - xp_disable_hot_keys(FALSE); -} - -/* - * QuartzShow - * Show the X server on screen. Does nothing if already shown. - * Calls mode specific screen resume to restore the X clip regions - * (if needed) and the X server cursor state. - */ -void QuartzShow(void) { - int i; - - if (XQuartzServerVisible) - return; - - XQuartzServerVisible = TRUE; - for (i = 0; i < screenInfo.numScreens; i++) { - if (screenInfo.screens[i]) { - quartzProcs->ResumeScreen(screenInfo.screens[i]); - } - } - - if (!XQuartzIsRootless) - QuartzShowFullscreen(TRUE); -} - - -/* - * QuartzHide - * Remove the X server display from the screen. Does nothing if already - * hidden. Calls mode specific screen suspend to set X clip regions to - * prevent drawing (if needed) and restore the Aqua cursor. - */ -void QuartzHide(void) -{ - int i; - - if (XQuartzServerVisible) { - for (i = 0; i < screenInfo.numScreens; i++) { - if (screenInfo.screens[i]) { - quartzProcs->SuspendScreen(screenInfo.screens[i]); - } - } - } - - if(!XQuartzIsRootless) - QuartzShowFullscreen(FALSE); - XQuartzServerVisible = FALSE; -} - - -/* - * QuartzSetRootClip - * Enable or disable rendering to the X screen. - */ -void QuartzSetRootClip( - BOOL enable) -{ - int i; - - if (!XQuartzServerVisible) - return; - - for (i = 0; i < screenInfo.numScreens; i++) { - if (screenInfo.screens[i]) { - xf86SetRootClip(screenInfo.screens[i], enable); - } - } -} - -/* - * QuartzSpaceChanged - * Unmap offscreen windows, map onscreen windows - */ -void QuartzSpaceChanged(uint32_t space_id) { - /* Do something special here, so we don't depend on quartz-wm for spaces to work... */ - DEBUG_LOG("Space Changed (%u) ... do something interesting...\n", space_id); -} - -/* - * QuartzCopyDisplayIDs - * Associate an X11 screen with one or more CoreGraphics display IDs by copying - * the list into a private array. Free the previously copied array, if present. - */ -void QuartzCopyDisplayIDs(ScreenPtr pScreen, - int displayCount, CGDirectDisplayID *displayIDs) { - QuartzScreenPtr pQuartzScreen = QUARTZ_PRIV(pScreen); - int size = displayCount * sizeof(CGDirectDisplayID); - - free(pQuartzScreen->displayIDs); - pQuartzScreen->displayIDs = malloc(size); - memcpy(pQuartzScreen->displayIDs, displayIDs, size); - pQuartzScreen->displayCount = displayCount; -} +/* + * + * Quartz-specific support for the Darwin X Server + * + * Copyright (c) 2001-2004 Greg Parker and Torrey T. Lyons. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name(s) of the above copyright + * holders shall not be used in advertising or otherwise to promote the sale, + * use or other dealings in this Software without prior written authorization. + */ + +#include "sanitizedCarbon.h" + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include "quartzCommon.h" +#include "quartzRandR.h" +#include "inputstr.h" +#include "quartz.h" +#include "darwin.h" +#include "darwinEvents.h" +#include "pseudoramiX.h" +#define _APPLEWM_SERVER_ +#include "applewmExt.h" + +#include "X11Application.h" + +#include + +// X headers +#include "scrnintstr.h" +#include "windowstr.h" +#include "colormapst.h" +#include "globals.h" +#include "mi.h" + +// System headers +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +DevPrivateKeyRec quartzScreenKeyRec; +int aquaMenuBarHeight = 0; +QuartzModeProcsPtr quartzProcs = NULL; +const char *quartzOpenGLBundle = NULL; + +Bool XQuartzFullscreenDisableHotkeys = TRUE; +Bool XQuartzOptionSendsAlt = FALSE; +Bool XQuartzEnableKeyEquivalents = TRUE; +Bool XQuartzFullscreenVisible = FALSE; +Bool XQuartzRootlessDefault = TRUE; +Bool XQuartzIsRootless = TRUE; +Bool XQuartzServerVisible = FALSE; +Bool XQuartzFullscreenMenu = FALSE; + +/* +=========================================================================== + + Screen functions + +=========================================================================== +*/ + +/* + * QuartzAddScreen + * Do mode dependent initialization of each screen for Quartz. + */ +Bool QuartzAddScreen( + int index, + ScreenPtr pScreen) +{ + // allocate space for private per screen Quartz specific storage + QuartzScreenPtr displayInfo = calloc(sizeof(QuartzScreenRec), 1); + + // QUARTZ_PRIV(pScreen) = displayInfo; + dixSetPrivate(&pScreen->devPrivates, quartzScreenKey, displayInfo); + + // do Quartz mode specific initialization + return quartzProcs->AddScreen(index, pScreen); +} + + +/* + * QuartzSetupScreen + * Finalize mode specific setup of each screen. + */ +Bool QuartzSetupScreen( + int index, + ScreenPtr pScreen) +{ + // do Quartz mode specific setup + if (! quartzProcs->SetupScreen(index, pScreen)) + return FALSE; + + // setup cursor support + if (! quartzProcs->InitCursor(pScreen)) + return FALSE; + +#if defined(RANDR) + if(!QuartzRandRInit(pScreen)) { + DEBUG_LOG("Failed to init RandR extension.\n"); + return FALSE; + } +#endif + + return TRUE; +} + + +/* + * QuartzInitOutput + * Quartz display initialization. + */ +void QuartzInitOutput( + int argc, + char **argv ) +{ + if (!RegisterBlockAndWakeupHandlers(QuartzBlockHandler, + QuartzWakeupHandler, + NULL)) + { + FatalError("Could not register block and wakeup handlers."); + } + + if (!dixRegisterPrivateKey(&quartzScreenKeyRec, PRIVATE_SCREEN, 0)) + FatalError("Failed to alloc quartz screen private.\n"); + + // Do display mode specific initialization + quartzProcs->DisplayInit(); +} + + +/* + * QuartzInitInput + * Inform the main thread the X server is ready to handle events. + */ +void QuartzInitInput( + int argc, + char **argv ) +{ + X11ApplicationSetCanQuit(0); + X11ApplicationServerReady(); + // Do final display mode specific initialization before handling events + if (quartzProcs->InitInput) + quartzProcs->InitInput(argc, argv); +} + + +void QuartzUpdateScreens(void) { + ScreenPtr pScreen; + WindowPtr pRoot; + int x, y, width, height, sx, sy; + xEvent e; + BoxRec bounds; + + if (noPseudoramiXExtension || screenInfo.numScreens != 1) + { + /* FIXME: if not using Xinerama, we have multiple screens, and + to do this properly may need to add or remove screens. Which + isn't possible. So don't do anything. Another reason why + we default to running with Xinerama. */ + + return; + } + + pScreen = screenInfo.screens[0]; + + PseudoramiXResetScreens(); + quartzProcs->AddPseudoramiXScreens(&x, &y, &width, &height, pScreen); + + pScreen->x = x; + pScreen->y = y; + pScreen->mmWidth = pScreen->mmWidth * ((double) width / pScreen->width); + pScreen->mmHeight = pScreen->mmHeight * ((double) height / pScreen->height); + pScreen->width = width; + pScreen->height = height; + + DarwinAdjustScreenOrigins(&screenInfo); + + /* DarwinAdjustScreenOrigins or UpdateScreen may change pScreen->x/y, + * so use it rather than x/y + */ + sx = pScreen->x + darwinMainScreenX; + sy = pScreen->y + darwinMainScreenY; + + /* Adjust the root window. */ + pRoot = pScreen->root; + AppleWMSetScreenOrigin(pRoot); + pScreen->ResizeWindow(pRoot, x - sx, y - sy, width, height, NULL); + + miPaintWindow(pRoot, &pRoot->borderClip, PW_BACKGROUND); + + /* pointer events are clipped to old display region after display reconfiguration + * http://xquartz.macosforge.org/trac/ticket/346 + */ + bounds.x1 = 0; + bounds.x2 = width; + bounds.y1 = 0; + bounds.y2 = height; + pScreen->ConstrainCursor(inputInfo.pointer, pScreen, &bounds); + inputInfo.pointer->spriteInfo->sprite->physLimits = bounds; + inputInfo.pointer->spriteInfo->sprite->hotLimits = bounds; + + DEBUG_LOG("Root Window: %dx%d @ (%d, %d) darwinMainScreen (%d, %d) xy (%d, %d) dixScreenOrigins (%d, %d)\n", width, height, x - sx, y - sy, darwinMainScreenX, darwinMainScreenY, x, y, pScreen->x, pScreen->y); + + /* Send an event for the root reconfigure */ + e.u.u.type = ConfigureNotify; + e.u.configureNotify.window = pRoot->drawable.id; + e.u.configureNotify.aboveSibling = None; + e.u.configureNotify.x = x - sx; + e.u.configureNotify.y = y - sy; + e.u.configureNotify.width = width; + e.u.configureNotify.height = height; + e.u.configureNotify.borderWidth = wBorderWidth(pRoot); + e.u.configureNotify.override = pRoot->overrideRedirect; + DeliverEvents(pRoot, &e, 1, NullWindow); + + quartzProcs->UpdateScreen(pScreen); +} + +static void pokeActivityCallback(CFRunLoopTimerRef timer, void *info) { + UpdateSystemActivity(OverallAct); +} + +static void QuartzScreenSaver(int state) { + static CFRunLoopTimerRef pokeActivityTimer = NULL; + static CFRunLoopTimerContext pokeActivityContext = { 0, NULL, NULL, NULL, NULL }; + static pthread_mutex_t pokeActivityMutex = PTHREAD_MUTEX_INITIALIZER; + + pthread_mutex_lock(&pokeActivityMutex); + + if(state) { + if(pokeActivityTimer == NULL) + goto QuartzScreenSaverEnd; + + CFRunLoopTimerInvalidate(pokeActivityTimer); + CFRelease(pokeActivityTimer); + pokeActivityTimer = NULL; + } else { + if(pokeActivityTimer != NULL) + goto QuartzScreenSaverEnd; + + pokeActivityTimer = CFRunLoopTimerCreate(NULL, CFAbsoluteTimeGetCurrent(), 30, 0, 0, pokeActivityCallback, &pokeActivityContext); + if(pokeActivityTimer == NULL) { + ErrorF("Unable to create pokeActivityTimer.\n"); + goto QuartzScreenSaverEnd; + } + + CFRunLoopAddTimer(CFRunLoopGetMain(), pokeActivityTimer, kCFRunLoopCommonModes); + } +QuartzScreenSaverEnd: + pthread_mutex_unlock(&pokeActivityMutex); +} + +void QuartzShowFullscreen(int state) { + int i; + + DEBUG_LOG("QuartzShowFullscreen: state=%d\n", state); + + if(XQuartzIsRootless) { + ErrorF("QuartzShowFullscreen called while in rootless mode.\n"); + return; + } + + QuartzScreenSaver(!state); + + if(XQuartzFullscreenVisible == state) + return; + + XQuartzFullscreenVisible = state; + + xp_disable_update (); + + if (!XQuartzFullscreenVisible) + RootlessHideAllWindows(); + + RootlessUpdateRooted(XQuartzFullscreenVisible); + + if (XQuartzFullscreenVisible) { + RootlessShowAllWindows (); + for (i=0; i < screenInfo.numScreens; i++) { + ScreenPtr pScreen = screenInfo.screens[i]; + RootlessRepositionWindows(pScreen); + // JH: I don't think this is necessary, but keeping it here as a reminder + //RootlessUpdateScreenPixmap(pScreen); + } + } + + /* Somehow the menubar manages to interfere with our event stream + * in fullscreen mode, even though it's not visible. + */ + X11ApplicationShowHideMenubar(!XQuartzFullscreenVisible); + + xp_reenable_update (); + + if (XQuartzFullscreenDisableHotkeys) + xp_disable_hot_keys(XQuartzFullscreenVisible); +} + +void QuartzSetRootless(Bool state) { + DEBUG_LOG("QuartzSetRootless state=%d\n", state); + + if(XQuartzIsRootless == state) + return; + + if(state) + QuartzShowFullscreen(FALSE); + + XQuartzIsRootless = state; + + xp_disable_update(); + + /* When in rootless, the menubar is not part of the screen, so we need to update our screens on toggle */ + QuartzUpdateScreens(); + + if(XQuartzIsRootless) { + RootlessShowAllWindows(); + } else { + RootlessHideAllWindows(); + } + + X11ApplicationShowHideMenubar(TRUE); + + xp_reenable_update(); + + xp_disable_hot_keys(FALSE); +} + +/* + * QuartzShow + * Show the X server on screen. Does nothing if already shown. + * Calls mode specific screen resume to restore the X clip regions + * (if needed) and the X server cursor state. + */ +void QuartzShow(void) { + int i; + + if (XQuartzServerVisible) + return; + + XQuartzServerVisible = TRUE; + for (i = 0; i < screenInfo.numScreens; i++) { + if (screenInfo.screens[i]) { + quartzProcs->ResumeScreen(screenInfo.screens[i]); + } + } + + if (!XQuartzIsRootless) + QuartzShowFullscreen(TRUE); +} + + +/* + * QuartzHide + * Remove the X server display from the screen. Does nothing if already + * hidden. Calls mode specific screen suspend to set X clip regions to + * prevent drawing (if needed) and restore the Aqua cursor. + */ +void QuartzHide(void) +{ + int i; + + if (XQuartzServerVisible) { + for (i = 0; i < screenInfo.numScreens; i++) { + if (screenInfo.screens[i]) { + quartzProcs->SuspendScreen(screenInfo.screens[i]); + } + } + } + + if(!XQuartzIsRootless) + QuartzShowFullscreen(FALSE); + XQuartzServerVisible = FALSE; +} + + +/* + * QuartzSetRootClip + * Enable or disable rendering to the X screen. + */ +void QuartzSetRootClip( + BOOL enable) +{ + int i; + + if (!XQuartzServerVisible) + return; + + for (i = 0; i < screenInfo.numScreens; i++) { + if (screenInfo.screens[i]) { + xf86SetRootClip(screenInfo.screens[i], enable); + } + } +} + +/* + * QuartzSpaceChanged + * Unmap offscreen windows, map onscreen windows + */ +void QuartzSpaceChanged(uint32_t space_id) { + /* Do something special here, so we don't depend on quartz-wm for spaces to work... */ + DEBUG_LOG("Space Changed (%u) ... do something interesting...\n", space_id); +} + +/* + * QuartzCopyDisplayIDs + * Associate an X11 screen with one or more CoreGraphics display IDs by copying + * the list into a private array. Free the previously copied array, if present. + */ +void QuartzCopyDisplayIDs(ScreenPtr pScreen, + int displayCount, CGDirectDisplayID *displayIDs) { + QuartzScreenPtr pQuartzScreen = QUARTZ_PRIV(pScreen); + int size = displayCount * sizeof(CGDirectDisplayID); + + free(pQuartzScreen->displayIDs); + pQuartzScreen->displayIDs = malloc(size); + memcpy(pQuartzScreen->displayIDs, displayIDs, size); + pQuartzScreen->displayCount = displayCount; +} + +void NSBeep(void); +void DDXRingBell( + int volume, // volume is % of max + int pitch, // pitch is Hz + int duration) // duration is milliseconds +{ + if (volume) + NSBeep(); +} diff --git a/xorg-server/hw/xquartz/quartz.h b/xorg-server/hw/xquartz/quartz.h index f0b519e21..b83391db9 100644 --- a/xorg-server/hw/xquartz/quartz.h +++ b/xorg-server/hw/xquartz/quartz.h @@ -1,146 +1,145 @@ -/* - * quartz.h - * - * External interface of the Quartz display modes seen by the generic, mode - * independent parts of the Darwin X server. - * - * Copyright (c) 2001-2003 Greg Parker and Torrey T. Lyons. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Except as contained in this notice, the name(s) of the above copyright - * holders shall not be used in advertising or otherwise to promote the sale, - * use or other dealings in this Software without prior written authorization. - */ - -#ifndef _QUARTZ_H -#define _QUARTZ_H - -#include "screenint.h" -#include "window.h" -#include "pixmap.h" - -/*------------------------------------------ - Quartz display mode function types - ------------------------------------------*/ - -/* - * Display mode initialization - */ -typedef void (*DisplayInitProc)(void); -typedef Bool (*AddScreenProc)(int index, ScreenPtr pScreen); -typedef Bool (*SetupScreenProc)(int index, ScreenPtr pScreen); -typedef void (*InitInputProc)(int argc, char **argv); - -/* - * Cursor functions - */ -typedef Bool (*InitCursorProc)(ScreenPtr pScreen); - -/* - * Suspend and resume X11 activity - */ -typedef void (*SuspendScreenProc)(ScreenPtr pScreen); -typedef void (*ResumeScreenProc)(ScreenPtr pScreen); - -/* - * Screen state change support - */ -typedef void (*AddPseudoramiXScreensProc) - (int *x, int *y, int *width, int *height, ScreenPtr pScreen); -typedef void (*UpdateScreenProc)(ScreenPtr pScreen); - -/* - * Rootless helper functions - */ -typedef Bool (*IsX11WindowProc)(void *nsWindow, int windowNumber); -typedef void (*HideWindowsProc)(Bool hide); - -/* - * Rootless functions for optional export to GLX layer - */ -typedef void * (*FrameForWindowProc)(WindowPtr pWin, Bool create); -typedef WindowPtr (*TopLevelParentProc)(WindowPtr pWindow); -typedef Bool (*CreateSurfaceProc) - (ScreenPtr pScreen, Drawable id, DrawablePtr pDrawable, - unsigned int client_id, unsigned int *surface_id, - unsigned int key[2], void (*notify) (void *arg, void *data), - void *notify_data); -typedef Bool (*DestroySurfaceProc) - (ScreenPtr pScreen, Drawable id, DrawablePtr pDrawable, - void (*notify) (void *arg, void *data), void *notify_data); - -/* - * Quartz display mode function list - */ -typedef struct _QuartzModeProcs { - DisplayInitProc DisplayInit; - AddScreenProc AddScreen; - SetupScreenProc SetupScreen; - InitInputProc InitInput; - - InitCursorProc InitCursor; - - SuspendScreenProc SuspendScreen; - ResumeScreenProc ResumeScreen; - - AddPseudoramiXScreensProc AddPseudoramiXScreens; - UpdateScreenProc UpdateScreen; - - IsX11WindowProc IsX11Window; - HideWindowsProc HideWindows; - - FrameForWindowProc FrameForWindow; - TopLevelParentProc TopLevelParent; - CreateSurfaceProc CreateSurface; - DestroySurfaceProc DestroySurface; -} QuartzModeProcsRec, *QuartzModeProcsPtr; - -extern QuartzModeProcsPtr quartzProcs; - -extern Bool XQuartzFullscreenVisible; /* Are the windows visible (predicated on !rootless) */ -extern Bool XQuartzServerVisible; /* Is the server visible ... TODO: Refactor to "active" */ -extern Bool XQuartzEnableKeyEquivalents; -extern Bool XQuartzRootlessDefault; /* Is our default mode rootless? */ -extern Bool XQuartzIsRootless; /* Is our current mode rootless (or FS)? */ -extern Bool XQuartzFullscreenMenu; /* Show the menu bar (autohide) while in FS */ -extern Bool XQuartzFullscreenDisableHotkeys; -extern Bool XQuartzOptionSendsAlt; /* Alt or Mode_switch? */ -extern Bool XQuartzUseSysBeep; /* Sys beep or our own? */ - -Bool QuartzAddScreen(int index, ScreenPtr pScreen); -Bool QuartzSetupScreen(int index, ScreenPtr pScreen); -void QuartzInitOutput(int argc,char **argv); -void QuartzInitInput(int argc, char **argv); -void QuartzInitServer(int argc, char **argv, char **envp); -void QuartzGiveUp(void); -void QuartzProcessEvent(xEvent *xe); -void QuartzUpdateScreens(void); - -void QuartzShow(void); -void QuartzHide(void); -void QuartzSetRootClip(BOOL enable); -void QuartzSpaceChanged(uint32_t space_id); - -void QuartzSetRootless(Bool state); -void QuartzShowFullscreen(Bool state); - -int server_main(int argc, char **argv, char **envp); -#endif +/* + * quartz.h + * + * External interface of the Quartz display modes seen by the generic, mode + * independent parts of the Darwin X server. + * + * Copyright (c) 2001-2003 Greg Parker and Torrey T. Lyons. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name(s) of the above copyright + * holders shall not be used in advertising or otherwise to promote the sale, + * use or other dealings in this Software without prior written authorization. + */ + +#ifndef _QUARTZ_H +#define _QUARTZ_H + +#include "screenint.h" +#include "window.h" +#include "pixmap.h" + +/*------------------------------------------ + Quartz display mode function types + ------------------------------------------*/ + +/* + * Display mode initialization + */ +typedef void (*DisplayInitProc)(void); +typedef Bool (*AddScreenProc)(int index, ScreenPtr pScreen); +typedef Bool (*SetupScreenProc)(int index, ScreenPtr pScreen); +typedef void (*InitInputProc)(int argc, char **argv); + +/* + * Cursor functions + */ +typedef Bool (*InitCursorProc)(ScreenPtr pScreen); + +/* + * Suspend and resume X11 activity + */ +typedef void (*SuspendScreenProc)(ScreenPtr pScreen); +typedef void (*ResumeScreenProc)(ScreenPtr pScreen); + +/* + * Screen state change support + */ +typedef void (*AddPseudoramiXScreensProc) + (int *x, int *y, int *width, int *height, ScreenPtr pScreen); +typedef void (*UpdateScreenProc)(ScreenPtr pScreen); + +/* + * Rootless helper functions + */ +typedef Bool (*IsX11WindowProc)(void *nsWindow, int windowNumber); +typedef void (*HideWindowsProc)(Bool hide); + +/* + * Rootless functions for optional export to GLX layer + */ +typedef void * (*FrameForWindowProc)(WindowPtr pWin, Bool create); +typedef WindowPtr (*TopLevelParentProc)(WindowPtr pWindow); +typedef Bool (*CreateSurfaceProc) + (ScreenPtr pScreen, Drawable id, DrawablePtr pDrawable, + unsigned int client_id, unsigned int *surface_id, + unsigned int key[2], void (*notify) (void *arg, void *data), + void *notify_data); +typedef Bool (*DestroySurfaceProc) + (ScreenPtr pScreen, Drawable id, DrawablePtr pDrawable, + void (*notify) (void *arg, void *data), void *notify_data); + +/* + * Quartz display mode function list + */ +typedef struct _QuartzModeProcs { + DisplayInitProc DisplayInit; + AddScreenProc AddScreen; + SetupScreenProc SetupScreen; + InitInputProc InitInput; + + InitCursorProc InitCursor; + + SuspendScreenProc SuspendScreen; + ResumeScreenProc ResumeScreen; + + AddPseudoramiXScreensProc AddPseudoramiXScreens; + UpdateScreenProc UpdateScreen; + + IsX11WindowProc IsX11Window; + HideWindowsProc HideWindows; + + FrameForWindowProc FrameForWindow; + TopLevelParentProc TopLevelParent; + CreateSurfaceProc CreateSurface; + DestroySurfaceProc DestroySurface; +} QuartzModeProcsRec, *QuartzModeProcsPtr; + +extern QuartzModeProcsPtr quartzProcs; + +extern Bool XQuartzFullscreenVisible; /* Are the windows visible (predicated on !rootless) */ +extern Bool XQuartzServerVisible; /* Is the server visible ... TODO: Refactor to "active" */ +extern Bool XQuartzEnableKeyEquivalents; +extern Bool XQuartzRootlessDefault; /* Is our default mode rootless? */ +extern Bool XQuartzIsRootless; /* Is our current mode rootless (or FS)? */ +extern Bool XQuartzFullscreenMenu; /* Show the menu bar (autohide) while in FS */ +extern Bool XQuartzFullscreenDisableHotkeys; +extern Bool XQuartzOptionSendsAlt; /* Alt or Mode_switch? */ + +Bool QuartzAddScreen(int index, ScreenPtr pScreen); +Bool QuartzSetupScreen(int index, ScreenPtr pScreen); +void QuartzInitOutput(int argc,char **argv); +void QuartzInitInput(int argc, char **argv); +void QuartzInitServer(int argc, char **argv, char **envp); +void QuartzGiveUp(void); +void QuartzProcessEvent(xEvent *xe); +void QuartzUpdateScreens(void); + +void QuartzShow(void); +void QuartzHide(void); +void QuartzSetRootClip(BOOL enable); +void QuartzSpaceChanged(uint32_t space_id); + +void QuartzSetRootless(Bool state); +void QuartzShowFullscreen(Bool state); + +int server_main(int argc, char **argv, char **envp); +#endif diff --git a/xorg-server/hw/xquartz/quartzAudio.c b/xorg-server/hw/xquartz/quartzAudio.c deleted file mode 100644 index d17d65808..000000000 --- a/xorg-server/hw/xquartz/quartzAudio.c +++ /dev/null @@ -1,329 +0,0 @@ -// -// QuartzAudio.m -// -// X Window bell support using CoreAudio or AppKit. -// Greg Parker gparker@cs.stanford.edu 19 Feb 2001 -// -// Info about sine wave sound playback: -// CoreAudio code derived from macosx-dev posting by Tim Wood -// http://www.omnigroup.com/mailman/archive/macosx-dev/2000-May/002004.html -// Smoothing transitions between sounds -// http://www.wam.umd.edu/~mphoenix/dss/dss.html -// -/* - * Copyright (c) 2001 Greg Parker. All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Except as contained in this notice, the name(s) of the above copyright - * holders shall not be used in advertising or otherwise to promote the sale, - * use or other dealings in this Software without prior written authorization. - */ - -#include "sanitizedCarbon.h" - -#ifdef HAVE_DIX_CONFIG_H -#include -#endif - -#include "quartz.h" -#include "quartzAudio.h" - -#include -#include -#include - -#include "inputstr.h" -#include -#include - -void NSBeep(void); - -typedef struct QuartzAudioRec { - double frequency; - double amplitude; - - UInt32 curFrame; - UInt32 remainingFrames; - UInt32 totalFrames; - double sampleRate; - UInt32 fadeLength; - - UInt32 bufferByteCount; - Boolean playing; - pthread_mutex_t lock; - - // used to fade out interrupted sound and avoid 'pop' - double prevFrequency; - double prevAmplitude; - UInt32 prevFrame; -} QuartzAudioRec; - -static AudioDeviceID quartzAudioDevice = kAudioDeviceUnknown; -static QuartzAudioRec data; - - -/* - * QuartzAudioEnvelope - * Fade sound in and out to avoid pop. - * Sounds with shorter duration will never reach full amplitude. Deal. - */ -static double QuartzAudioEnvelope( - UInt32 curFrame, - UInt32 totalFrames, - UInt32 fadeLength ) -{ - double fadeFrames = min(fadeLength, totalFrames / 2); - if (fadeFrames < 1) return 0; - - if (curFrame < fadeFrames) { - return curFrame / fadeFrames; - } else if (curFrame > totalFrames - fadeFrames) { - return (totalFrames-curFrame) / fadeFrames; - } else { - return 1.0; - } -} - - -/* - * QuartzFillBuffer - * Fill this buffer with data and update the data position. - * FIXME: this is ugly - */ -static void QuartzFillBuffer( - AudioBuffer *audiobuffer, - QuartzAudioRec *data ) -{ - float *buffer, *b; - unsigned int frame, frameCount; - unsigned int bufferFrameCount; - float multiplier, v; - int i; - - buffer = (float *)audiobuffer->mData; - bufferFrameCount = audiobuffer->mDataByteSize / (sizeof(float) * audiobuffer->mNumberChannels); - - frameCount = min(bufferFrameCount, data->remainingFrames); - - // Fade out previous sine wave, if any. - b = buffer; - if (data->prevFrame) { - multiplier = 2*M_PI*(data->prevFrequency/data->sampleRate); - for (frame = 0; frame < data->fadeLength; frame++) { - v = data->prevAmplitude * - QuartzAudioEnvelope(frame+data->fadeLength, - 2*data->fadeLength, - data->fadeLength) * - sin(multiplier * (data->prevFrame+frame)); - for (i = 0; i < audiobuffer->mNumberChannels; i++) { - *b++ = v; - } - } - // no more prev fade - data->prevFrame = 0; - - // adjust for space eaten by prev fade - b += audiobuffer->mNumberChannels*frame; - bufferFrameCount -= frame; - frameCount = min(bufferFrameCount, data->remainingFrames); - } - - // Write a sine wave with the specified frequency and amplitude - multiplier = 2*M_PI*(data->frequency/data->sampleRate); - for (frame = 0; frame < frameCount; frame++) { - v = data->amplitude * - QuartzAudioEnvelope(data->curFrame+frame, data->totalFrames, - data->fadeLength) * - sin(multiplier * (data->curFrame+frame)); - for (i = 0; i < audiobuffer->mNumberChannels; i++) { - *b++ = v; - } - } - - // Zero out the rest of the buffer, if any - memset(b, 0, sizeof(float) * audiobuffer->mNumberChannels * - (bufferFrameCount-frame)); - - data->curFrame += frameCount; - data->remainingFrames -= frameCount; - if (data->remainingFrames == 0) { - data->playing = FALSE; - data->curFrame = 0; - } -} - - -/* - * QuartzAudioIOProc - * Callback function for audio playback. - * FIXME: use inOutputTime to correct for skipping - */ -static OSStatus -QuartzAudioIOProc( - AudioDeviceID inDevice, - const AudioTimeStamp *inNow, - const AudioBufferList *inInputData, - const AudioTimeStamp *inInputTime, - AudioBufferList *outOutputData, - const AudioTimeStamp *inOutputTime, - void *inClientData ) -{ - QuartzAudioRec *data = (QuartzAudioRec *)inClientData; - int i; - Boolean wasPlaying; - - pthread_mutex_lock(&data->lock); - wasPlaying = data->playing; - for (i = 0; i < outOutputData->mNumberBuffers; i++) { - if (data->playing) { - QuartzFillBuffer(outOutputData->mBuffers+i, data); - } - else { - memset(outOutputData->mBuffers[i].mData, 0, - outOutputData->mBuffers[i].mDataByteSize); - } - } - if (wasPlaying && !data->playing) { - OSStatus err; - err = AudioDeviceStop(inDevice, QuartzAudioIOProc); - if(err != noErr) - fprintf(stderr, "Error stopping audio device: %ld\n", (long int)err); - } - pthread_mutex_unlock(&data->lock); - return 0; -} - - -/* - * DDXRingBell - * Play a tone using the CoreAudio API - */ -void DDXRingBell( - int volume, // volume is % of max - int pitch, // pitch is Hz - int duration ) // duration is milliseconds -{ - if (XQuartzUseSysBeep) { - if (volume) - NSBeep(); - return; - } - - if (quartzAudioDevice == kAudioDeviceUnknown) return; - - pthread_mutex_lock(&data.lock); - - // fade previous sound, if any - data.prevFrequency = data.frequency; - data.prevAmplitude = data.amplitude; - data.prevFrame = data.curFrame; - - // set new sound - data.frequency = pitch; - data.amplitude = volume / 100.0; - data.curFrame = 0; - data.totalFrames = (int)(data.sampleRate * duration / 1000.0); - data.remainingFrames = data.totalFrames; - - if (! data.playing) { - OSStatus status; - status = AudioDeviceStart(quartzAudioDevice, QuartzAudioIOProc); - if (status) { - ErrorF("DDXRingBell: AudioDeviceStart returned %ld\n", (long)status); - } else { - data.playing = TRUE; - } - } - pthread_mutex_unlock(&data.lock); -} - -/* - * QuartzAudioInit - * Prepare to play the bell with the CoreAudio API - */ -void QuartzAudioInit(void) -{ - UInt32 propertySize; - OSStatus status; - AudioDeviceID outputDevice; - double sampleRate; - AudioObjectPropertyAddress devicePropertyAddress = { kAudioHardwarePropertyDefaultOutputDevice, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster }; - AudioObjectPropertyAddress sampleRatePropertyAddress = { kAudioDevicePropertyNominalSampleRate, kAudioDevicePropertyScopeOutput, kAudioObjectPropertyElementMaster }; - - // Get the default output device - propertySize = sizeof(outputDevice); - status = AudioObjectGetPropertyData(kAudioObjectSystemObject, &devicePropertyAddress, - 0, NULL, - &propertySize, &outputDevice); - if (status) { - ErrorF("QuartzAudioInit: AudioObjectGetPropertyData(output device) returned %ld\n", - (long)status); - return; - } - if (outputDevice == kAudioDeviceUnknown) { - ErrorF("QuartzAudioInit: No audio output devices available.\n"); - return; - } - - // Get the basic device description - sampleRate = 0.; - propertySize = sizeof(sampleRate); - status = AudioObjectGetPropertyData(outputDevice, &sampleRatePropertyAddress, - 0, NULL, - &propertySize, &sampleRate); - if (status) { - ErrorF("QuartzAudioInit: AudioObjectGetPropertyData(sample rate) returned %ld\n", - (long)status); - return; - } - - // Fill in the playback data - data.frequency = 0; - data.amplitude = 0; - data.curFrame = 0; - data.remainingFrames = 0; - data.sampleRate = sampleRate; - // data.bufferByteCount = bufferByteCount; - data.playing = FALSE; - data.prevAmplitude = 0; - data.prevFrame = 0; - data.prevFrequency = 0; - data.fadeLength = data.sampleRate / 200; - pthread_mutex_init(&data.lock, NULL); // fixme error check - - // fixme assert fadeLength= 1050 - { - AudioDeviceIOProcID sInputIOProcID = NULL; - status = AudioDeviceCreateIOProcID( outputDevice, QuartzAudioIOProc, &data, &sInputIOProcID ); - } -#else - status = AudioDeviceAddIOProc(outputDevice, QuartzAudioIOProc, &data); -#endif - if (status) { - ErrorF("QuartzAudioInit: AddIOProc returned %ld\n", (long)status); - return; - } - - // success! - quartzAudioDevice = outputDevice; -} diff --git a/xorg-server/hw/xquartz/quartzAudio.h b/xorg-server/hw/xquartz/quartzAudio.h deleted file mode 100644 index 2a78b3957..000000000 --- a/xorg-server/hw/xquartz/quartzAudio.h +++ /dev/null @@ -1,37 +0,0 @@ -// -// QuartzAudio.h -// -// X Window bell support using CoreAudio or AppKit. -// Greg Parker gparker@cs.stanford.edu 19 Feb 2001 -/* - * Copyright (c) 2001 Greg Parker. All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Except as contained in this notice, the name(s) of the above copyright - * holders shall not be used in advertising or otherwise to promote the sale, - * use or other dealings in this Software without prior written authorization. - */ - -#ifndef _QUARTZAUDIO_H -#define _QUARTZAUDIO_H - -void QuartzAudioInit(void); - -#endif diff --git a/xorg-server/hw/xquartz/quartzKeyboard.c b/xorg-server/hw/xquartz/quartzKeyboard.c index cd73ec5bd..54f709a8b 100644 --- a/xorg-server/hw/xquartz/quartzKeyboard.c +++ b/xorg-server/hw/xquartz/quartzKeyboard.c @@ -1,858 +1,857 @@ -/* - quartzKeyboard.c: Keyboard support for Xquartz - - Copyright (c) 2003-2008 Apple Inc. - Copyright (c) 2001-2004 Torrey T. Lyons. All Rights Reserved. - Copyright 2004 Kaleb S. KEITHLEY. All Rights Reserved. - - Copyright (C) 1999,2000 by Eric Sunshine - 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. - 3. The name of the author may not be used to endorse or promote products - derived from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. -*/ - -#include "sanitizedCarbon.h" - -#ifdef HAVE_DIX_CONFIG_H -#include -#endif - -#define HACK_MISSING 1 -#define HACK_KEYPAD 1 -#define HACK_BLACKLIST 1 - -#include -#include -#include -#include -#include -#include - -#include "quartz.h" -#include "darwin.h" -#include "darwinEvents.h" - -#include "quartzKeyboard.h" -#include "quartzAudio.h" - -#include "X11Application.h" - -#include "threadSafety.h" - -#ifdef NDEBUG -#undef NDEBUG -#include -#define NDEBUG 1 -#else -#include -#endif -#include - -#include "xkbsrv.h" -#include "exevents.h" -#include "X11/keysym.h" -#include "keysym2ucs.h" - -extern void -CopyKeyClass(DeviceIntPtr device, DeviceIntPtr master); - -enum { - MOD_COMMAND = 256, - MOD_SHIFT = 512, - MOD_OPTION = 2048, - MOD_CONTROL = 4096, -}; - -#define UKEYSYM(u) ((u) | 0x01000000) - -#if HACK_MISSING -/* Table of keycode->keysym mappings we use to fallback on for important - keys that are often not in the Unicode mapping. */ - -const static struct { - unsigned short keycode; - KeySym keysym; -} known_keys[] = { - {55, XK_Meta_L}, - {56, XK_Shift_L}, - {57, XK_Caps_Lock}, - {58, XK_Alt_L}, - {59, XK_Control_L}, - - {60, XK_Shift_R}, - {61, XK_Alt_R}, - {62, XK_Control_R}, - {63, XK_Meta_R}, - - {122, XK_F1}, - {120, XK_F2}, - {99, XK_F3}, - {118, XK_F4}, - {96, XK_F5}, - {97, XK_F6}, - {98, XK_F7}, - {100, XK_F8}, - {101, XK_F9}, - {109, XK_F10}, - {103, XK_F11}, - {111, XK_F12}, - {105, XK_F13}, - {107, XK_F14}, - {113, XK_F15}, -}; -#endif - -#if HACK_KEYPAD -/* Table of keycode->old,new-keysym mappings we use to fixup the numeric - keypad entries. */ - -const static struct { - unsigned short keycode; - KeySym normal, keypad; -} known_numeric_keys[] = { - {65, XK_period, XK_KP_Decimal}, - {67, XK_asterisk, XK_KP_Multiply}, - {69, XK_plus, XK_KP_Add}, - {75, XK_slash, XK_KP_Divide}, - {76, 0x01000003, XK_KP_Enter}, - {78, XK_minus, XK_KP_Subtract}, - {81, XK_equal, XK_KP_Equal}, - {82, XK_0, XK_KP_0}, - {83, XK_1, XK_KP_1}, - {84, XK_2, XK_KP_2}, - {85, XK_3, XK_KP_3}, - {86, XK_4, XK_KP_4}, - {87, XK_5, XK_KP_5}, - {88, XK_6, XK_KP_6}, - {89, XK_7, XK_KP_7}, - {91, XK_8, XK_KP_8}, - {92, XK_9, XK_KP_9}, -}; -#endif - -#if HACK_BLACKLIST -/* wine notepad produces wrong characters on shift+arrow - * http://xquartz.macosforge.org/trac/ticket/295 - * http://developer.apple.com/legacy/mac/library/documentation/mac/Text/Text-579.html - * - * legacy Mac keycodes for arrow keys that shift-modify to math symbols - */ -const static unsigned short keycode_blacklist[] = {66, 70, 72, 77}; -#endif - -/* Table mapping normal keysyms to their dead equivalents. - FIXME: all the unicode keysyms (apart from circumflex) were guessed. */ - -const static struct { - KeySym normal, dead; -} dead_keys[] = { - {XK_grave, XK_dead_grave}, - {XK_apostrophe, XK_dead_acute}, /* US:"=" on a Czech keyboard */ - {XK_acute, XK_dead_acute}, - {UKEYSYM (0x384), XK_dead_acute}, /* US:";" on a Greek keyboard */ -// {XK_Greek_accentdieresis, XK_dead_diaeresis}, /* US:"opt+;" on a Greek keyboard ... replace with dead_accentdieresis if there is one */ - {XK_asciicircum, XK_dead_circumflex}, - {UKEYSYM (0x2c6), XK_dead_circumflex}, /* MODIFIER LETTER CIRCUMFLEX ACCENT */ - {XK_asciitilde, XK_dead_tilde}, - {UKEYSYM (0x2dc), XK_dead_tilde}, /* SMALL TILDE */ - {XK_macron, XK_dead_macron}, - {XK_breve, XK_dead_breve}, - {XK_abovedot, XK_dead_abovedot}, - {XK_diaeresis, XK_dead_diaeresis}, - {UKEYSYM (0x2da), XK_dead_abovering}, /* DOT ABOVE */ - {XK_doubleacute, XK_dead_doubleacute}, - {XK_caron, XK_dead_caron}, - {XK_cedilla, XK_dead_cedilla}, - {XK_ogonek, XK_dead_ogonek}, - {UKEYSYM (0x269), XK_dead_iota}, /* LATIN SMALL LETTER IOTA */ - {UKEYSYM (0x2ec), XK_dead_voiced_sound}, /* MODIFIER LETTER VOICING */ -/* {XK_semivoiced_sound, XK_dead_semivoiced_sound}, */ - {UKEYSYM (0x323), XK_dead_belowdot}, /* COMBINING DOT BELOW */ - {UKEYSYM (0x309), XK_dead_hook}, /* COMBINING HOOK ABOVE */ - {UKEYSYM (0x31b), XK_dead_horn}, /* COMBINING HORN */ -}; - -typedef struct darwinKeyboardInfo_struct { - CARD8 modMap[MAP_LENGTH]; - KeySym keyMap[MAP_LENGTH * GLYPHS_PER_KEY]; - unsigned char modifierKeycodes[32][2]; -} darwinKeyboardInfo; - -darwinKeyboardInfo keyInfo; -pthread_mutex_t keyInfo_mutex = PTHREAD_MUTEX_INITIALIZER; - -static void DarwinChangeKeyboardControl(DeviceIntPtr device, KeybdCtrl *ctrl) { - // FIXME: to be implemented - // keyclick, bell volume / pitch, autorepead, LED's -} - -//----------------------------------------------------------------------------- -// Utility functions to help parse Darwin keymap -//----------------------------------------------------------------------------- - -/* - * DarwinBuildModifierMaps - * Use the keyMap field of keyboard info structure to populate - * the modMap and modifierKeycodes fields. - */ -static void DarwinBuildModifierMaps(darwinKeyboardInfo *info) { - int i; - KeySym *k; - - memset(info->modMap, NoSymbol, sizeof(info->modMap)); - memset(info->modifierKeycodes, 0, sizeof(info->modifierKeycodes)); - - for (i = 0; i < NUM_KEYCODES; i++) { - k = info->keyMap + i * GLYPHS_PER_KEY; - - switch (*k) { - case XK_Shift_L: - info->modifierKeycodes[NX_MODIFIERKEY_SHIFT][0] = i; - info->modMap[MIN_KEYCODE + i] = ShiftMask; - break; - - case XK_Shift_R: -#ifdef NX_MODIFIERKEY_RSHIFT - info->modifierKeycodes[NX_MODIFIERKEY_RSHIFT][0] = i; -#else - info->modifierKeycodes[NX_MODIFIERKEY_SHIFT][0] = i; -#endif - info->modMap[MIN_KEYCODE + i] = ShiftMask; - break; - - case XK_Control_L: - info->modifierKeycodes[NX_MODIFIERKEY_CONTROL][0] = i; - info->modMap[MIN_KEYCODE + i] = ControlMask; - break; - - case XK_Control_R: -#ifdef NX_MODIFIERKEY_RCONTROL - info->modifierKeycodes[NX_MODIFIERKEY_RCONTROL][0] = i; -#else - info->modifierKeycodes[NX_MODIFIERKEY_CONTROL][0] = i; -#endif - info->modMap[MIN_KEYCODE + i] = ControlMask; - break; - - case XK_Caps_Lock: - info->modifierKeycodes[NX_MODIFIERKEY_ALPHALOCK][0] = i; - info->modMap[MIN_KEYCODE + i] = LockMask; - break; - - case XK_Alt_L: - info->modifierKeycodes[NX_MODIFIERKEY_ALTERNATE][0] = i; - info->modMap[MIN_KEYCODE + i] = Mod1Mask; - if(!XQuartzOptionSendsAlt) - *k = XK_Mode_switch; // Yes, this is ugly. This needs to be cleaned up when we integrate quartzKeyboard with this code and refactor. - break; - - case XK_Alt_R: -#ifdef NX_MODIFIERKEY_RALTERNATE - info->modifierKeycodes[NX_MODIFIERKEY_RALTERNATE][0] = i; -#else - info->modifierKeycodes[NX_MODIFIERKEY_ALTERNATE][0] = i; -#endif - if(!XQuartzOptionSendsAlt) - *k = XK_Mode_switch; // Yes, this is ugly. This needs to be cleaned up when we integrate quartzKeyboard with this code and refactor. - info->modMap[MIN_KEYCODE + i] = Mod1Mask; - break; - - case XK_Mode_switch: - ErrorF("DarwinBuildModifierMaps: XK_Mode_switch encountered, unable to determine side.\n"); - info->modifierKeycodes[NX_MODIFIERKEY_ALTERNATE][0] = i; -#ifdef NX_MODIFIERKEY_RALTERNATE - info->modifierKeycodes[NX_MODIFIERKEY_RALTERNATE][0] = i; -#endif - info->modMap[MIN_KEYCODE + i] = Mod1Mask; - break; - - case XK_Meta_L: - info->modifierKeycodes[NX_MODIFIERKEY_COMMAND][0] = i; - info->modMap[MIN_KEYCODE + i] = Mod2Mask; - break; - - case XK_Meta_R: -#ifdef NX_MODIFIERKEY_RCOMMAND - info->modifierKeycodes[NX_MODIFIERKEY_RCOMMAND][0] = i; -#else - info->modifierKeycodes[NX_MODIFIERKEY_COMMAND][0] = i; -#endif - info->modMap[MIN_KEYCODE + i] = Mod2Mask; - break; - - case XK_Num_Lock: - info->modMap[MIN_KEYCODE + i] = Mod3Mask; - break; - } - } -} - -/* - * DarwinKeyboardInit - * Get the Darwin keyboard map and compute an equivalent - * X keyboard map and modifier map. Set the new keyboard - * device structure. - */ -void DarwinKeyboardInit(DeviceIntPtr pDev) { - // Open a shared connection to the HID System. - // Note that the Event Status Driver is really just a wrapper - // for a kIOHIDParamConnectType connection. - assert(darwinParamConnect = NXOpenEventStatus()); - - InitKeyboardDeviceStruct(pDev, NULL, NULL, DarwinChangeKeyboardControl); - - DarwinKeyboardReloadHandler(); - - CopyKeyClass(pDev, inputInfo.keyboard); -} - -/* Set the repeat rates based on global preferences and keycodes for modifiers. - * Precondition: Has the keyInfo_mutex lock. - */ -static void DarwinKeyboardSetRepeat(DeviceIntPtr pDev, int initialKeyRepeatValue, int keyRepeatValue) { - if(initialKeyRepeatValue == 300000) { // off - /* Turn off repeats globally */ - XkbSetRepeatKeys(pDev, -1, AutoRepeatModeOff); - } else { - int i; - XkbControlsPtr ctrl; - XkbControlsRec old; - - /* Turn on repeats globally */ - XkbSetRepeatKeys(pDev, -1, AutoRepeatModeOn); - - /* Setup the bit mask for individual key repeats */ - ctrl = pDev->key->xkbInfo->desc->ctrls; - old= *ctrl; - - ctrl->repeat_delay = initialKeyRepeatValue * 15; - ctrl->repeat_interval = keyRepeatValue * 15; - - /* Turn off key-repeat for modifier keys, on for others */ - /* First set them all on */ - for(i=0; i < XkbPerKeyBitArraySize; i++) - ctrl->per_key_repeat[i] = -1; - - /* Now turn off the modifiers */ - for(i=0; i < 32; i++) { - unsigned char keycode; - - keycode = keyInfo.modifierKeycodes[i][0]; - if(keycode) - ClearBit(ctrl->per_key_repeat, keycode + MIN_KEYCODE); - - keycode = keyInfo.modifierKeycodes[i][1]; - if(keycode) - ClearBit(ctrl->per_key_repeat, keycode + MIN_KEYCODE); - } - - /* Hurray for data duplication */ - if (pDev->kbdfeed) - memcpy(pDev->kbdfeed->ctrl.autoRepeats, ctrl->per_key_repeat, XkbPerKeyBitArraySize); - - //fprintf(stderr, "per_key_repeat =\n"); - //for(i=0; i < XkbPerKeyBitArraySize; i++) - // fprintf(stderr, "%02x%s", ctrl->per_key_repeat[i], (i + 1) & 7 ? "" : "\n"); - - /* And now we notify the puppies about the changes */ - XkbDDXChangeControls(pDev, &old, ctrl); - } -} - -void DarwinKeyboardReloadHandler(void) { - KeySymsRec keySyms; - CFIndex initialKeyRepeatValue, keyRepeatValue; - BOOL ok; - DeviceIntPtr pDev; - const char *xmodmap = PROJECTROOT "/bin/xmodmap"; - const char *sysmodmap = PROJECTROOT "/lib/X11/xinit/.Xmodmap"; - const char *homedir = getenv("HOME"); - char usermodmap[PATH_MAX], cmd[PATH_MAX]; - - DEBUG_LOG("DarwinKeyboardReloadHandler\n"); - - /* Get our key repeat settings from GlobalPreferences */ - (void)CFPreferencesAppSynchronize(CFSTR(".GlobalPreferences")); - - initialKeyRepeatValue = CFPreferencesGetAppIntegerValue(CFSTR("InitialKeyRepeat"), CFSTR(".GlobalPreferences"), &ok); - if(!ok) - initialKeyRepeatValue = 35; - - keyRepeatValue = CFPreferencesGetAppIntegerValue(CFSTR("KeyRepeat"), CFSTR(".GlobalPreferences"), &ok); - if(!ok) - keyRepeatValue = 6; - - pthread_mutex_lock(&keyInfo_mutex); { - /* Initialize our keySyms */ - keySyms.map = keyInfo.keyMap; - keySyms.mapWidth = GLYPHS_PER_KEY; - keySyms.minKeyCode = MIN_KEYCODE; - keySyms.maxKeyCode = MAX_KEYCODE; - - // TODO: We should build the entire XkbDescRec and use XkbCopyKeymap - /* Apply the mappings to darwinKeyboard */ - XkbApplyMappingChange(darwinKeyboard, &keySyms, keySyms.minKeyCode, - keySyms.maxKeyCode - keySyms.minKeyCode + 1, - keyInfo.modMap, serverClient); - DarwinKeyboardSetRepeat(darwinKeyboard, initialKeyRepeatValue, keyRepeatValue); - - /* Apply the mappings to the core keyboard */ - for (pDev = inputInfo.devices; pDev; pDev = pDev->next) { - if ((pDev->coreEvents || pDev == inputInfo.keyboard) && pDev->key) { - XkbApplyMappingChange(pDev, &keySyms, keySyms.minKeyCode, - keySyms.maxKeyCode - keySyms.minKeyCode + 1, - keyInfo.modMap, serverClient); - DarwinKeyboardSetRepeat(pDev, initialKeyRepeatValue, keyRepeatValue); - } - } - } pthread_mutex_unlock(&keyInfo_mutex); - - /* Modify with xmodmap */ - if (access(xmodmap, F_OK) == 0) { - /* Check for system .Xmodmap */ - if (access(sysmodmap, F_OK) == 0) { - if(snprintf (cmd, sizeof(cmd), "%s %s", xmodmap, sysmodmap) < sizeof(cmd)) { - X11ApplicationLaunchClient(cmd); - } else { - ErrorF("X11.app: Unable to create / execute xmodmap command line"); - } - } - - /* Check for user's local .Xmodmap */ - if ((homedir != NULL) && (snprintf (usermodmap, sizeof(usermodmap), "%s/.Xmodmap", homedir) < sizeof(usermodmap))) { - if (access(usermodmap, F_OK) == 0) { - if(snprintf (cmd, sizeof(cmd), "%s %s", xmodmap, usermodmap) < sizeof(cmd)) { - X11ApplicationLaunchClient(cmd); - } else { - ErrorF("X11.app: Unable to create / execute xmodmap command line"); - } - } - } else { - ErrorF("X11.app: Unable to determine path to user's .Xmodmap"); - } - } -} - -//----------------------------------------------------------------------------- -// Modifier translation functions -// -// There are three different ways to specify a Mac modifier key: -// keycode - specifies hardware key, read from keymapping -// key - NX_MODIFIERKEY_*, really an index -// mask - NX_*MASK, mask for modifier flags in event record -// Left and right side have different keycodes but the same key and mask. -//----------------------------------------------------------------------------- - -/* - * DarwinModifierNXKeyToNXKeycode - * Return the keycode for an NX_MODIFIERKEY_* modifier. - * side = 0 for left or 1 for right. - * Returns 0 if key+side is not a known modifier. - */ -int DarwinModifierNXKeyToNXKeycode(int key, int side) { - int retval; - pthread_mutex_lock(&keyInfo_mutex); - retval = keyInfo.modifierKeycodes[key][side]; - pthread_mutex_unlock(&keyInfo_mutex); - - return retval; -} - -/* - * DarwinModifierNXKeycodeToNXKey - * Returns -1 if keycode+side is not a modifier key - * outSide may be NULL, else it gets 0 for left and 1 for right. - */ -int DarwinModifierNXKeycodeToNXKey(unsigned char keycode, int *outSide) { - int key, side; - - keycode += MIN_KEYCODE; - - // search modifierKeycodes for this keycode+side - pthread_mutex_lock(&keyInfo_mutex); - for (key = 0; key < NX_NUMMODIFIERS; key++) { - for (side = 0; side <= 1; side++) { - if (keyInfo.modifierKeycodes[key][side] == keycode) break; - } - } - pthread_mutex_unlock(&keyInfo_mutex); - - if (key == NX_NUMMODIFIERS) { - return -1; - } - if (outSide) *outSide = side; - - return key; -} - -/* - * DarwinModifierNXMaskToNXKey - * Returns -1 if mask is not a known modifier mask. - */ -int DarwinModifierNXMaskToNXKey(int mask) { - switch (mask) { - case NX_ALPHASHIFTMASK: return NX_MODIFIERKEY_ALPHALOCK; - case NX_SHIFTMASK: return NX_MODIFIERKEY_SHIFT; -#ifdef NX_DEVICELSHIFTKEYMASK - case NX_DEVICELSHIFTKEYMASK: return NX_MODIFIERKEY_SHIFT; - case NX_DEVICERSHIFTKEYMASK: return NX_MODIFIERKEY_RSHIFT; -#endif - case NX_CONTROLMASK: return NX_MODIFIERKEY_CONTROL; -#ifdef NX_DEVICELCTLKEYMASK - case NX_DEVICELCTLKEYMASK: return NX_MODIFIERKEY_CONTROL; - case NX_DEVICERCTLKEYMASK: return NX_MODIFIERKEY_RCONTROL; -#endif - case NX_ALTERNATEMASK: return NX_MODIFIERKEY_ALTERNATE; -#ifdef NX_DEVICELALTKEYMASK - case NX_DEVICELALTKEYMASK: return NX_MODIFIERKEY_ALTERNATE; - case NX_DEVICERALTKEYMASK: return NX_MODIFIERKEY_RALTERNATE; -#endif - case NX_COMMANDMASK: return NX_MODIFIERKEY_COMMAND; -#ifdef NX_DEVICELCMDKEYMASK - case NX_DEVICELCMDKEYMASK: return NX_MODIFIERKEY_COMMAND; - case NX_DEVICERCMDKEYMASK: return NX_MODIFIERKEY_RCOMMAND; -#endif - case NX_NUMERICPADMASK: return NX_MODIFIERKEY_NUMERICPAD; - case NX_HELPMASK: return NX_MODIFIERKEY_HELP; - case NX_SECONDARYFNMASK: return NX_MODIFIERKEY_SECONDARYFN; - } - return -1; -} - -/* - * DarwinModifierNXKeyToNXMask - * Returns 0 if key is not a known modifier key. - */ -int DarwinModifierNXKeyToNXMask(int key) { - switch (key) { - case NX_MODIFIERKEY_ALPHALOCK: return NX_ALPHASHIFTMASK; -#ifdef NX_DEVICELSHIFTKEYMASK - case NX_MODIFIERKEY_SHIFT: return NX_DEVICELSHIFTKEYMASK; - case NX_MODIFIERKEY_RSHIFT: return NX_DEVICERSHIFTKEYMASK; - case NX_MODIFIERKEY_CONTROL: return NX_DEVICELCTLKEYMASK; - case NX_MODIFIERKEY_RCONTROL: return NX_DEVICERCTLKEYMASK; - case NX_MODIFIERKEY_ALTERNATE: return NX_DEVICELALTKEYMASK; - case NX_MODIFIERKEY_RALTERNATE: return NX_DEVICERALTKEYMASK; - case NX_MODIFIERKEY_COMMAND: return NX_DEVICELCMDKEYMASK; - case NX_MODIFIERKEY_RCOMMAND: return NX_DEVICERCMDKEYMASK; -#else - case NX_MODIFIERKEY_SHIFT: return NX_SHIFTMASK; - case NX_MODIFIERKEY_CONTROL: return NX_CONTROLMASK; - case NX_MODIFIERKEY_ALTERNATE: return NX_ALTERNATEMASK; - case NX_MODIFIERKEY_COMMAND: return NX_COMMANDMASK; -#endif - case NX_MODIFIERKEY_NUMERICPAD: return NX_NUMERICPADMASK; - case NX_MODIFIERKEY_HELP: return NX_HELPMASK; - case NX_MODIFIERKEY_SECONDARYFN: return NX_SECONDARYFNMASK; - } - return 0; -} - -/* - * DarwinModifierStringToNXMask - * Returns 0 if string is not a known modifier. - */ -int DarwinModifierStringToNXMask(const char *str, int separatelr) { -#ifdef NX_DEVICELSHIFTKEYMASK - if(separatelr) { - if (!strcasecmp(str, "shift")) return NX_DEVICELSHIFTKEYMASK | NX_DEVICERSHIFTKEYMASK; - if (!strcasecmp(str, "control")) return NX_DEVICELCTLKEYMASK | NX_DEVICERCTLKEYMASK; - if (!strcasecmp(str, "option")) return NX_DEVICELALTKEYMASK | NX_DEVICERALTKEYMASK; - if (!strcasecmp(str, "alt")) return NX_DEVICELALTKEYMASK | NX_DEVICERALTKEYMASK; - if (!strcasecmp(str, "command")) return NX_DEVICELCMDKEYMASK | NX_DEVICERCMDKEYMASK; - if (!strcasecmp(str, "lshift")) return NX_DEVICELSHIFTKEYMASK; - if (!strcasecmp(str, "rshift")) return NX_DEVICERSHIFTKEYMASK; - if (!strcasecmp(str, "lcontrol")) return NX_DEVICELCTLKEYMASK; - if (!strcasecmp(str, "rcontrol")) return NX_DEVICERCTLKEYMASK; - if (!strcasecmp(str, "loption")) return NX_DEVICELALTKEYMASK; - if (!strcasecmp(str, "roption")) return NX_DEVICERALTKEYMASK; - if (!strcasecmp(str, "lalt")) return NX_DEVICELALTKEYMASK; - if (!strcasecmp(str, "ralt")) return NX_DEVICERALTKEYMASK; - if (!strcasecmp(str, "lcommand")) return NX_DEVICELCMDKEYMASK; - if (!strcasecmp(str, "rcommand")) return NX_DEVICERCMDKEYMASK; - } else { -#endif - if (!strcasecmp(str, "shift")) return NX_SHIFTMASK; - if (!strcasecmp(str, "control")) return NX_CONTROLMASK; - if (!strcasecmp(str, "option")) return NX_ALTERNATEMASK; - if (!strcasecmp(str, "alt")) return NX_ALTERNATEMASK; - if (!strcasecmp(str, "command")) return NX_COMMANDMASK; - if (!strcasecmp(str, "lshift")) return NX_SHIFTMASK; - if (!strcasecmp(str, "rshift")) return NX_SHIFTMASK; - if (!strcasecmp(str, "lcontrol")) return NX_CONTROLMASK; - if (!strcasecmp(str, "rcontrol")) return NX_CONTROLMASK; - if (!strcasecmp(str, "loption")) return NX_ALTERNATEMASK; - if (!strcasecmp(str, "roption")) return NX_ALTERNATEMASK; - if (!strcasecmp(str, "lalt")) return NX_ALTERNATEMASK; - if (!strcasecmp(str, "ralt")) return NX_ALTERNATEMASK; - if (!strcasecmp(str, "lcommand")) return NX_COMMANDMASK; - if (!strcasecmp(str, "rcommand")) return NX_COMMANDMASK; -#ifdef NX_DEVICELSHIFTKEYMASK - } -#endif - if (!strcasecmp(str, "lock")) return NX_ALPHASHIFTMASK; - if (!strcasecmp(str, "fn")) return NX_SECONDARYFNMASK; - if (!strcasecmp(str, "help")) return NX_HELPMASK; - if (!strcasecmp(str, "numlock")) return NX_NUMERICPADMASK; - return 0; -} - -/* - * LegalModifier - * This allows the ddx layer to prevent some keys from being remapped - * as modifier keys. - */ -Bool LegalModifier(unsigned int key, DeviceIntPtr pDev) -{ - return 1; -} - -static inline UniChar macroman2ucs(unsigned char c) { - /* Precalculated table mapping MacRoman-128 to Unicode. Generated - by creating single element CFStringRefs then extracting the - first character. */ - - static const unsigned short table[128] = { - 0xc4, 0xc5, 0xc7, 0xc9, 0xd1, 0xd6, 0xdc, 0xe1, - 0xe0, 0xe2, 0xe4, 0xe3, 0xe5, 0xe7, 0xe9, 0xe8, - 0xea, 0xeb, 0xed, 0xec, 0xee, 0xef, 0xf1, 0xf3, - 0xf2, 0xf4, 0xf6, 0xf5, 0xfa, 0xf9, 0xfb, 0xfc, - 0x2020, 0xb0, 0xa2, 0xa3, 0xa7, 0x2022, 0xb6, 0xdf, - 0xae, 0xa9, 0x2122, 0xb4, 0xa8, 0x2260, 0xc6, 0xd8, - 0x221e, 0xb1, 0x2264, 0x2265, 0xa5, 0xb5, 0x2202, 0x2211, - 0x220f, 0x3c0, 0x222b, 0xaa, 0xba, 0x3a9, 0xe6, 0xf8, - 0xbf, 0xa1, 0xac, 0x221a, 0x192, 0x2248, 0x2206, 0xab, - 0xbb, 0x2026, 0xa0, 0xc0, 0xc3, 0xd5, 0x152, 0x153, - 0x2013, 0x2014, 0x201c, 0x201d, 0x2018, 0x2019, 0xf7, 0x25ca, - 0xff, 0x178, 0x2044, 0x20ac, 0x2039, 0x203a, 0xfb01, 0xfb02, - 0x2021, 0xb7, 0x201a, 0x201e, 0x2030, 0xc2, 0xca, 0xc1, - 0xcb, 0xc8, 0xcd, 0xce, 0xcf, 0xcc, 0xd3, 0xd4, - 0xf8ff, 0xd2, 0xda, 0xdb, 0xd9, 0x131, 0x2c6, 0x2dc, - 0xaf, 0x2d8, 0x2d9, 0x2da, 0xb8, 0x2dd, 0x2db, 0x2c7, - }; - - if (c < 128) return c; - else return table[c - 128]; -} - -static KeySym make_dead_key(KeySym in) { - int i; - - for (i = 0; i < sizeof (dead_keys) / sizeof (dead_keys[0]); i++) - if (dead_keys[i].normal == in) return dead_keys[i].dead; - - return in; -} - -static Bool QuartzReadSystemKeymap(darwinKeyboardInfo *info) { -#if !defined(__LP64__) || MAC_OS_X_VERSION_MIN_REQUIRED < 1050 - KeyboardLayoutRef key_layout; - int is_uchr = 1; -#endif - const void *chr_data = NULL; - int num_keycodes = NUM_KEYCODES; - UInt32 keyboard_type = LMGetKbdType(); - int i, j; - OSStatus err; - KeySym *k; - CFDataRef currentKeyLayoutDataRef = NULL; - -#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050 - TISInputSourceRef currentKeyLayoutRef = TISCopyCurrentKeyboardLayoutInputSource(); - - if (currentKeyLayoutRef) { - currentKeyLayoutDataRef = (CFDataRef )TISGetInputSourceProperty(currentKeyLayoutRef, kTISPropertyUnicodeKeyLayoutData); - if (currentKeyLayoutDataRef) - chr_data = CFDataGetBytePtr(currentKeyLayoutDataRef); - } -#endif - -#if !defined(__LP64__) || MAC_OS_X_VERSION_MIN_REQUIRED < 1050 - if (chr_data == NULL) { -#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050 - ErrorF("X11.app: Error detected in determining keyboard layout. If you are using an Apple-provided keyboard layout, please report this error at http://xquartz.macosforge.org and http://bugreport.apple.com\n"); - ErrorF("X11.app: Debug Info: keyboard_type=%u, currentKeyLayoutRef=%p, currentKeyLayoutDataRef=%p, chr_data=%p\n", - (unsigned)keyboard_type, currentKeyLayoutRef, currentKeyLayoutDataRef, chr_data); -#endif - - KLGetCurrentKeyboardLayout (&key_layout); - KLGetKeyboardLayoutProperty (key_layout, kKLuchrData, &chr_data); - -#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050 - if(chr_data != NULL) { - ErrorF("X11.app: Fallback succeeded, but this is still a bug. Please report the above information.\n"); - } -#endif - } - - if (chr_data == NULL) { - ErrorF("X11.app: Debug Info: kKLuchrData failed, trying kKLKCHRData.\n"); - ErrorF("If you are using a 3rd party keyboard layout, please see http://xquartz.macosforge.org/trac/ticket/154\n"); - KLGetKeyboardLayoutProperty (key_layout, kKLKCHRData, &chr_data); - is_uchr = 0; - num_keycodes = 128; - -#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050 - if(chr_data != NULL) { - ErrorF("X11.app: Fallback succeeded, but this is still a bug. Please report the above information.\n"); - } -#endif - } -#endif - -#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050 - if(currentKeyLayoutRef) - CFRelease(currentKeyLayoutRef); -#endif - - if (chr_data == NULL) { - ErrorF ( "Couldn't get uchr or kchr resource\n"); - return FALSE; - } - - /* Scan the keycode range for the Unicode character that each - key produces in the four shift states. Then convert that to - an X11 keysym (which may just the bit that says "this is - Unicode" if it can't find the real symbol.) */ - - /* KeyTranslate is not available on 64-bit platforms; UCKeyTranslate - must be used instead. */ - - for (i = 0; i < num_keycodes; i++) { - static const int mods[4] = {0, MOD_SHIFT, MOD_OPTION, - MOD_OPTION | MOD_SHIFT}; - - k = info->keyMap + i * GLYPHS_PER_KEY; - - for (j = 0; j < 4; j++) { -#if !defined(__LP64__) || MAC_OS_X_VERSION_MIN_REQUIRED < 1050 - if (is_uchr) { -#endif - UniChar s[8]; - UniCharCount len; - UInt32 dead_key_state = 0, extra_dead = 0; - - err = UCKeyTranslate (chr_data, i, kUCKeyActionDown, - mods[j] >> 8, keyboard_type, 0, - &dead_key_state, 8, &len, s); - if (err != noErr) continue; - - if (len == 0 && dead_key_state != 0) { - /* Found a dead key. Work out which one it is, but - remembering that it's dead. */ - err = UCKeyTranslate (chr_data, i, kUCKeyActionDown, - mods[j] >> 8, keyboard_type, - kUCKeyTranslateNoDeadKeysMask, - &extra_dead, 8, &len, s); - if (err != noErr) continue; - } - - /* Not sure why 0x0010 is there. - * 0x0000 - 'Unicode Hex Input' ... - */ - if (len > 0 && s[0] != 0x0010 && s[0] != 0x0000) { - k[j] = ucs2keysym (s[0]); - if (dead_key_state != 0) k[j] = make_dead_key (k[j]); - } -#if !defined(__LP64__) || MAC_OS_X_VERSION_MIN_REQUIRED < 1050 - } else { // kchr - UInt32 c, state = 0, state2 = 0; - UInt16 code; - - code = i | mods[j]; - c = KeyTranslate (chr_data, code, &state); - - /* Dead keys are only processed on key-down, so ask - to translate those events. When we find a dead key, - translating the matching key up event will give - us the actual dead character. */ - - if (state != 0) - c = KeyTranslate (chr_data, code | 128, &state2); - - /* Characters seem to be in MacRoman encoding. */ - - if (c != 0 && c != 0x0010) { - k[j] = ucs2keysym (macroman2ucs (c & 255)); - - if (state != 0) k[j] = make_dead_key (k[j]); - } - } -#endif - } - - if (k[3] == k[2]) k[3] = NoSymbol; - if (k[1] == k[0]) k[1] = NoSymbol; - if (k[0] == k[2] && k[1] == k[3]) k[2] = k[3] = NoSymbol; - if (k[3] == k[0] && k[2] == k[1] && k[2] == NoSymbol) k[3] = NoSymbol; - } - -#if HACK_MISSING - /* Fix up some things that are normally missing.. */ - - for (i = 0; i < sizeof (known_keys) / sizeof (known_keys[0]); i++) { - k = info->keyMap + known_keys[i].keycode * GLYPHS_PER_KEY; - - if ( k[0] == NoSymbol && k[1] == NoSymbol - && k[2] == NoSymbol && k[3] == NoSymbol) - k[0] = known_keys[i].keysym; - } -#endif - -#if HACK_KEYPAD - /* And some more things. We find the right symbols for the numeric - keypad, but not the KP_ keysyms. So try to convert known keycodes. */ - for (i = 0; i < sizeof (known_numeric_keys) / sizeof (known_numeric_keys[0]); i++) { - k = info->keyMap + known_numeric_keys[i].keycode * GLYPHS_PER_KEY; - - if (k[0] == known_numeric_keys[i].normal) - k[0] = known_numeric_keys[i].keypad; - } -#endif - -#if HACK_BLACKLIST - for (i = 0; i < sizeof (keycode_blacklist) / sizeof (keycode_blacklist[0]); i++) { - k = info->keyMap + keycode_blacklist[i] * GLYPHS_PER_KEY; - k[0] = k[1] = k[2] = k[3] = NoSymbol; - } -#endif - - DarwinBuildModifierMaps(info); - - return TRUE; -} - -Bool QuartsResyncKeymap(Bool sendDDXEvent) { - Bool retval; - /* Update keyInfo */ - pthread_mutex_lock(&keyInfo_mutex); - memset(keyInfo.keyMap, 0, sizeof(keyInfo.keyMap)); - retval = QuartzReadSystemKeymap(&keyInfo); - pthread_mutex_unlock(&keyInfo_mutex); - - /* Tell server thread to deal with new keyInfo */ - if(sendDDXEvent) - DarwinSendDDXEvent(kXquartzReloadKeymap, 0); - - return retval; -} +/* + quartzKeyboard.c: Keyboard support for Xquartz + + Copyright (c) 2003-2008 Apple Inc. + Copyright (c) 2001-2004 Torrey T. Lyons. All Rights Reserved. + Copyright 2004 Kaleb S. KEITHLEY. All Rights Reserved. + + Copyright (C) 1999,2000 by Eric Sunshine + 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. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. +*/ + +#include "sanitizedCarbon.h" + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#define HACK_MISSING 1 +#define HACK_KEYPAD 1 +#define HACK_BLACKLIST 1 + +#include +#include +#include +#include +#include +#include + +#include "quartz.h" +#include "darwin.h" +#include "darwinEvents.h" + +#include "quartzKeyboard.h" + +#include "X11Application.h" + +#include "threadSafety.h" + +#ifdef NDEBUG +#undef NDEBUG +#include +#define NDEBUG 1 +#else +#include +#endif +#include + +#include "xkbsrv.h" +#include "exevents.h" +#include "X11/keysym.h" +#include "keysym2ucs.h" + +extern void +CopyKeyClass(DeviceIntPtr device, DeviceIntPtr master); + +enum { + MOD_COMMAND = 256, + MOD_SHIFT = 512, + MOD_OPTION = 2048, + MOD_CONTROL = 4096, +}; + +#define UKEYSYM(u) ((u) | 0x01000000) + +#if HACK_MISSING +/* Table of keycode->keysym mappings we use to fallback on for important + keys that are often not in the Unicode mapping. */ + +const static struct { + unsigned short keycode; + KeySym keysym; +} known_keys[] = { + {55, XK_Meta_L}, + {56, XK_Shift_L}, + {57, XK_Caps_Lock}, + {58, XK_Alt_L}, + {59, XK_Control_L}, + + {60, XK_Shift_R}, + {61, XK_Alt_R}, + {62, XK_Control_R}, + {63, XK_Meta_R}, + + {122, XK_F1}, + {120, XK_F2}, + {99, XK_F3}, + {118, XK_F4}, + {96, XK_F5}, + {97, XK_F6}, + {98, XK_F7}, + {100, XK_F8}, + {101, XK_F9}, + {109, XK_F10}, + {103, XK_F11}, + {111, XK_F12}, + {105, XK_F13}, + {107, XK_F14}, + {113, XK_F15}, +}; +#endif + +#if HACK_KEYPAD +/* Table of keycode->old,new-keysym mappings we use to fixup the numeric + keypad entries. */ + +const static struct { + unsigned short keycode; + KeySym normal, keypad; +} known_numeric_keys[] = { + {65, XK_period, XK_KP_Decimal}, + {67, XK_asterisk, XK_KP_Multiply}, + {69, XK_plus, XK_KP_Add}, + {75, XK_slash, XK_KP_Divide}, + {76, 0x01000003, XK_KP_Enter}, + {78, XK_minus, XK_KP_Subtract}, + {81, XK_equal, XK_KP_Equal}, + {82, XK_0, XK_KP_0}, + {83, XK_1, XK_KP_1}, + {84, XK_2, XK_KP_2}, + {85, XK_3, XK_KP_3}, + {86, XK_4, XK_KP_4}, + {87, XK_5, XK_KP_5}, + {88, XK_6, XK_KP_6}, + {89, XK_7, XK_KP_7}, + {91, XK_8, XK_KP_8}, + {92, XK_9, XK_KP_9}, +}; +#endif + +#if HACK_BLACKLIST +/* wine notepad produces wrong characters on shift+arrow + * http://xquartz.macosforge.org/trac/ticket/295 + * http://developer.apple.com/legacy/mac/library/documentation/mac/Text/Text-579.html + * + * legacy Mac keycodes for arrow keys that shift-modify to math symbols + */ +const static unsigned short keycode_blacklist[] = {66, 70, 72, 77}; +#endif + +/* Table mapping normal keysyms to their dead equivalents. + FIXME: all the unicode keysyms (apart from circumflex) were guessed. */ + +const static struct { + KeySym normal, dead; +} dead_keys[] = { + {XK_grave, XK_dead_grave}, + {XK_apostrophe, XK_dead_acute}, /* US:"=" on a Czech keyboard */ + {XK_acute, XK_dead_acute}, + {UKEYSYM (0x384), XK_dead_acute}, /* US:";" on a Greek keyboard */ +// {XK_Greek_accentdieresis, XK_dead_diaeresis}, /* US:"opt+;" on a Greek keyboard ... replace with dead_accentdieresis if there is one */ + {XK_asciicircum, XK_dead_circumflex}, + {UKEYSYM (0x2c6), XK_dead_circumflex}, /* MODIFIER LETTER CIRCUMFLEX ACCENT */ + {XK_asciitilde, XK_dead_tilde}, + {UKEYSYM (0x2dc), XK_dead_tilde}, /* SMALL TILDE */ + {XK_macron, XK_dead_macron}, + {XK_breve, XK_dead_breve}, + {XK_abovedot, XK_dead_abovedot}, + {XK_diaeresis, XK_dead_diaeresis}, + {UKEYSYM (0x2da), XK_dead_abovering}, /* DOT ABOVE */ + {XK_doubleacute, XK_dead_doubleacute}, + {XK_caron, XK_dead_caron}, + {XK_cedilla, XK_dead_cedilla}, + {XK_ogonek, XK_dead_ogonek}, + {UKEYSYM (0x269), XK_dead_iota}, /* LATIN SMALL LETTER IOTA */ + {UKEYSYM (0x2ec), XK_dead_voiced_sound}, /* MODIFIER LETTER VOICING */ +/* {XK_semivoiced_sound, XK_dead_semivoiced_sound}, */ + {UKEYSYM (0x323), XK_dead_belowdot}, /* COMBINING DOT BELOW */ + {UKEYSYM (0x309), XK_dead_hook}, /* COMBINING HOOK ABOVE */ + {UKEYSYM (0x31b), XK_dead_horn}, /* COMBINING HORN */ +}; + +typedef struct darwinKeyboardInfo_struct { + CARD8 modMap[MAP_LENGTH]; + KeySym keyMap[MAP_LENGTH * GLYPHS_PER_KEY]; + unsigned char modifierKeycodes[32][2]; +} darwinKeyboardInfo; + +darwinKeyboardInfo keyInfo; +pthread_mutex_t keyInfo_mutex = PTHREAD_MUTEX_INITIALIZER; + +static void DarwinChangeKeyboardControl(DeviceIntPtr device, KeybdCtrl *ctrl) { + // FIXME: to be implemented + // keyclick, bell volume / pitch, autorepead, LED's +} + +//----------------------------------------------------------------------------- +// Utility functions to help parse Darwin keymap +//----------------------------------------------------------------------------- + +/* + * DarwinBuildModifierMaps + * Use the keyMap field of keyboard info structure to populate + * the modMap and modifierKeycodes fields. + */ +static void DarwinBuildModifierMaps(darwinKeyboardInfo *info) { + int i; + KeySym *k; + + memset(info->modMap, NoSymbol, sizeof(info->modMap)); + memset(info->modifierKeycodes, 0, sizeof(info->modifierKeycodes)); + + for (i = 0; i < NUM_KEYCODES; i++) { + k = info->keyMap + i * GLYPHS_PER_KEY; + + switch (*k) { + case XK_Shift_L: + info->modifierKeycodes[NX_MODIFIERKEY_SHIFT][0] = i; + info->modMap[MIN_KEYCODE + i] = ShiftMask; + break; + + case XK_Shift_R: +#ifdef NX_MODIFIERKEY_RSHIFT + info->modifierKeycodes[NX_MODIFIERKEY_RSHIFT][0] = i; +#else + info->modifierKeycodes[NX_MODIFIERKEY_SHIFT][0] = i; +#endif + info->modMap[MIN_KEYCODE + i] = ShiftMask; + break; + + case XK_Control_L: + info->modifierKeycodes[NX_MODIFIERKEY_CONTROL][0] = i; + info->modMap[MIN_KEYCODE + i] = ControlMask; + break; + + case XK_Control_R: +#ifdef NX_MODIFIERKEY_RCONTROL + info->modifierKeycodes[NX_MODIFIERKEY_RCONTROL][0] = i; +#else + info->modifierKeycodes[NX_MODIFIERKEY_CONTROL][0] = i; +#endif + info->modMap[MIN_KEYCODE + i] = ControlMask; + break; + + case XK_Caps_Lock: + info->modifierKeycodes[NX_MODIFIERKEY_ALPHALOCK][0] = i; + info->modMap[MIN_KEYCODE + i] = LockMask; + break; + + case XK_Alt_L: + info->modifierKeycodes[NX_MODIFIERKEY_ALTERNATE][0] = i; + info->modMap[MIN_KEYCODE + i] = Mod1Mask; + if(!XQuartzOptionSendsAlt) + *k = XK_Mode_switch; // Yes, this is ugly. This needs to be cleaned up when we integrate quartzKeyboard with this code and refactor. + break; + + case XK_Alt_R: +#ifdef NX_MODIFIERKEY_RALTERNATE + info->modifierKeycodes[NX_MODIFIERKEY_RALTERNATE][0] = i; +#else + info->modifierKeycodes[NX_MODIFIERKEY_ALTERNATE][0] = i; +#endif + if(!XQuartzOptionSendsAlt) + *k = XK_Mode_switch; // Yes, this is ugly. This needs to be cleaned up when we integrate quartzKeyboard with this code and refactor. + info->modMap[MIN_KEYCODE + i] = Mod1Mask; + break; + + case XK_Mode_switch: + ErrorF("DarwinBuildModifierMaps: XK_Mode_switch encountered, unable to determine side.\n"); + info->modifierKeycodes[NX_MODIFIERKEY_ALTERNATE][0] = i; +#ifdef NX_MODIFIERKEY_RALTERNATE + info->modifierKeycodes[NX_MODIFIERKEY_RALTERNATE][0] = i; +#endif + info->modMap[MIN_KEYCODE + i] = Mod1Mask; + break; + + case XK_Meta_L: + info->modifierKeycodes[NX_MODIFIERKEY_COMMAND][0] = i; + info->modMap[MIN_KEYCODE + i] = Mod2Mask; + break; + + case XK_Meta_R: +#ifdef NX_MODIFIERKEY_RCOMMAND + info->modifierKeycodes[NX_MODIFIERKEY_RCOMMAND][0] = i; +#else + info->modifierKeycodes[NX_MODIFIERKEY_COMMAND][0] = i; +#endif + info->modMap[MIN_KEYCODE + i] = Mod2Mask; + break; + + case XK_Num_Lock: + info->modMap[MIN_KEYCODE + i] = Mod3Mask; + break; + } + } +} + +/* + * DarwinKeyboardInit + * Get the Darwin keyboard map and compute an equivalent + * X keyboard map and modifier map. Set the new keyboard + * device structure. + */ +void DarwinKeyboardInit(DeviceIntPtr pDev) { + // Open a shared connection to the HID System. + // Note that the Event Status Driver is really just a wrapper + // for a kIOHIDParamConnectType connection. + assert(darwinParamConnect = NXOpenEventStatus()); + + InitKeyboardDeviceStruct(pDev, NULL, NULL, DarwinChangeKeyboardControl); + + DarwinKeyboardReloadHandler(); + + CopyKeyClass(pDev, inputInfo.keyboard); +} + +/* Set the repeat rates based on global preferences and keycodes for modifiers. + * Precondition: Has the keyInfo_mutex lock. + */ +static void DarwinKeyboardSetRepeat(DeviceIntPtr pDev, int initialKeyRepeatValue, int keyRepeatValue) { + if(initialKeyRepeatValue == 300000) { // off + /* Turn off repeats globally */ + XkbSetRepeatKeys(pDev, -1, AutoRepeatModeOff); + } else { + int i; + XkbControlsPtr ctrl; + XkbControlsRec old; + + /* Turn on repeats globally */ + XkbSetRepeatKeys(pDev, -1, AutoRepeatModeOn); + + /* Setup the bit mask for individual key repeats */ + ctrl = pDev->key->xkbInfo->desc->ctrls; + old= *ctrl; + + ctrl->repeat_delay = initialKeyRepeatValue * 15; + ctrl->repeat_interval = keyRepeatValue * 15; + + /* Turn off key-repeat for modifier keys, on for others */ + /* First set them all on */ + for(i=0; i < XkbPerKeyBitArraySize; i++) + ctrl->per_key_repeat[i] = -1; + + /* Now turn off the modifiers */ + for(i=0; i < 32; i++) { + unsigned char keycode; + + keycode = keyInfo.modifierKeycodes[i][0]; + if(keycode) + ClearBit(ctrl->per_key_repeat, keycode + MIN_KEYCODE); + + keycode = keyInfo.modifierKeycodes[i][1]; + if(keycode) + ClearBit(ctrl->per_key_repeat, keycode + MIN_KEYCODE); + } + + /* Hurray for data duplication */ + if (pDev->kbdfeed) + memcpy(pDev->kbdfeed->ctrl.autoRepeats, ctrl->per_key_repeat, XkbPerKeyBitArraySize); + + //fprintf(stderr, "per_key_repeat =\n"); + //for(i=0; i < XkbPerKeyBitArraySize; i++) + // fprintf(stderr, "%02x%s", ctrl->per_key_repeat[i], (i + 1) & 7 ? "" : "\n"); + + /* And now we notify the puppies about the changes */ + XkbDDXChangeControls(pDev, &old, ctrl); + } +} + +void DarwinKeyboardReloadHandler(void) { + KeySymsRec keySyms; + CFIndex initialKeyRepeatValue, keyRepeatValue; + BOOL ok; + DeviceIntPtr pDev; + const char *xmodmap = PROJECTROOT "/bin/xmodmap"; + const char *sysmodmap = PROJECTROOT "/lib/X11/xinit/.Xmodmap"; + const char *homedir = getenv("HOME"); + char usermodmap[PATH_MAX], cmd[PATH_MAX]; + + DEBUG_LOG("DarwinKeyboardReloadHandler\n"); + + /* Get our key repeat settings from GlobalPreferences */ + (void)CFPreferencesAppSynchronize(CFSTR(".GlobalPreferences")); + + initialKeyRepeatValue = CFPreferencesGetAppIntegerValue(CFSTR("InitialKeyRepeat"), CFSTR(".GlobalPreferences"), &ok); + if(!ok) + initialKeyRepeatValue = 35; + + keyRepeatValue = CFPreferencesGetAppIntegerValue(CFSTR("KeyRepeat"), CFSTR(".GlobalPreferences"), &ok); + if(!ok) + keyRepeatValue = 6; + + pthread_mutex_lock(&keyInfo_mutex); { + /* Initialize our keySyms */ + keySyms.map = keyInfo.keyMap; + keySyms.mapWidth = GLYPHS_PER_KEY; + keySyms.minKeyCode = MIN_KEYCODE; + keySyms.maxKeyCode = MAX_KEYCODE; + + // TODO: We should build the entire XkbDescRec and use XkbCopyKeymap + /* Apply the mappings to darwinKeyboard */ + XkbApplyMappingChange(darwinKeyboard, &keySyms, keySyms.minKeyCode, + keySyms.maxKeyCode - keySyms.minKeyCode + 1, + keyInfo.modMap, serverClient); + DarwinKeyboardSetRepeat(darwinKeyboard, initialKeyRepeatValue, keyRepeatValue); + + /* Apply the mappings to the core keyboard */ + for (pDev = inputInfo.devices; pDev; pDev = pDev->next) { + if ((pDev->coreEvents || pDev == inputInfo.keyboard) && pDev->key) { + XkbApplyMappingChange(pDev, &keySyms, keySyms.minKeyCode, + keySyms.maxKeyCode - keySyms.minKeyCode + 1, + keyInfo.modMap, serverClient); + DarwinKeyboardSetRepeat(pDev, initialKeyRepeatValue, keyRepeatValue); + } + } + } pthread_mutex_unlock(&keyInfo_mutex); + + /* Modify with xmodmap */ + if (access(xmodmap, F_OK) == 0) { + /* Check for system .Xmodmap */ + if (access(sysmodmap, F_OK) == 0) { + if(snprintf (cmd, sizeof(cmd), "%s %s", xmodmap, sysmodmap) < sizeof(cmd)) { + X11ApplicationLaunchClient(cmd); + } else { + ErrorF("X11.app: Unable to create / execute xmodmap command line"); + } + } + + /* Check for user's local .Xmodmap */ + if ((homedir != NULL) && (snprintf (usermodmap, sizeof(usermodmap), "%s/.Xmodmap", homedir) < sizeof(usermodmap))) { + if (access(usermodmap, F_OK) == 0) { + if(snprintf (cmd, sizeof(cmd), "%s %s", xmodmap, usermodmap) < sizeof(cmd)) { + X11ApplicationLaunchClient(cmd); + } else { + ErrorF("X11.app: Unable to create / execute xmodmap command line"); + } + } + } else { + ErrorF("X11.app: Unable to determine path to user's .Xmodmap"); + } + } +} + +//----------------------------------------------------------------------------- +// Modifier translation functions +// +// There are three different ways to specify a Mac modifier key: +// keycode - specifies hardware key, read from keymapping +// key - NX_MODIFIERKEY_*, really an index +// mask - NX_*MASK, mask for modifier flags in event record +// Left and right side have different keycodes but the same key and mask. +//----------------------------------------------------------------------------- + +/* + * DarwinModifierNXKeyToNXKeycode + * Return the keycode for an NX_MODIFIERKEY_* modifier. + * side = 0 for left or 1 for right. + * Returns 0 if key+side is not a known modifier. + */ +int DarwinModifierNXKeyToNXKeycode(int key, int side) { + int retval; + pthread_mutex_lock(&keyInfo_mutex); + retval = keyInfo.modifierKeycodes[key][side]; + pthread_mutex_unlock(&keyInfo_mutex); + + return retval; +} + +/* + * DarwinModifierNXKeycodeToNXKey + * Returns -1 if keycode+side is not a modifier key + * outSide may be NULL, else it gets 0 for left and 1 for right. + */ +int DarwinModifierNXKeycodeToNXKey(unsigned char keycode, int *outSide) { + int key, side; + + keycode += MIN_KEYCODE; + + // search modifierKeycodes for this keycode+side + pthread_mutex_lock(&keyInfo_mutex); + for (key = 0; key < NX_NUMMODIFIERS; key++) { + for (side = 0; side <= 1; side++) { + if (keyInfo.modifierKeycodes[key][side] == keycode) break; + } + } + pthread_mutex_unlock(&keyInfo_mutex); + + if (key == NX_NUMMODIFIERS) { + return -1; + } + if (outSide) *outSide = side; + + return key; +} + +/* + * DarwinModifierNXMaskToNXKey + * Returns -1 if mask is not a known modifier mask. + */ +int DarwinModifierNXMaskToNXKey(int mask) { + switch (mask) { + case NX_ALPHASHIFTMASK: return NX_MODIFIERKEY_ALPHALOCK; + case NX_SHIFTMASK: return NX_MODIFIERKEY_SHIFT; +#ifdef NX_DEVICELSHIFTKEYMASK + case NX_DEVICELSHIFTKEYMASK: return NX_MODIFIERKEY_SHIFT; + case NX_DEVICERSHIFTKEYMASK: return NX_MODIFIERKEY_RSHIFT; +#endif + case NX_CONTROLMASK: return NX_MODIFIERKEY_CONTROL; +#ifdef NX_DEVICELCTLKEYMASK + case NX_DEVICELCTLKEYMASK: return NX_MODIFIERKEY_CONTROL; + case NX_DEVICERCTLKEYMASK: return NX_MODIFIERKEY_RCONTROL; +#endif + case NX_ALTERNATEMASK: return NX_MODIFIERKEY_ALTERNATE; +#ifdef NX_DEVICELALTKEYMASK + case NX_DEVICELALTKEYMASK: return NX_MODIFIERKEY_ALTERNATE; + case NX_DEVICERALTKEYMASK: return NX_MODIFIERKEY_RALTERNATE; +#endif + case NX_COMMANDMASK: return NX_MODIFIERKEY_COMMAND; +#ifdef NX_DEVICELCMDKEYMASK + case NX_DEVICELCMDKEYMASK: return NX_MODIFIERKEY_COMMAND; + case NX_DEVICERCMDKEYMASK: return NX_MODIFIERKEY_RCOMMAND; +#endif + case NX_NUMERICPADMASK: return NX_MODIFIERKEY_NUMERICPAD; + case NX_HELPMASK: return NX_MODIFIERKEY_HELP; + case NX_SECONDARYFNMASK: return NX_MODIFIERKEY_SECONDARYFN; + } + return -1; +} + +/* + * DarwinModifierNXKeyToNXMask + * Returns 0 if key is not a known modifier key. + */ +int DarwinModifierNXKeyToNXMask(int key) { + switch (key) { + case NX_MODIFIERKEY_ALPHALOCK: return NX_ALPHASHIFTMASK; +#ifdef NX_DEVICELSHIFTKEYMASK + case NX_MODIFIERKEY_SHIFT: return NX_DEVICELSHIFTKEYMASK; + case NX_MODIFIERKEY_RSHIFT: return NX_DEVICERSHIFTKEYMASK; + case NX_MODIFIERKEY_CONTROL: return NX_DEVICELCTLKEYMASK; + case NX_MODIFIERKEY_RCONTROL: return NX_DEVICERCTLKEYMASK; + case NX_MODIFIERKEY_ALTERNATE: return NX_DEVICELALTKEYMASK; + case NX_MODIFIERKEY_RALTERNATE: return NX_DEVICERALTKEYMASK; + case NX_MODIFIERKEY_COMMAND: return NX_DEVICELCMDKEYMASK; + case NX_MODIFIERKEY_RCOMMAND: return NX_DEVICERCMDKEYMASK; +#else + case NX_MODIFIERKEY_SHIFT: return NX_SHIFTMASK; + case NX_MODIFIERKEY_CONTROL: return NX_CONTROLMASK; + case NX_MODIFIERKEY_ALTERNATE: return NX_ALTERNATEMASK; + case NX_MODIFIERKEY_COMMAND: return NX_COMMANDMASK; +#endif + case NX_MODIFIERKEY_NUMERICPAD: return NX_NUMERICPADMASK; + case NX_MODIFIERKEY_HELP: return NX_HELPMASK; + case NX_MODIFIERKEY_SECONDARYFN: return NX_SECONDARYFNMASK; + } + return 0; +} + +/* + * DarwinModifierStringToNXMask + * Returns 0 if string is not a known modifier. + */ +int DarwinModifierStringToNXMask(const char *str, int separatelr) { +#ifdef NX_DEVICELSHIFTKEYMASK + if(separatelr) { + if (!strcasecmp(str, "shift")) return NX_DEVICELSHIFTKEYMASK | NX_DEVICERSHIFTKEYMASK; + if (!strcasecmp(str, "control")) return NX_DEVICELCTLKEYMASK | NX_DEVICERCTLKEYMASK; + if (!strcasecmp(str, "option")) return NX_DEVICELALTKEYMASK | NX_DEVICERALTKEYMASK; + if (!strcasecmp(str, "alt")) return NX_DEVICELALTKEYMASK | NX_DEVICERALTKEYMASK; + if (!strcasecmp(str, "command")) return NX_DEVICELCMDKEYMASK | NX_DEVICERCMDKEYMASK; + if (!strcasecmp(str, "lshift")) return NX_DEVICELSHIFTKEYMASK; + if (!strcasecmp(str, "rshift")) return NX_DEVICERSHIFTKEYMASK; + if (!strcasecmp(str, "lcontrol")) return NX_DEVICELCTLKEYMASK; + if (!strcasecmp(str, "rcontrol")) return NX_DEVICERCTLKEYMASK; + if (!strcasecmp(str, "loption")) return NX_DEVICELALTKEYMASK; + if (!strcasecmp(str, "roption")) return NX_DEVICERALTKEYMASK; + if (!strcasecmp(str, "lalt")) return NX_DEVICELALTKEYMASK; + if (!strcasecmp(str, "ralt")) return NX_DEVICERALTKEYMASK; + if (!strcasecmp(str, "lcommand")) return NX_DEVICELCMDKEYMASK; + if (!strcasecmp(str, "rcommand")) return NX_DEVICERCMDKEYMASK; + } else { +#endif + if (!strcasecmp(str, "shift")) return NX_SHIFTMASK; + if (!strcasecmp(str, "control")) return NX_CONTROLMASK; + if (!strcasecmp(str, "option")) return NX_ALTERNATEMASK; + if (!strcasecmp(str, "alt")) return NX_ALTERNATEMASK; + if (!strcasecmp(str, "command")) return NX_COMMANDMASK; + if (!strcasecmp(str, "lshift")) return NX_SHIFTMASK; + if (!strcasecmp(str, "rshift")) return NX_SHIFTMASK; + if (!strcasecmp(str, "lcontrol")) return NX_CONTROLMASK; + if (!strcasecmp(str, "rcontrol")) return NX_CONTROLMASK; + if (!strcasecmp(str, "loption")) return NX_ALTERNATEMASK; + if (!strcasecmp(str, "roption")) return NX_ALTERNATEMASK; + if (!strcasecmp(str, "lalt")) return NX_ALTERNATEMASK; + if (!strcasecmp(str, "ralt")) return NX_ALTERNATEMASK; + if (!strcasecmp(str, "lcommand")) return NX_COMMANDMASK; + if (!strcasecmp(str, "rcommand")) return NX_COMMANDMASK; +#ifdef NX_DEVICELSHIFTKEYMASK + } +#endif + if (!strcasecmp(str, "lock")) return NX_ALPHASHIFTMASK; + if (!strcasecmp(str, "fn")) return NX_SECONDARYFNMASK; + if (!strcasecmp(str, "help")) return NX_HELPMASK; + if (!strcasecmp(str, "numlock")) return NX_NUMERICPADMASK; + return 0; +} + +/* + * LegalModifier + * This allows the ddx layer to prevent some keys from being remapped + * as modifier keys. + */ +Bool LegalModifier(unsigned int key, DeviceIntPtr pDev) +{ + return 1; +} + +static inline UniChar macroman2ucs(unsigned char c) { + /* Precalculated table mapping MacRoman-128 to Unicode. Generated + by creating single element CFStringRefs then extracting the + first character. */ + + static const unsigned short table[128] = { + 0xc4, 0xc5, 0xc7, 0xc9, 0xd1, 0xd6, 0xdc, 0xe1, + 0xe0, 0xe2, 0xe4, 0xe3, 0xe5, 0xe7, 0xe9, 0xe8, + 0xea, 0xeb, 0xed, 0xec, 0xee, 0xef, 0xf1, 0xf3, + 0xf2, 0xf4, 0xf6, 0xf5, 0xfa, 0xf9, 0xfb, 0xfc, + 0x2020, 0xb0, 0xa2, 0xa3, 0xa7, 0x2022, 0xb6, 0xdf, + 0xae, 0xa9, 0x2122, 0xb4, 0xa8, 0x2260, 0xc6, 0xd8, + 0x221e, 0xb1, 0x2264, 0x2265, 0xa5, 0xb5, 0x2202, 0x2211, + 0x220f, 0x3c0, 0x222b, 0xaa, 0xba, 0x3a9, 0xe6, 0xf8, + 0xbf, 0xa1, 0xac, 0x221a, 0x192, 0x2248, 0x2206, 0xab, + 0xbb, 0x2026, 0xa0, 0xc0, 0xc3, 0xd5, 0x152, 0x153, + 0x2013, 0x2014, 0x201c, 0x201d, 0x2018, 0x2019, 0xf7, 0x25ca, + 0xff, 0x178, 0x2044, 0x20ac, 0x2039, 0x203a, 0xfb01, 0xfb02, + 0x2021, 0xb7, 0x201a, 0x201e, 0x2030, 0xc2, 0xca, 0xc1, + 0xcb, 0xc8, 0xcd, 0xce, 0xcf, 0xcc, 0xd3, 0xd4, + 0xf8ff, 0xd2, 0xda, 0xdb, 0xd9, 0x131, 0x2c6, 0x2dc, + 0xaf, 0x2d8, 0x2d9, 0x2da, 0xb8, 0x2dd, 0x2db, 0x2c7, + }; + + if (c < 128) return c; + else return table[c - 128]; +} + +static KeySym make_dead_key(KeySym in) { + int i; + + for (i = 0; i < sizeof (dead_keys) / sizeof (dead_keys[0]); i++) + if (dead_keys[i].normal == in) return dead_keys[i].dead; + + return in; +} + +static Bool QuartzReadSystemKeymap(darwinKeyboardInfo *info) { +#if !defined(__LP64__) || MAC_OS_X_VERSION_MIN_REQUIRED < 1050 + KeyboardLayoutRef key_layout; + int is_uchr = 1; +#endif + const void *chr_data = NULL; + int num_keycodes = NUM_KEYCODES; + UInt32 keyboard_type = LMGetKbdType(); + int i, j; + OSStatus err; + KeySym *k; + CFDataRef currentKeyLayoutDataRef = NULL; + +#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050 + TISInputSourceRef currentKeyLayoutRef = TISCopyCurrentKeyboardLayoutInputSource(); + + if (currentKeyLayoutRef) { + currentKeyLayoutDataRef = (CFDataRef )TISGetInputSourceProperty(currentKeyLayoutRef, kTISPropertyUnicodeKeyLayoutData); + if (currentKeyLayoutDataRef) + chr_data = CFDataGetBytePtr(currentKeyLayoutDataRef); + } +#endif + +#if !defined(__LP64__) || MAC_OS_X_VERSION_MIN_REQUIRED < 1050 + if (chr_data == NULL) { +#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050 + ErrorF("X11.app: Error detected in determining keyboard layout. If you are using an Apple-provided keyboard layout, please report this error at http://xquartz.macosforge.org and http://bugreport.apple.com\n"); + ErrorF("X11.app: Debug Info: keyboard_type=%u, currentKeyLayoutRef=%p, currentKeyLayoutDataRef=%p, chr_data=%p\n", + (unsigned)keyboard_type, currentKeyLayoutRef, currentKeyLayoutDataRef, chr_data); +#endif + + KLGetCurrentKeyboardLayout (&key_layout); + KLGetKeyboardLayoutProperty (key_layout, kKLuchrData, &chr_data); + +#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050 + if(chr_data != NULL) { + ErrorF("X11.app: Fallback succeeded, but this is still a bug. Please report the above information.\n"); + } +#endif + } + + if (chr_data == NULL) { + ErrorF("X11.app: Debug Info: kKLuchrData failed, trying kKLKCHRData.\n"); + ErrorF("If you are using a 3rd party keyboard layout, please see http://xquartz.macosforge.org/trac/ticket/154\n"); + KLGetKeyboardLayoutProperty (key_layout, kKLKCHRData, &chr_data); + is_uchr = 0; + num_keycodes = 128; + +#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050 + if(chr_data != NULL) { + ErrorF("X11.app: Fallback succeeded, but this is still a bug. Please report the above information.\n"); + } +#endif + } +#endif + +#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050 + if(currentKeyLayoutRef) + CFRelease(currentKeyLayoutRef); +#endif + + if (chr_data == NULL) { + ErrorF ( "Couldn't get uchr or kchr resource\n"); + return FALSE; + } + + /* Scan the keycode range for the Unicode character that each + key produces in the four shift states. Then convert that to + an X11 keysym (which may just the bit that says "this is + Unicode" if it can't find the real symbol.) */ + + /* KeyTranslate is not available on 64-bit platforms; UCKeyTranslate + must be used instead. */ + + for (i = 0; i < num_keycodes; i++) { + static const int mods[4] = {0, MOD_SHIFT, MOD_OPTION, + MOD_OPTION | MOD_SHIFT}; + + k = info->keyMap + i * GLYPHS_PER_KEY; + + for (j = 0; j < 4; j++) { +#if !defined(__LP64__) || MAC_OS_X_VERSION_MIN_REQUIRED < 1050 + if (is_uchr) { +#endif + UniChar s[8]; + UniCharCount len; + UInt32 dead_key_state = 0, extra_dead = 0; + + err = UCKeyTranslate (chr_data, i, kUCKeyActionDown, + mods[j] >> 8, keyboard_type, 0, + &dead_key_state, 8, &len, s); + if (err != noErr) continue; + + if (len == 0 && dead_key_state != 0) { + /* Found a dead key. Work out which one it is, but + remembering that it's dead. */ + err = UCKeyTranslate (chr_data, i, kUCKeyActionDown, + mods[j] >> 8, keyboard_type, + kUCKeyTranslateNoDeadKeysMask, + &extra_dead, 8, &len, s); + if (err != noErr) continue; + } + + /* Not sure why 0x0010 is there. + * 0x0000 - 'Unicode Hex Input' ... + */ + if (len > 0 && s[0] != 0x0010 && s[0] != 0x0000) { + k[j] = ucs2keysym (s[0]); + if (dead_key_state != 0) k[j] = make_dead_key (k[j]); + } +#if !defined(__LP64__) || MAC_OS_X_VERSION_MIN_REQUIRED < 1050 + } else { // kchr + UInt32 c, state = 0, state2 = 0; + UInt16 code; + + code = i | mods[j]; + c = KeyTranslate (chr_data, code, &state); + + /* Dead keys are only processed on key-down, so ask + to translate those events. When we find a dead key, + translating the matching key up event will give + us the actual dead character. */ + + if (state != 0) + c = KeyTranslate (chr_data, code | 128, &state2); + + /* Characters seem to be in MacRoman encoding. */ + + if (c != 0 && c != 0x0010) { + k[j] = ucs2keysym (macroman2ucs (c & 255)); + + if (state != 0) k[j] = make_dead_key (k[j]); + } + } +#endif + } + + if (k[3] == k[2]) k[3] = NoSymbol; + if (k[1] == k[0]) k[1] = NoSymbol; + if (k[0] == k[2] && k[1] == k[3]) k[2] = k[3] = NoSymbol; + if (k[3] == k[0] && k[2] == k[1] && k[2] == NoSymbol) k[3] = NoSymbol; + } + +#if HACK_MISSING + /* Fix up some things that are normally missing.. */ + + for (i = 0; i < sizeof (known_keys) / sizeof (known_keys[0]); i++) { + k = info->keyMap + known_keys[i].keycode * GLYPHS_PER_KEY; + + if ( k[0] == NoSymbol && k[1] == NoSymbol + && k[2] == NoSymbol && k[3] == NoSymbol) + k[0] = known_keys[i].keysym; + } +#endif + +#if HACK_KEYPAD + /* And some more things. We find the right symbols for the numeric + keypad, but not the KP_ keysyms. So try to convert known keycodes. */ + for (i = 0; i < sizeof (known_numeric_keys) / sizeof (known_numeric_keys[0]); i++) { + k = info->keyMap + known_numeric_keys[i].keycode * GLYPHS_PER_KEY; + + if (k[0] == known_numeric_keys[i].normal) + k[0] = known_numeric_keys[i].keypad; + } +#endif + +#if HACK_BLACKLIST + for (i = 0; i < sizeof (keycode_blacklist) / sizeof (keycode_blacklist[0]); i++) { + k = info->keyMap + keycode_blacklist[i] * GLYPHS_PER_KEY; + k[0] = k[1] = k[2] = k[3] = NoSymbol; + } +#endif + + DarwinBuildModifierMaps(info); + + return TRUE; +} + +Bool QuartsResyncKeymap(Bool sendDDXEvent) { + Bool retval; + /* Update keyInfo */ + pthread_mutex_lock(&keyInfo_mutex); + memset(keyInfo.keyMap, 0, sizeof(keyInfo.keyMap)); + retval = QuartzReadSystemKeymap(&keyInfo); + pthread_mutex_unlock(&keyInfo_mutex); + + /* Tell server thread to deal with new keyInfo */ + if(sendDDXEvent) + DarwinSendDDXEvent(kXquartzReloadKeymap, 0); + + return retval; +} diff --git a/xorg-server/hw/xquartz/quartzStartup.c b/xorg-server/hw/xquartz/quartzStartup.c index ba92ecef6..36c8182ae 100644 --- a/xorg-server/hw/xquartz/quartzStartup.c +++ b/xorg-server/hw/xquartz/quartzStartup.c @@ -40,7 +40,6 @@ #include "X11Controller.h" #include "darwin.h" #include "darwinEvents.h" -#include "quartzAudio.h" #include "quartz.h" #include "opaque.h" #include "micmap.h" @@ -117,9 +116,6 @@ int server_main(int argc, char **argv, char **envp) { } } - /* Create the audio mutex */ - QuartzAudioInit(); - X11ControllerMain(argc, argv, envp); exit(0); } -- cgit v1.2.3