diff options
Diffstat (limited to 'xorg-server/hw')
24 files changed, 3032 insertions, 6946 deletions
diff --git a/xorg-server/hw/dmx/doc/Makefile.am b/xorg-server/hw/dmx/doc/Makefile.am index b8a047baa..ef7c23da1 100644 --- a/xorg-server/hw/dmx/doc/Makefile.am +++ b/xorg-server/hw/dmx/doc/Makefile.am @@ -1,290 +1,290 @@ -# 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.
-
-SGML_FILES = dmx.sgml scaled.sgml
-
-if BUILD_LINUXDOC
-TXT_FILES = $(SGML_FILES:%.sgml=%.txt)
-PS_FILES = $(SGML_FILES:%.sgml=%.ps)
-if BUILD_PDFDOC
-PDF_FILES = $(SGML_FILES:%.sgml=%.pdf)
-endif
-HTML_FILES = $(SGML_FILES:%.sgml=%.html)
-
-SUFFIXES = .sgml .txt .html .ps .pdf
-
-.sgml.txt:
- @rm -f $@
- $(MAKE_TEXT) $<
-
-.sgml.ps:
- @rm -f $@
- $(MAKE_PS) $<
-
-.ps.pdf:
- @rm -f $@
- $(MAKE_PDF) $<
-
-.sgml.html:
- @rm -f $@
- $(MAKE_HTML) $<
-
-noinst_DATA = $(TXT_FILES) $(PS_FILES) $(PDF_FILES) $(HTML_FILES)
-CLEANFILES = $(TXT_FILES) $(PS_FILES) $(PDF_FILES) $(HTML_FILES)
-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 = \
- $(SGML_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. + +SGML_FILES = dmx.sgml scaled.sgml + +if BUILD_LINUXDOC +TXT_FILES = $(SGML_FILES:%.sgml=%.txt) +PS_FILES = $(SGML_FILES:%.sgml=%.ps) +if BUILD_PDFDOC +PDF_FILES = $(SGML_FILES:%.sgml=%.pdf) +endif +HTML_FILES = $(SGML_FILES:%.sgml=%.html) + +SUFFIXES = .sgml .txt .html .ps .pdf + +.sgml.txt: + @rm -f $@ + $(AM_V_GEN)$(MAKE_TEXT) $< + +.sgml.ps: + @rm -f $@ + $(AM_V_GEN)$(MAKE_PS) $< + +.ps.pdf: + @rm -f $@ + $(AM_V_GEN)$(MAKE_PDF) $< + +.sgml.html: + @rm -f $@ + $(AM_V_GEN)$(MAKE_HTML) $< + +noinst_DATA = $(TXT_FILES) $(PS_FILES) $(PDF_FILES) $(HTML_FILES) +CLEANFILES = $(TXT_FILES) $(PS_FILES) $(PDF_FILES) $(HTML_FILES) +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 = \ + $(SGML_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/dmx/doc/dmx.txt b/xorg-server/hw/dmx/doc/dmx.txt deleted file mode 100644 index 568c75178..000000000 --- a/xorg-server/hw/dmx/doc/dmx.txt +++ /dev/null @@ -1,2989 +0,0 @@ - Distributed Multihead X design - Kevin E. Martin, David H. Dawes, and Rickard E. Faith - - 29 June 2004 (created 25 July 2001) - - This document covers the motivation, background, design, and implemen- - tation of the distributed multihead X (DMX) system. It is a living - document and describes the current design and implementation details - of the DMX system. As the project progresses, this document will be - continually updated to reflect the changes in the code and/or design. - _C_o_p_y_r_i_g_h_t _2_0_0_1 _b_y _V_A _L_i_n_u_x _S_y_s_t_e_m_s_, _I_n_c_._, _F_r_e_m_o_n_t_, _C_a_l_i_f_o_r_n_i_a_. _C_o_p_y_- - _r_i_g_h_t _2_0_0_1_-_2_0_0_4 _b_y _R_e_d _H_a_t_, _I_n_c_._, _R_a_l_e_i_g_h_, _N_o_r_t_h _C_a_r_o_l_i_n_a - - ______________________________________________________________________ - - Table of Contents - - - - 1. Introduction - 1.1 The Distributed Multihead X Server - 1.2 Layout of Paper - - 2. Development plan - 2.1 Bootstrap code - 2.2 Input device handling - 2.3 Output device handling - 2.3.1 Initialization - 2.3.2 Handling rendering requests - 2.4 Optimizing DMX - 2.5 DMX X extension support - 2.6 Common X extension support - 2.7 OpenGL support - - 3. Current issues - 3.1 Fonts - 3.2 Zero width rendering primitives - 3.3 Output scaling - 3.4 Per-screen colormaps - - A. Background - A.1 Core input device handling - A.1.1 InitInput() - A.1.2 InitAndStartDevices() - A.1.3 devReadInput() - A.1.4 ProcessInputEvents() - A.1.5 DisableDevice() - A.1.6 CloseDevice() - A.1.7 LegalModifier() - A.2 Output handling - A.2.1 InitOutput() - A.2.2 AddScreen() - A.2.3 ScreenInit() - A.2.4 CloseScreen() - A.2.5 GC operations - A.2.6 Xnest - A.2.7 Shadow framebuffer - A.3 Xinerama - A.3.1 Xinerama-specific changes to the DIX code - A.3.2 Xinerama-specific changes to the MI code - A.3.3 Intercepted DIX core requests - - B. Development Results - B.1 Phase I - B.1.1 Scope - B.1.2 Results - B.1.3 X Test Suite - B.1.3.1 Introduction - B.1.3.2 Expected Failures for a Single Head - B.1.3.3 Expected Failures for Xinerama - B.1.3.4 Additional Failures from Xdmx - B.1.3.5 Summary and Future Work - B.1.4 Fonts - B.1.5 Performance - B.1.6 Pixmaps - B.2 Phase II - B.2.1 Moving from XFree86 4.1.99.1 to 4.2.0.0 - B.2.2 Global changes - B.2.3 XSync() Batching - B.2.4 Offscreen Optimization - B.2.5 Lazy Window Creation Optimization - B.2.6 Subdividing Rendering Primitives - B.2.7 Summary of x11perf Data - B.2.8 Profiling with OProfile - B.2.9 X Test Suite - B.3 Phase III - B.3.1 SHAPE - B.3.2 RENDER - B.3.3 XKEYBOARD - B.3.4 XInput - B.3.5 DPMS - B.3.6 Other Extensions - B.4 Phase IV - B.4.1 Moving to XFree86 4.3.0 - B.4.2 Extensions - B.4.2.1 XC-MISC (supported) - B.4.2.2 Extended-Visual-Information (supported) - B.4.2.3 RES (supported) - B.4.2.4 BIG-REQUESTS (supported) - B.4.2.5 XSYNC (supported) - B.4.2.6 XTEST, RECORD, DEC-XTRAP (supported) and XTestExtension1 (not supported) - B.4.2.7 MIT-MISC (not supported) - B.4.2.8 SCREENSAVER (not supported) - B.4.2.9 GLX (supported) - B.4.2.10 RENDER (supported) - B.4.2.11 Summary - B.4.3 Additional Testing with the X Test Suite - B.4.3.1 XFree86 without XTEST - B.4.3.2 XFree86 with XTEST - B.4.3.3 Xdmx with XTEST, without Xinerama, without GLX - B.4.3.4 Xdmx with XTEST, with Xinerama, without GLX - B.4.3.5 Xdmx with XTEST, with Xinerama, with GLX - B.4.3.6 Conclusion - B.4.4 Dynamic Reconfiguration - B.4.4.1 Dynamic reconfiguration extension - B.4.4.2 Bounding box - B.4.4.3 Sample applications - B.4.4.4 Additional notes - B.4.5 Doxygen documentation - B.4.6 Valgrind - B.4.7 RATS - - - ______________________________________________________________________ - - 11.. IInnttrroodduuccttiioonn - - 11..11.. TThhee DDiissttrriibbuutteedd MMuullttiihheeaadd XX SSeerrvveerr - - Current Open Source multihead solutions are limited to a single - physical machine. A single X server controls multiple display - devices, which can be arranged as independent heads or unified into a - single desktop (with Xinerama). These solutions are limited to the - number of physical devices that can co-exist in a single machine - (e.g., due to the number of AGP/PCI slots available for graphics - cards). Thus, large tiled displays are not currently possible. The - work described in this paper will eliminate the requirement that the - display devices reside in the same physical machine. This will be - accomplished by developing a front-end proxy X server that will - control multiple back-end X servers that make up the large display. - - - The overall structure of the distributed multihead X (DMX) project is - as follows: A single front-end X server will act as a proxy to a set - of back-end X servers, which handle all of the visible rendering. X - clients will connect to the front-end server just as they normally - would to a regular X server. The front-end server will present an - abstracted view to the client of a single large display. This will - ensure that all standard X clients will continue to operate without - modification (limited, as always, by the visuals and extensions - provided by the X server). Clients that are DMX-aware will be able to - use an extension to obtain information about the back-end servers - (e.g., for placement of pop-up windows, window alignments by the - window manager, etc.). - - - The architecture of the DMX server is divided into two main sections: - input (e.g., mouse and keyboard events) and output (e.g., rendering - and windowing requests). Each of these are describe briefly below, - and the rest of this design document will describe them in greater - detail. - - - The DMX server can receive input from three general types of input - devices: "local" devices that are physically attached to the machine - on which DMX is running, "backend" devices that are physically - attached to one or more of the back-end X servers (and that generate - events via the X protocol stream from the backend), and "console" - devices that can be abstracted from any non-back-end X server. - Backend and console devices are treated differently because the - pointer device on the back-end X server also controls the location of - the hardware X cursor. Full support for XInput extension devices is - provided. - - - Rendering requests will be accepted by the front-end server; however, - rendering to visible windows will be broken down as needed and sent to - the appropriate back-end server(s) via X11 library calls for actual - rendering. The basic framework will follow a Xnest-style approach. - GC state will be managed in the front-end server and sent to the - appropriate back-end server(s) as required. Pixmap rendering will (at - least initially) be handled by the front-end X server. Windowing - requests (e.g., ordering, mapping, moving, etc.) will handled in the - front-end server. If the request requires a visible change, the - windowing operation will be translated into requests for the - appropriate back-end server(s). Window state will be mirrored in the - back-end server(s) as needed. - - - 11..22.. LLaayyoouutt ooff PPaappeerr - - The next section describes the general development plan that was - actually used for implementation. The final section discusses - outstanding issues at the conclusion of development. The first - appendix provides low-level technical detail that may be of interest - to those intimately familiar with the X server architecture. The - final appendix describes the four phases of development that were - performed during the first two years of development. - - - The final year of work was divided into 9 tasks that are not described - in specific sections of this document. The major tasks during that - time were the enhancement of the reconfiguration ability added in - Phase IV, addition of support for a dynamic number of back-end - displays (instead of a hard-coded limit), and the support for back-end - display and input removal and addition. This work is mentioned in - this paper, but is not covered in detail. - - - 22.. DDeevveellooppmmeenntt ppllaann - - This section describes the development plan from approximately June - 2001 through July 2003. - - - - 22..11.. BBoooottssttrraapp ccooddee - - To allow for rapid development of the DMX server by multiple - developers during the first development stage, the problem will be - broken down into three tasks: the overall DMX framework, back-end - rendering services and input device handling services. However, - before the work begins on these tasks, a simple framework that each - developer could use was implemented to bootstrap the development - effort. This framework renders to a single back-end server and - provides dummy input devices (i.e., the keyboard and mouse). The - simple back-end rendering service was implemented using the shadow - framebuffer support currently available in the XFree86 environment. - - - Using this bootstrapping framework, each developer has been able to - work on each of the tasks listed above independently as follows: the - framework will be extended to handle arbitrary back-end server - configurations; the back-end rendering services will be transitioned - to the more efficient Xnest-style implementation; and, an input device - framework to handle various input devices via the input extension will - be developed. - - - Status: The boot strap code is complete. - - - - 22..22.. IInnppuutt ddeevviiccee hhaannddlliinngg - - An X server (including the front-end X server) requires two core input - devices -- a keyboard and a pointer (mouse). These core devices are - handled and required by the core X11 protocol. Additional types of - input devices may be attached and utilized via the XInput extension. - These are usually referred to as ``XInput extension devices'', - - - There are some options as to how the front-end X server gets its core - input devices: - - - 1. Local Input. The physical input devices (e.g., keyboard and mouse) - can be attached directly to the front-end X server. In this case, - the keyboard and mouse on the machine running the front-end X - server will be used. The front-end will have drivers to read the - raw input from those devices and convert it into the required X - input events (e.g., key press/release, pointer button - press/release, pointer motion). The front-end keyboard driver will - keep track of keyboard properties such as key and modifier - mappings, autorepeat state, keyboard sound and led state. - Similarly the front-end pointer driver will keep track if pointer - properties such as the button mapping and movement acceleration - parameters. With this option, input is handled fully in the front- - end X server, and the back-end X servers are used in a display-only - mode. This option was implemented and works for a limited number - of Linux-specific devices. Adding additional local input devices - for other architectures is expected to be relatively simple. - - - The following options are available for implementing local input - devices: - - - a. The XFree86 X server has modular input drivers that could be - adapted for this purpose. The mouse driver supports a wide - range of mouse types and interfaces, as well as a range of - Operating System platforms. The keyboard driver in XFree86 is - not currently as modular as the mouse driver, but could be made - so. The XFree86 X server also has a range of other input - drivers for extended input devices such as tablets and touch - screens. Unfortunately, the XFree86 drivers are generally - complex, often simultaneously providing support for multiple - devices across multiple architectures; and rely so heavily on - XFree86-specific helper-functions, that this option was not - pursued. - - - b. The kdrive X server in XFree86 has built-in drivers that support - PS/2 mice and keyboard under Linux. The mouse driver can - indirectly handle other mouse types if the Linux utility gpm is - used as to translate the native mouse protocol into PS/2 mouse - format. These drivers could be adapted and built in to the - front-end X server if this range of hardware and OS support is - sufficient. While much simpler than the XFree86 drivers, the - kdrive drivers were not used for the DMX implementation. - - c. Reimplementation of keyboard and mouse drivers from scratch for - the DMX framework. Because keyboard and mouse drivers are - relatively trivial to implement, this pathway was selected. - Other drivers in the X source tree were referenced, and - significant contributions from other drivers are noted in the - DMX source code. - - - 2. Backend Input. The front-end can make use of the core input - devices attached to one or more of the back-end X servers. Core - input events from multiple back-ends are merged into a single input - event stream. This can work sanely when only a single set of input - devices is used at any given time. The keyboard and pointer state - will be handled in the front-end, with changes propagated to the - back-end servers as needed. This option was implemented and works - well. Because the core pointer on a back-end controls the hardware - mouse on that back-end, core pointers cannot be treated as XInput - extension devices. However, all back-end XInput extensions devices - can be mapped to either DMX core or DMX XInput extension devices. - - 3. Console Input. The front-end server could create a console window - that is displayed on an X server independent of the back-end X - servers. This console window could display things like the - physical screen layout, and the front-end could get its core input - events from events delivered to the console window. This option - was implemented and works well. To help the human navigate, window - outlines are also displayed in the console window. Further, - console windows can be used as either core or XInput extension - devices. - - 4. Other options were initially explored, but they were all partial - subsets of the options listed above and, hence, are irrelevant. - - - Although extended input devices are not specifically mentioned in the - Distributed X requirements, the options above were all implemented so - that XInput extension devices were supported. - - - The bootstrap code (Xdmx) had dummy input devices, and these are still - supported in the final version. These do the necessary initialization - to satisfy the X server's requirements for core pointer and keyboard - devices, but no input events are ever generated. - - - Status: The input code is complete. Because of the complexity of the - XFree86 input device drivers (and their heavy reliance on XFree86 - infrastructure), separate low-level device drivers were implemented - for Xdmx. The following kinds of drivers are supported (in general, - the devices can be treated arbitrarily as "core" input devices or as - XInput "extension" devices; and multiple instances of different kinds - of devices can be simultaneously available): - - 1. A "dummy" device drive that never generates events. - - 2. "Local" input is from the low-level hardware on which the Xdmx - binary is running. This is the only area where using the XFree86 - driver infrastructure would have been helpful, and then only - partially, since good support for generic USB devices does not yet - exist in XFree86 (in any case, XFree86 and kdrive driver code was - used where possible). Currently, the following local devices are - supported under Linux (porting to other operating systems should be - fairly straightforward): - - +o Linux keyboard - - +o Linux serial mouse (MS) - - +o Linux PS/2 mouse - - +o USB keyboard - - +o USB mouse - - +o USB generic device (e.g., joystick, gamepad, etc.) - - - 3. "Backend" input is taken from one or more of the back-end displays. - In this case, events are taken from the back-end X server and are - converted to Xdmx events. Care must be taken so that the sprite - moves properly on the display from which input is being taken. - - 4. "Console" input is taken from an X window that Xdmx creates on the - operator's display (i.e., on the machine running the Xdmx binary). - When the operator's mouse is inside the console window, then those - events are converted to Xdmx events. Several special features are - available: the console can display outlines of windows that are on - the Xdmx display (to facilitate navigation), the cursor can be - confined to the console, and a "fine" mode can be activated to - allow very precise cursor positioning. - - - - 22..33.. OOuuttppuutt ddeevviiccee hhaannddlliinngg - - The output of the DMX system displays rendering and windowing requests - across multiple screens. The screens are typically arranged in a grid - such that together they represent a single large display. - - - The output section of the DMX code consists of two parts. The first - is in the front-end proxy X server (Xdmx), which accepts client - connections, manages the windows, and potentially renders primitives - but does not actually display any of the drawing primitives. The - second part is the back-end X server(s), which accept commands from - the front-end server and display the results on their screens. - - - 22..33..11.. IInniittiiaalliizzaattiioonn - - The DMX front-end must first initialize its screens by connecting to - each of the back-end X servers and collecting information about each - of these screens. However, the information collected from the back- - end X servers might be inconsistent. Handling these cases can be - difficult and/or inefficient. For example, a two screen system has - one back-end X server running at 16bpp while the second is running at - 32bpp. Converting rendering requests (e.g., XPutImage() or - XGetImage() requests) to the appropriate bit depth can be very time - consuming. Analyzing these cases to determine how or even if it is - possible to handle them is required. The current Xinerama code - handles many of these cases (e.g., in PanoramiXConsolidate()) and will - be used as a starting point. In general, the best solution is to use - homogeneous X servers and display devices. Using back-end servers - with the same depth is a requirement of the final DMX implementation. - - - Once this screen consolidation is finished, the relative position of - each back-end X server's screen in the unified screen is initialized. - A full-screen window is opened on each of the back-end X servers, and - the cursor on each screen is turned off. The final DMX implementation - can also make use of a partial-screen window, or multiple windows per - back-end screen. - - - 22..33..22.. HHaannddlliinngg rreennddeerriinngg rreeqquueessttss - - After initialization, X applications connect to the front-end server. - There are two possible implementations of how rendering and windowing - requests are handled in the DMX system: - - - 1. A shadow framebuffer is used in the front-end server as the render - target. In this option, all protocol requests are completely - handled in the front-end server. All state and resources are - maintained in the front-end including a shadow copy of the entire - framebuffer. The framebuffers attached to the back-end servers are - updated by XPutImage() calls with data taken directly from the - shadow framebuffer. - - - This solution suffers from two main problems. First, it does not - take advantage of any accelerated hardware available in the system. - Second, the size of the XPutImage() calls can be quite large and - thus will be limited by the bandwidth available. - - - The initial DMX implementation used a shadow framebuffer by - default. - - - 2. Rendering requests are sent to each back-end server for handling - (as is done in the Xnest server described above). In this option, - certain protocol requests are handled in the front-end server and - certain requests are repackaged and then sent to the back-end - servers. The framebuffer is distributed across the multiple back- - end servers. Rendering to the framebuffer is handled on each back- - end and can take advantage of any acceleration available on the - back-end servers' graphics display device. State is maintained - both in the front and back-end servers. - - - This solution suffers from two main drawbacks. First, protocol - requests are sent to all back-end servers -- even those that will - completely clip the rendering primitive -- which wastes bandwidth - and processing time. Second, state is maintained both in the - front- and back-end servers. These drawbacks are not as severe as - in option 1 (above) and can either be overcome through - optimizations or are acceptable. Therefore, this option will be - used in the final implementation. - - - The final DMX implementation defaults to this mechanism, but also - supports the shadow framebuffer mechanism. Several optimizations - were implemented to eliminate the drawbacks of the default - mechanism. These optimizations are described the section below and - in Phase II of the Development Results (see appendix). - - - - Status: Both the shadow framebuffer and Xnest-style code is complete. - - - - 22..44.. OOppttiimmiizziinngg DDMMXX - - Initially, the Xnest-style solution's performance will be measured and - analyzed to determine where the performance bottlenecks exist. There - are four main areas that will be addressed. - - - First, to obtain reasonable interactivity with the first development - phase, XSync() was called after each protocol request. The XSync() - function flushes any pending protocol requests. It then waits for the - back-end to process the request and send a reply that the request has - completed. This happens with each back-end server and performance - greatly suffers. As a result of the way XSync() is called in the - first development phase, the batching that the X11 library performs is - effectively defeated. The XSync() call usage will be analyzed and - optimized by batching calls and performing them at regular intervals, - except where interactivity will suffer (e.g., on cursor movements). - - - Second, the initial Xnest-style solution described above sends the - repackaged protocol requests to all back-end servers regardless of - whether or not they would be completely clipped out. The requests - that are trivially rejected on the back-end server wastes the limited - bandwidth available. By tracking clipping changes in the DMX X - server's windowing code (e.g., by opening, closing, moving or resizing - windows), we can determine whether or not back-end windows are visible - so that trivial tests in the front-end server's GC ops drawing - functions can eliminate these unnecessary protocol requests. - - - Third, each protocol request will be analyzed to determine if it is - possible to break the request into smaller pieces at display - boundaries. The initial ones to be analyzed are put and get image - requests since they will require the greatest bandwidth to transmit - data between the front and back-end servers. Other protocol requests - will be analyzed and those that will benefit from breaking them into - smaller requests will be implemented. - - - Fourth, an extension is being considered that will allow font glyphs - to be transferred from the front-end DMX X server to each back-end - server. This extension will permit the front-end to handle all font - requests and eliminate the requirement that all back-end X servers - share the exact same fonts as the front-end server. We are - investigating the feasibility of this extension during this - development phase. - - - Other potential optimizations will be determined from the performance - analysis. - - Please note that in our initial design, we proposed optimizing BLT - operations (e.g., XCopyArea() and window moves) by developing an - extension that would allow individual back-end servers to directly - copy pixel data to other back-end servers. This potential - optimization was in response to the simple image movement - implementation that required potentially many calls to GetImage() and - PutImage(). However, the current Xinerama implementation handles - these BLT operations differently. Instead of copying data to and from - screens, they generate expose events -- just as happens in the case - when a window is moved from off a screen to on screen. This approach - saves the limited bandwidth available between front and back-end - servers and is being standardized with Xinerama. It also eliminates - the potential setup problems and security issues resulting from having - each back-end server open connections to all other back-end servers. - Therefore, we suggest accepting Xinerama's expose event solution. - - - Also note that the approach proposed in the second and third - optimizations might cause backing store algorithms in the back-end to - be defeated, so a DMX X server configuration flag will be added to - disable these optimizations. - - - Status: The optimizations proposed above are complete. It was - determined that the using the xfs font server was sufficient and - creating a new mechanism to pass glyphs was redundant; therefore, the - fourth optimization proposed above was not included in DMX. - - - - 22..55.. DDMMXX XX eexxtteennssiioonn ssuuppppoorrtt - - The DMX X server keeps track of all the windowing information on the - back-end X servers, but does not currently export this information to - any client applications. An extension will be developed to pass the - screen information and back-end window IDs to DMX-aware clients. - These clients can then use this information to directly connect to and - render to the back-end windows. Bypassing the DMX X server allows - DMX-aware clients to break up complex rendering requests on their own - and send them directly to the windows on the back-end server's - screens. An example of a client that can make effective use of this - extension is Chromium. - - - Status: The extension, as implemented, is fully documented in "Client- - to-Server DMX Extension to the X Protocol". Future changes might be - required based on feedback and other proposed enhancements to DMX. - Currently, the following facilities are supported: - - 1. Screen information (clipping rectangle for each screen relative to - the virtual screen) - - 2. Window information (window IDs and clipping information for each - back-end window that corresponds to each DMX window) - - 3. Input device information (mappings from DMX device IDs to back-end - device IDs) - - 4. Force window creation (so that a client can override the server- - side lazy window creation optimization) - - 5. Reconfiguration (so that a client can request that a screen - position be changed) - - 6. Addition and removal of back-end servers and back-end and console - inputs. - 22..66.. CCoommmmoonn XX eexxtteennssiioonn ssuuppppoorrtt - - The XInput, XKeyboard and Shape extensions are commonly used - extensions to the base X11 protocol. XInput allows multiple and non- - standard input devices to be accessed simultaneously. These input - devices can be connected to either the front-end or back-end servers. - XKeyboard allows much better keyboard mappings control. Shape adds - support for arbitrarily shaped windows and is used by various window - managers. Nearly all potential back-end X servers make these - extensions available, and support for each one will be added to the - DMX system. - - - In addition to the extensions listed above, support for the X - Rendering extension (Render) is being developed. Render adds digital - image composition to the rendering model used by the X Window System. - While this extension is still under development by Keith Packard of - HP, support for the current version will be added to the DMX system. - - - Support for the XTest extension was added during the first development - phase. - - - Status: The following extensions are supported and are discussed in - more detail in Phase IV of the Development Results (see appendix): - BIG-REQUESTS, DEC-XTRAP, DMX, DPMS, Extended-Visual-Information, GLX, - LBX, RECORD, RENDER, SECURITY, SHAPE, SYNC, X-Resource, XC-APPGROUP, - XC-MISC, XFree86-Bigfont, XINERAMA, XInputExtension, XKEYBOARD, and - XTEST. - - - 22..77.. OOppeennGGLL ssuuppppoorrtt - - OpenGL support using the Mesa code base exists in XFree86 release 4 - and later. Currently, the direct rendering infrastructure (DRI) - provides accelerated OpenGL support for local clients and - unaccelerated OpenGL support (i.e., software rendering) is provided - for non-local clients. - - - The single head OpenGL support in XFree86 4.x will be extended to use - the DMX system. When the front and back-end servers are on the same - physical hardware, it is possible to use the DRI to directly render to - the back-end servers. First, the existing DRI will be extended to - support multiple display heads, and then to support the DMX system. - OpenGL rendering requests will be direct rendering to each back-end X - server. The DRI will request the screen layout (either from the - existing Xinerama extension or a DMX-specific extension). Support for - synchronized swap buffers will also be added (on hardware that - supports it). Note that a single front-end server with a single back- - end server on the same physical machine can emulate accelerated - indirect rendering. - - - When the front and back-end servers are on different physical hardware - or are using non-XFree86 4.x X servers, a mechanism to render - primitives across the back-end servers will be provided. There are - several options as to how this can be implemented. - - - 1. The existing OpenGL support in each back-end server can be used by - repackaging rendering primitives and sending them to each back-end - server. This option is similar to the unoptimized Xnest-style - approach mentioned above. Optimization of this solution is beyond - the scope of this project and is better suited to other distributed - rendering systems. - - 2. Rendering to a pixmap in the front-end server using the current - XFree86 4.x code, and then displaying to the back-ends via calls to - XPutImage() is another option. This option is similar to the - shadow frame buffer approach mentioned above. It is slower and - bandwidth intensive, but has the advantage that the back-end - servers are not required to have OpenGL support. - - - These, and other, options will be investigated in this phase of the - work. - - - Work by others have made Chromium DMX-aware. Chromium will use the - DMX X protocol extension to obtain information about the back-end - servers and will render directly to those servers, bypassing DMX. - - - Status: OpenGL support by the glxProxy extension was implemented by - SGI and has been integrated into the DMX code base. - - - - 33.. CCuurrrreenntt iissssuueess - - In this sections the current issues are outlined that require further - investigation. - - - 33..11.. FFoonnttss - - The font path and glyphs need to be the same for the front-end and - each of the back-end servers. Font glyphs could be sent to the back- - end servers as necessary but this would consume a significant amount - of available bandwidth during font rendering for clients that use many - different fonts (e.g., Netscape). Initially, the font server (xfs) - will be used to provide the fonts to both the front-end and back-end - servers. Other possibilities will be investigated during development. - - - 33..22.. ZZeerroo wwiiddtthh rreennddeerriinngg pprriimmiittiivveess - - To allow pixmap and on-screen rendering to be pixel perfect, all back- - end servers must render zero width primitives exactly the same as the - front-end renders the primitives to pixmaps. For those back-end - servers that do not exactly match, zero width primitives will be - automatically converted to one width primitives. This can be handled - in the front-end server via the GC state. - - - 33..33.. OOuuttppuutt ssccaalliinngg - - With very large tiled displays, it might be difficult to read the - information on the standard X desktop. In particular, the cursor can - be easily lost and fonts could be difficult to read. Automatic - primitive scaling might prove to be very useful. We will investigate - the possibility of scaling the cursor and providing a set of alternate - pre-scaled fonts to replace the standard fonts that many applications - use (e.g., fixed). Other options for automatic scaling will also be - investigated. - - - - 33..44.. PPeerr--ssccrreeeenn ccoolloorrmmaappss - - Each screen's default colormap in the set of back-end X servers should - be able to be adjusted via a configuration utility. This support is - would allow the back-end screens to be calibrated via custom gamma - tables. On 24-bit systems that support a DirectColor visual, this - type of correction can be accommodated. One possible implementation - would be to advertise to X client of the DMX server a TrueColor visual - while using DirectColor visuals on the back-end servers to implement - this type of color correction. Other options will be investigated. - - - AA.. BBaacckkggrroouunndd - - This section describes the existing Open Source architectures that can - be used to handle multiple screens and upon which this development - project is based. This section was written before the implementation - was finished, and may not reflect actual details of the - implementation. It is left for historical interest only. - - - AA..11.. CCoorree iinnppuutt ddeevviiccee hhaannddlliinngg - - The following is a description of how core input devices are handled - by an X server. - - - AA..11..11.. IInniittIInnppuutt(()) - - InitInput() is a DDX function that is called at the start of each - server generation from the X server's main() function. Its purpose is - to determine what input devices are connected to the X server, - register them with the DIX and MI layers, and initialize the input - event queue. InitInput() does not have a return value, but the X - server will abort if either a core keyboard device or a core pointer - device are not registered. Extended input (XInput) devices can also - be registered in InitInput(). - - - InitInput() usually has implementation specific code to determine - which input devices are available. For each input device it will be - using, it calls AddInputDevice(): - - - AAddddIInnppuuttDDeevviiccee(()) - This DIX function allocates the device structure, registers a - callback function (which handles device init, close, on and - off), and returns the input handle, which can be treated as - opaque. It is called once for each input device. - - - Once input handles for core keyboard and core pointer devices have - been obtained from AddInputDevice(), they are registered as core - devices by calling RegisterPointerDevice() and - RegisterKeyboardDevice(). Each of these should be called once. If - both core devices are not registered, then the X server will exit with - a fatal error when it attempts to start the input devices in - InitAndStartDevices(), which is called directly after InitInput() (see - below). - - - RReeggiisstteerr{{PPooiinntteerr,,KKeeyybbooaarrdd}}DDeevviiccee(()) - These DIX functions take a handle returned from AddInputDevice() - and initialize the core input device fields in inputInfo, and - initialize the input processing and grab functions for each core - input device. - The core pointer device is then registered with the miPointer code - (which does the high level cursor handling). While this registration - is not necessary for correct miPointer operation in the current - XFree86 code, it is still done mostly for compatibility reasons. - - - mmiiRReeggiisstteerrPPooiinntteerrDDeevviiccee(()) - This MI function registers the core pointer's input handle with - with the miPointer code. - - - The final part of InitInput() is the initialization of the input event - queue handling. In most cases, the event queue handling provided in - the MI layer is used. The primary XFree86 X server uses its own event - queue handling to support some special cases related to the XInput - extension and the XFree86-specific DGA extension. For our purposes, - the MI event queue handling should be suitable. It is initialized by - calling mieqInit(): - - - mmiieeqqIInniitt(()) - This MI function initializes the MI event queue for the core - devices, and is passed the public component of the input handles - for the two core devices. - - - If a wakeup handler is required to deliver synchronous input events, - it can be registered here by calling the DIX function - RegisterBlockAndWakeupHandlers(). (See the devReadInput() description - below.) - - - AA..11..22.. IInniittAAnnddSSttaarrttDDeevviicceess(()) - - InitAndStartDevices() is a DIX function that is called immediately - after InitInput() from the X server's main() function. Its purpose is - to initialize each input device that was registered with - AddInputDevice(), enable each input device that was successfully - initialized, and create the list of enabled input devices. Once each - registered device is processed in this way, the list of enabled input - devices is checked to make sure that both a core keyboard device and - core pointer device were registered and successfully enabled. If not, - InitAndStartDevices() returns failure, and results in the the X server - exiting with a fatal error. - - - Each registered device is initialized by calling its callback - (dev->deviceProc) with the DEVICE_INIT argument: - - - ((**ddeevv-->>ddeevviicceePPrroocc))((ddeevv,, DDEEVVIICCEE__IINNIITT)) - This function initializes the device structs with core - information relevant to the device. - - - For pointer devices, this means specifying the number of - buttons, default button mapping, the function used to get motion - events (usually miPointerGetMotionEvents()), the function used - to change/control the core pointer motion parameters - (acceleration and threshold), and the motion buffer size. - - - For keyboard devices, this means specifying the keycode range, - default keycode to keysym mapping, default modifier mapping, and - the functions used to sound the keyboard bell and modify/control - the keyboard parameters (LEDs, bell pitch and duration, key - click, which keys are auto-repeating, etc). - - - Each initialized device is enabled by calling EnableDevice(): - - - EEnnaabblleeDDeevviiccee(()) - EnableDevice() calls the device callback with DEVICE_ON: - - ((**ddeevv-->>ddeevviicceePPrroocc))((ddeevv,, DDEEVVIICCEE__OONN)) - This typically opens and initializes the relevant physical - device, and when appropriate, registers the device's file - descriptor (or equivalent) as a valid input source. - - - EnableDevice() then adds the device handle to the X server's - global list of enabled devices. - - - InitAndStartDevices() then verifies that a valid core keyboard and - pointer has been initialized and enabled. It returns failure if - either are missing. - - - AA..11..33.. ddeevvRReeaaddIInnppuutt(()) - - Each device will have some function that gets called to read its - physical input. These may be called in a number of different ways. - In the case of synchronous I/O, they will be called from a DDX wakeup- - handler that gets called after the server detects that new input is - available. In the case of asynchronous I/O, they will be called from - a (SIGIO) signal handler triggered when new input is available. This - function should do at least two things: make sure that input events - get enqueued, and make sure that the cursor gets moved for motion - events (except if these are handled later by the driver's own event - queue processing function, which cannot be done when using the MI - event queue handling). - - - Events are queued by calling mieqEnqueue(): - - - mmiieeqqEEnnqquueeuuee(()) - This MI function is used to add input events to the event queue. - It is simply passed the event to be queued. - - - The cursor position should be updated when motion events are enqueued, - by calling either miPointerAbsoluteCursor() or miPointerDeltaCursor(): - - - mmiiPPooiinntteerrAAbbssoolluutteeCCuurrssoorr(()) - This MI function is used to move the cursor to the absolute - coordinates provided. - - mmiiPPooiinntteerrDDeellttaaCCuurrssoorr(()) - This MI function is used to move the cursor relative to its - current position. - - - AA..11..44.. PPrroocceessssIInnppuuttEEvveennttss(()) - - ProcessInputEvents() is a DDX function that is called from the X - server's main dispatch loop when new events are available in the input - event queue. It typically processes the enqueued events, and updates - the cursor/pointer position. It may also do other DDX-specific event - processing. - - - Enqueued events are processed by mieqProcessInputEvents() and passed - to the DIX layer for transmission to clients: - - - mmiieeqqPPrroocceessssIInnppuuttEEvveennttss(()) - This function processes each event in the event queue, and - passes it to the device's input processing function. The DIX - layer provides default functions to do this processing, and they - handle the task of getting the events passed back to the - relevant clients. - - mmiiPPooiinntteerrUUppddaattee(()) - This function resynchronized the cursor position with the new - pointer position. It also takes care of moving the cursor - between screens when needed in multi-head configurations. - - - - AA..11..55.. DDiissaabblleeDDeevviiccee(()) - - DisableDevice is a DIX function that removes an input device from the - list of enabled devices. The result of this is that the device no - longer generates input events. The device's data structures are kept - in place, and disabling a device like this can be reversed by calling - EnableDevice(). DisableDevice() may be called from the DDX when it is - desirable to do so (e.g., the XFree86 server does this when VT - switching). Except for special cases, this is not normally called for - core input devices. - - - DisableDevice() calls the device's callback function with DEVICE_OFF: - - - ((**ddeevv-->>ddeevviicceePPrroocc))((ddeevv,, DDEEVVIICCEE__OOFFFF)) - This typically closes the relevant physical device, and when - appropriate, unregisters the device's file descriptor (or - equivalent) as a valid input source. - - - DisableDevice() then removes the device handle from the X server's - global list of enabled devices. - - - - AA..11..66.. CClloosseeDDeevviiccee(()) - - CloseDevice is a DIX function that removes an input device from the - list of available devices. It disables input from the device and - frees all data structures associated with the device. This function - is usually called from CloseDownDevices(), which is called from main() - at the end of each server generation to close all input devices. - - - CloseDevice() calls the device's callback function with DEVICE_CLOSE: - - - ((**ddeevv-->>ddeevviicceePPrroocc))((ddeevv,, DDEEVVIICCEE__CCLLOOSSEE)) - This typically closes the relevant physical device, and when - appropriate, unregisters the device's file descriptor (or - equivalent) as a valid input source. If any device specific - data structures were allocated when the device was initialized, - they are freed here. - - CloseDevice() then frees the data structures that were allocated for - the device when it was registered/initialized. - - - - AA..11..77.. LLeeggaallMMooddiiffiieerr(()) - - LegalModifier() is a required DDX function that can be used to - restrict which keys may be modifier keys. This seems to be present - for historical reasons, so this function should simply return TRUE - unconditionally. - - - - AA..22.. OOuuttppuutt hhaannddlliinngg - - The following sections describe the main functions required to - initialize, use and close the output device(s) for each screen in the - X server. - - - AA..22..11.. IInniittOOuuttppuutt(()) - - This DDX function is called near the start of each server generation - from the X server's main() function. InitOutput()'s main purpose is - to initialize each screen and fill in the global screenInfo structure - for each screen. It is passed three arguments: a pointer to the - screenInfo struct, which it is to initialize, and argc and argv from - main(), which can be used to determine additional configuration - information. - - - The primary tasks for this function are outlined below: - - - 1. PPaarrssee ccoonnffiigguurraattiioonn iinnffoo:: The first task of InitOutput() is to - parses any configuration information from the configuration file. - In addition to the XF86Config file, other configuration information - can be taken from the command line. The command line options can - be gathered either in InitOutput() or earlier in the - ddxProcessArgument() function, which is called by - ProcessCommandLine(). The configuration information determines the - characteristics of the screen(s). For example, in the XFree86 X - server, the XF86Config file specifies the monitor information, the - screen resolution, the graphics devices and slots in which they are - located, and, for Xinerama, the screens' layout. - - 2. IInniittiiaalliizzee ssccrreeeenn iinnffoo:: The next task is to initialize the screen- - dependent internal data structures. For example, part of what the - XFree86 X server does is to allocate its screen and pixmap private - indices, probe for graphics devices, compare the probed devices to - the ones listed in the XF86Config file, and add the ones that match - to the internal xf86Screens[] structure. - - 3. SSeett ppiixxmmaapp ffoorrmmaattss:: The next task is to initialize the screenInfo's - image byte order, bitmap bit order and bitmap scanline unit/pad. - The screenInfo's pixmap format's depth, bits per pixel and scanline - padding is also initialized at this stage. - - 4. UUnniiffyy ssccrreeeenn iinnffoo:: An optional task that might be done at this - stage is to compare all of the information from the various screens - and determines if they are compatible (i.e., if the set of screens - can be unified into a single desktop). This task has potential to - be useful to the DMX front-end server, if Xinerama's - PanoramiXConsolidate() function is not sufficient. - - Once these tasks are complete, the valid screens are known and each of - these screens can be initialized by calling AddScreen(). - - - AA..22..22.. AAddddSSccrreeeenn(()) - - This DIX function is called from InitOutput(), in the DDX layer, to - add each new screen to the screenInfo structure. The DDX screen - initialization function and command line arguments (i.e., argc and - argv) are passed to it as arguments. - - - This function first allocates a new Screen structure and any privates - that are required. It then initializes some of the fields in the - Screen struct and sets up the pixmap padding information. Finally, it - calls the DDX screen initialization function ScreenInit(), which is - described below. It returns the number of the screen that were just - added, or -1 if there is insufficient memory to add the screen or if - the DDX screen initialization fails. - - - AA..22..33.. SSccrreeeennIInniitt(()) - - This DDX function initializes the rest of the Screen structure with - either generic or screen-specific functions (as necessary). It also - fills in various screen attributes (e.g., width and height in - millimeters, black and white pixel values). - - - The screen init function usually calls several functions to perform - certain screen initialization functions. They are described below: - - - {{mmii,,**ffbb}}SSccrreeeennIInniitt(()) - The DDX layer's ScreenInit() function usually calls another - layer's ScreenInit() function (e.g., miScreenInit() or - fbScreenInit()) to initialize the fallbacks that the DDX driver - does not specifically handle. - - - After calling another layer's ScreenInit() function, any screen- - specific functions either wrap or replace the other layer's - function pointers. If a function is to be wrapped, each of the - old function pointers from the other layer are stored in a - screen private area. Common functions to wrap are CloseScreen() - and SaveScreen(). - - - mmiiIInniittiiaalliizzeeBBaacckkiinnggSSttoorree(()) - This MI function initializes the screen's backing storage - functions, which are used to save areas of windows that are - currently covered by other windows. - - - mmiiDDCCIInniittiiaalliizzee(()) - This MI function initializes the MI cursor display structures - and function pointers. If a hardware cursor is used, the DDX - layer's ScreenInit() function will wrap additional screen and - the MI cursor display function pointers. - - - Another common task for ScreenInit() function is to initialize the - output device state. For example, in the XFree86 X server, the - ScreenInit() function saves the original state of the video card and - then initializes the video mode of the graphics device. - - AA..22..44.. CClloosseeSSccrreeeenn(()) - - This function restores any wrapped screen functions (and in particular - the wrapped CloseScreen() function) and restores the state of the - output device to its original state. It should also free any private - data it created during the screen initialization. - - - AA..22..55.. GGCC ooppeerraattiioonnss - - When the X server is requested to render drawing primitives, it does - so by calling drawing functions through the graphics context's - operation function pointer table (i.e., the GCOps functions). These - functions render the basic graphics operations such as drawing - rectangles, lines, text or copying pixmaps. Default routines are - provided either by the MI layer, which draws indirectly through a - simple span interface, or by the framebuffer layers (e.g., CFB, MFB, - FB), which draw directly to a linearly mapped frame buffer. - - - To take advantage of special hardware on the graphics device, specific - GCOps functions can be replaced by device specific code. However, - many times the graphics devices can handle only a subset of the - possible states of the GC, so during graphics context validation, - appropriate routines are selected based on the state and capabilities - of the hardware. For example, some graphics hardware can accelerate - single pixel width lines with certain dash patterns. Thus, for dash - patterns that are not supported by hardware or for width 2 or greater - lines, the default routine is chosen during GC validation. - - - Note that some pointers to functions that draw to the screen are - stored in the Screen structure. They include GetImage(), GetSpans(), - PaintWindowBackground(), PaintWindowBorder(), CopyWindow() and - RestoreAreas(). - - - AA..22..66.. XXnneesstt - - The Xnest X server is a special proxy X server that relays the X - protocol requests that it receives to a ``real'' X server that then - processes the requests and displays the results, if applicable. To - the X applications, Xnest appears as if it is a regular X server. - However, Xnest is both server to the X application and client of the - real X server, which will actually handle the requests. - - - The Xnest server implements all of the standard input and output - initialization steps outlined above. - - - IInniittOOuuttppuutt(()) - Xnest takes its configuration information from command line - arguments via ddxProcessArguments(). This information includes - the real X server display to connect to, its default visual - class, the screen depth, the Xnest window's geometry, etc. - Xnest then connects to the real X server and gathers visual, - colormap, depth and pixmap information about that server's - display, creates a window on that server, which will be used as - the root window for Xnest. - - - Next, Xnest initializes its internal data structures and uses - the data from the real X server's pixmaps to initialize its own - pixmap formats. Finally, it calls AddScreen(xnestOpenScreen, - argc, argv) to initialize each of its screens. - SSccrreeeennIInniitt(()) - Xnest's ScreenInit() function is called xnestOpenScreen(). This - function initializes its screen's depth and visual information, - and then calls miScreenInit() to set up the default screen - functions. It then calls miInitializeBackingStore() and - miDCInitialize() to initialize backing store and the software - cursor. Finally, it replaces many of the screen functions with - its own functions that repackage and send the requests to the - real X server to which Xnest is attached. - - - CClloosseeSSccrreeeenn(()) - This function frees its internal data structure allocations. - Since it replaces instead of wrapping screen functions, there - are no function pointers to unwrap. This can potentially lead - to problems during server regeneration. - - - GGCC ooppeerraattiioonnss - The GC operations in Xnest are very simple since they leave all - of the drawing to the real X server to which Xnest is attached. - Each of the GCOps takes the request and sends it to the real X - server using standard Xlib calls. For example, the X - application issues a XDrawLines() call. This function turns - into a protocol request to Xnest, which calls the - xnestPolylines() function through Xnest's GCOps function pointer - table. The xnestPolylines() function is only a single line, - which calls XDrawLines() using the same arguments that were - passed into it. Other GCOps functions are very similar. Two - exceptions to the simple GCOps functions described above are the - image functions and the BLT operations. - - - The image functions, GetImage() and PutImage(), must use a - temporary image to hold the image to be put of the image that - was just grabbed from the screen while it is in transit to the - real X server or the client. When the image has been - transmitted, the temporary image is destroyed. - - - The BLT operations, CopyArea() and CopyPlane(), handle not only - the copy function, which is the same as the simple cases - described above, but also the graphics exposures that result - when the GC's graphics exposure bit is set to True. Graphics - exposures are handled in a helper function, - xnestBitBlitHelper(). This function collects the exposure - events from the real X server and, if any resulting in regions - being exposed, then those regions are passed back to the MI - layer so that it can generate exposure events for the X - application. - - - The Xnest server takes its input from the X server to which it is - connected. When the mouse is in the Xnest server's window, keyboard - and mouse events are received by the Xnest server, repackaged and sent - back to any client that requests those events. - - - AA..22..77.. SShhaaddooww ffrraammeebbuuffffeerr - - The most common type of framebuffer is a linear array memory that maps - to the video memory on the graphics device. However, accessing that - video memory over an I/O bus (e.g., ISA or PCI) can be slow. The - shadow framebuffer layer allows the developer to keep the entire - framebuffer in main memory and copy it back to video memory at regular - intervals. It also has been extended to handle planar video memory - and rotated framebuffers. - - - There are two main entry points to the shadow framebuffer code: - - - sshhaaddoowwAAlllloocc((wwiiddtthh,, hheeiigghhtt,, bbpppp)) - This function allocates the in memory copy of the framebuffer of - size width*height*bpp. It returns a pointer to that memory, - which will be used by the framebuffer ScreenInit() code during - the screen's initialization. - - - sshhaaddoowwIInniitt((ppSSccrreeeenn,, uuppddaatteePPrroocc,, wwiinnddoowwPPrroocc)) - This function initializes the shadow framebuffer layer. It - wraps several screen drawing functions, and registers a block - handler that will update the screen. The updateProc is a - function that will copy the damaged regions to the screen, and - the windowProc is a function that is used when the entire linear - video memory range cannot be accessed simultaneously so that - only a window into that memory is available (e.g., when using - the VGA aperture). - - - The shadow framebuffer code keeps track of the damaged area of each - screen by calculating the bounding box of all drawing operations that - have occurred since the last screen update. Then, when the block - handler is next called, only the damaged portion of the screen is - updated. - - - Note that since the shadow framebuffer is kept in main memory, all - drawing operations are performed by the CPU and, thus, no accelerated - hardware drawing operations are possible. - - - - AA..33.. XXiinneerraammaa - - Xinerama is an X extension that allows multiple physical screens - controlled by a single X server to appear as a single screen. - Although the extension allows clients to find the physical screen - layout via extension requests, it is completely transparent to clients - at the core X11 protocol level. The original public implementation of - Xinerama came from Digital/Compaq. XFree86 rewrote it, filling in - some missing pieces and improving both X11 core protocol compliance - and performance. The Xinerama extension will be passing through - X.Org's standardization process in the near future, and the sample - implementation will be based on this rewritten version. - - - The current implementation of Xinerama is based primarily in the DIX - (device independent) and MI (machine independent) layers of the X - server. With few exceptions the DDX layers do not need any changes to - support Xinerama. X server extensions often do need modifications to - provide full Xinerama functionality. - - - The following is a code-level description of how Xinerama functions. - - - Note: Because the Xinerama extension was originally called the - PanoramiX extension, many of the Xinerama functions still have the - PanoramiX prefix. - - - PPaannoorraammiiXXEExxtteennssiioonnIInniitt(()) - PanoramiXExtensionInit() is a device-independent extension - function that is called at the start of each server generation - from InitExtensions(), which is called from the X server's - main() function after all output devices have been initialized, - but before any input devices have been initialized. - - - PanoramiXNumScreens is set to the number of physical screens. - If only one physical screen is present, the extension is - disabled, and PanoramiXExtensionInit() returns without doing - anything else. - - - The Xinerama extension is registered by calling AddExtension(). - - - A local per-screen array of data structures (panoramiXdataPtr[]) - is allocated for each physical screen, and GC and Screen private - indexes are allocated, and both GC and Screen private areas are - allocated for each physical screen. These hold Xinerama- - specific per-GC and per-Screen data. Each screen's CreateGC and - CloseScreen functions are wrapped by XineramaCreateGC() and - XineramaCloseScreen() respectively. Some new resource classes - are created for Xinerama drawables and GCs, and resource types - for Xinerama windows, pixmaps and colormaps. - - - A region (XineramaScreenRegions[i]) is initialized for each - physical screen, and single region (PanoramiXScreenRegion) is - initialized to be the union of the screen regions. The - panoramiXdataPtr[] array is also initialized with the size and - origin of each screen. The relative positioning information for - the physical screens is taken from the array dixScreenOrigins[], - which the DDX layer must initialize in InitOutput(). The bounds - of the combined screen is also calculated (PanoramiXPixWidth and - PanoramiXPixHeight). - - - The DIX layer has a list of function pointers (ProcVector[]) - that holds the entry points for the functions that process core - protocol requests. The requests that Xinerama must intercept - and break up into physical screen-specific requests are wrapped. - The original set is copied to SavedProcVector[]. The types of - requests intercepted are Window requests, GC requests, colormap - requests, drawing requests, and some geometry-related requests. - This wrapping allows the bulk of the protocol request processing - to be handled transparently to the DIX layer. Some operations - cannot be dealt with in this way and are handled with Xinerama- - specific code within the DIX layer. - - - PPaannoorraammiiXXCCoonnssoolliiddaattee(()) - PanoramiXConsolidate() is a device-independent extension - function that is called directly from the X server's main() - function after extensions and input/output devices have been - initialized, and before the root windows are defined and - initialized. - - - This function finds the set of depths (PanoramiXDepths[]) and - visuals (PanoramiXVisuals[]) common to all of the physical - screens. PanoramiXNumDepths is set to the number of common - depths, and PanoramiXNumVisuals is set to the number of common - visuals. Resources are created for the single root window and - the default colormap. Each of these resources has per-physical - screen entries. - - - PPaannoorraammiiXXCCrreeaatteeCCoonnnneeccttiioonnBBlloocckk(()) - PanoramiXConsolidate() is a device-independent extension - function that is called directly from the X server's main() - function after the per-physical screen root windows are created. - It is called instead of the standard DIX CreateConnectionBlock() - function. If this function returns FALSE, the X server exits - with a fatal error. This function will return FALSE if no - common depths were found in PanoramiXConsolidate(). With no - common depths, Xinerama mode is not possible. - - - The connection block holds the information that clients get when - they open a connection to the X server. It includes information - such as the supported pixmap formats, number of screens and the - sizes, depths, visuals, default colormap information, etc, for - each of the screens (much of information that xdpyinfo shows). - The connection block is initialized with the combined single - screen values that were calculated in the above two functions. - - - The Xinerama extension allows the registration of connection - block callback functions. The purpose of these is to allow - other extensions to do processing at this point. These - callbacks can be registered by calling - XineramaRegisterConnectionBlockCallback() from the other - extension's ExtensionInit() function. Each registered - connection block callback is called at the end of - PanoramiXCreateConnectionBlock(). - - - AA..33..11.. XXiinneerraammaa--ssppeecciiffiicc cchhaannggeess ttoo tthhee DDIIXX ccooddee - - There are a few types of Xinerama-specific changes within the DIX - code. The main ones are described here. - - - Functions that deal with colormap or GC -related operations outside of - the intercepted protocol requests have a test added to only do the - processing for screen numbers > 0. This is because they are handled - for the single Xinerama screen and the processing is done once for - screen 0. - - - The handling of motion events does some coordinate translation between - the physical screen's origin and screen zero's origin. Also, motion - events must be reported relative to the composite screen origin rather - than the physical screen origins. - - - There is some special handling for cursor, window and event processing - that cannot (either not at all or not conveniently) be done via the - intercepted protocol requests. A particular case is the handling of - pointers moving between physical screens. - - - AA..33..22.. XXiinneerraammaa--ssppeecciiffiicc cchhaannggeess ttoo tthhee MMII ccooddee - - The only Xinerama-specific change to the MI code is in - miSendExposures() to handle the coordinate (and window ID) translation - for expose events. - - - - AA..33..33.. IInntteerrcceepptteedd DDIIXX ccoorree rreeqquueessttss - - Xinerama breaks up drawing requests for dispatch to each physical - screen. It also breaks up windows into pieces for each physical - screen. GCs are translated into per-screen GCs. Colormaps are - replicated on each physical screen. The functions handling the - intercepted requests take care of breaking the requests and - repackaging them so that they can be passed to the standard request - handling functions for each screen in turn. In addition, and to aid - the repackaging, the information from many of the intercepted requests - is used to keep up to date the necessary state information for the - single composite screen. Requests (usually those with replies) that - can be satisfied completely from this stored state information do not - call the standard request handling functions. - - - - BB.. DDeevveellooppmmeenntt RReessuullttss - - In this section the results of each phase of development are - discussed. This development took place between approximately June - 2001 and July 2003. - - - BB..11.. PPhhaassee II - - The initial development phase dealt with the basic implementation - including the bootstrap code, which used the shadow framebuffer, and - the unoptimized implementation, based on an Xnest-style - implementation. - - - BB..11..11.. SSccooppee - - The goal of Phase I is to provide fundamental functionality that can - act as a foundation for ongoing work: - - 1. Develop the proxy X server - - +o The proxy X server will operate on the X11 protocol and relay - requests as necessary to correctly perform the request. - - +o Work will be based on the existing work for Xinerama and Xnest. - - +o Input events and windowing operations are handled in the proxy - server and rendering requests are repackaged and sent to each of - the back-end servers for display. - - +o The multiple screen layout (including support for overlapping - screens) will be user configurable via a configuration file or - through the configuration tool. - - 2. Develop graphical configuration tool - - +o There will be potentially a large number of X servers to - configure into a single display. The tool will allow the user - to specify which servers are involved in the configuration and - how they should be laid out. - - 3. Pass the X Test Suite - - +o The X Test Suite covers the basic X11 operations. All tests - known to succeed must correctly operate in the distributed X - environment. - - - For this phase, the back-end X servers are assumed to be unmodified X - servers that do not support any DMX-related protocol extensions; - future optimization pathways are considered, but are not implemented; - and the configuration tool is assumed to rely only on libraries in the - X source tree (e.g., Xt). - - - BB..11..22.. RReessuullttss - - The proxy X server, Xdmx, was developed to distribute X11 protocol - requests to the set of back-end X servers. It opens a window on each - back-end server, which represents the part of the front-end's root - window that is visible on that screen. It mirrors window, pixmap and - other state in each back-end server. Drawing requests are sent to - either windows or pixmaps on each back-end server. This code is based - on Xnest and uses the existing Xinerama extension. - - - Input events can be taken from (1) devices attached to the back-end - server, (2) core devices attached directly to the Xdmx server, or (3) - from a ``console'' window on another X server. Events for these - devices are gathered, processed and delivered to clients attached to - the Xdmx server. - - - An intuitive configuration format was developed to help the user - easily configure the multiple back-end X servers. It was defined (see - grammar in Xdmx man page) and a parser was implemented that is used by - the Xdmx server and by a standalone xdmxconfig utility. The parsing - support was implemented such that it can be easily factored out of the - X source tree for use with other tools (e.g., vdl). Support for - converting legacy vdl-format configuration files to the DMX format is - provided by the vdltodmx utility. - - - Originally, the configuration file was going to be a subsection of - XFree86's XF86Config file, but that was not possible since Xdmx is a - completely separate X server. Thus, a separate config file format was - developed. In addition, a graphical configuration tool, xdmxconfig, - was developed to allow the user to create and arrange the screens in - the configuration file. The --ccoonnffiiggffiillee and --ccoonnffiigg command-line - options can be used to start Xdmx using a configuration file. - - - An extension that enables remote input testing is required for the X - Test Suite to function. During this phase, this extension (XTEST) was - implemented in the Xdmx server. The results from running the X Test - Suite are described in detail below. - - - BB..11..33.. XX TTeesstt SSuuiittee - - BB..11..33..11.. IInnttrroodduuccttiioonn - - The X Test Suite contains tests that verify Xlib functions operate - correctly. The test suite is designed to run on a single X server; - however, since X applications will not be able to tell the difference - between the DMX server and a standard X server, the X Test Suite - should also run on the DMX server. - - The Xdmx server was tested with the X Test Suite, and the existing - failures are noted in this section. To put these results in - perspective, we first discuss expected X Test failures and how errors - in underlying systems can impact Xdmx test results. - - - BB..11..33..22.. EExxppeecctteedd FFaaiilluurreess ffoorr aa SSiinnggllee HHeeaadd - - A correctly implemented X server with a single screen is expected to - fail certain X Test tests. The following well-known errors occur - because of rounding error in the X server code: - - XDrawArc: Tests 42, 63, 66, 73 - XDrawArcs: Tests 45, 66, 69, 76 - - - - The following failures occur because of the high-level X server - implementation: - - XLoadQueryFont: Test 1 - XListFontsWithInfo: Tests 3, 4 - XQueryFont: Tests 1, 2 - - - - The following test fails when running the X server as root under Linux - because of the way directory modes are interpreted: - - XWriteBitmapFile: Test 3 - - - - Depending on the video card used for the back-end, other failures may - also occur because of bugs in the low-level driver implementation. - Over time, failures of this kind are usually fixed by XFree86, but - will show up in Xdmx testing until then. - - - BB..11..33..33.. EExxppeecctteedd FFaaiilluurreess ffoorr XXiinneerraammaa - - Xinerama fails several X Test Suite tests because of design decisions - made for the current implementation of Xinerama. Over time, many of - these errors will be corrected by XFree86 and the group working on a - new Xinerama implementation. Therefore, Xdmx will also share X Suite - Test failures with Xinerama. - - We may be able to fix or work-around some of these failures at the - Xdmx level, but this will require additional exploration that was not - part of Phase I. - - Xinerama is constantly improving, and the list of Xinerama-related - failures depends on XFree86 version and the underlying graphics - hardware. We tested with a variety of hardware, including nVidia, S3, - ATI Radeon, and Matrox G400 (in dual-head mode). The list below - includes only those failures that appear to be from the Xinerama - layer, and does not include failures listed in the previous section, - or failures that appear to be from the low-level graphics driver - itself: - - These failures were noted with multiple Xinerama configurations: - - XCopyPlane: Tests 13, 22, 31 (well-known Xinerama implementation issue) - XSetFontPath: Test 4 - XGetDefault: Test 5 - XMatchVisualInfo: Test 1 - - - - These failures were noted only when using one dual-head video card - with a 4.2.99.x XFree86 server: - - XListPixmapFormats: Test 1 - XDrawRectangles: Test 45 - - - - These failures were noted only when using two video cards from - different vendors with a 4.1.99.x XFree86 server: - - XChangeWindowAttributes: Test 32 - XCreateWindow: Test 30 - XDrawLine: Test 22 - XFillArc: Test 22 - XChangeKeyboardControl: Tests 9, 10 - XRebindKeysym: Test 1 - - - - BB..11..33..44.. AAddddiittiioonnaall FFaaiilluurreess ffrroomm XXddmmxx - - When running Xdmx, no unexpected failures were noted. Since the Xdmx - server is based on Xinerama, we expect to have most of the Xinerama - failures present in the Xdmx server. Similarly, since the Xdmx server - must rely on the low-level device drivers on each back-end server, we - also expect that Xdmx will exhibit most of the back-end failures. - Here is a summary: - - XListPixmapFormats: Test 1 (configuration dependent) - XChangeWindowAttributes: Test 32 - XCreateWindow: Test 30 - XCopyPlane: Test 13, 22, 31 - XSetFontPath: Test 4 - XGetDefault: Test 5 (configuration dependent) - XMatchVisualInfo: Test 1 - XRebindKeysym: Test 1 (configuration dependent) - - - - Note that this list is shorter than the combined list for Xinerama - because Xdmx uses different code paths to perform some Xinerama - operations. Further, some Xinerama failures have been fixed in the - XFree86 4.2.99.x CVS repository. - - - BB..11..33..55.. SSuummmmaarryy aanndd FFuuttuurree WWoorrkk - - Running the X Test Suite on Xdmx does not produce any failures that - cannot be accounted for by the underlying Xinerama subsystem used by - the front-end or by the low-level device-driver code running on the - back-end X servers. The Xdmx server therefore is as ``correct'' as - possible with respect to the standard set of X Test Suite tests. - - During the following phases, we will continue to verify Xdmx - correctness using the X Test Suite. We may also use other tests - suites or write additional tests that run under the X Test Suite that - specifically verify the expected behavior of DMX. - - - - BB..11..44.. FFoonnttss - - In Phase I, fonts are handled directly by both the front-end and the - back-end servers, which is required since we must treat each back-end - server during this phase as a ``black box''. What this requires is - that tthhee ffrroonntt-- aanndd bbaacckk--eenndd sseerrvveerrss mmuusstt sshhaarree tthhee eexxaacctt ssaammee ffoonntt - ppaatthh. There are two ways to help make sure that all servers share the - same font path: - - - 1. First, each server can be configured to use the same font server. - The font server, xfs, can be configured to serve fonts to multiple - X servers via TCP. - - 2. Second, each server can be configured to use the same font path and - either those font paths can be copied to each back-end machine or - they can be mounted (e.g., via NFS) on each back-end machine. - - - One additional concern is that a client program can set its own font - path, and if it does so, then that font path must be available on each - back-end machine. - - - The -fontpath command line option was added to allow users to - initialize the font path of the front end server. This font path is - propagated to each back-end server when the default font is loaded. - If there are any problems, an error message is printed, which will - describe the problem and list the current font path. For more - information about setting the font path, see the -fontpath option - description in the man page. - - - BB..11..55.. PPeerrffoorrmmaannccee - - Phase I of development was not intended to optimize performance. Its - focus was on completely and correctly handling the base X11 protocol - in the Xdmx server. However, several insights were gained during - Phase I, which are listed here for reference during the next phase of - development. - - - 1. Calls to XSync() can slow down rendering since it requires a - complete round trip to and from a back-end server. This is - especially problematic when communicating over long haul networks. - - 2. Sending drawing requests to only the screens that they overlap - should improve performance. - - - BB..11..66.. PPiixxmmaappss - - Pixmaps were originally expected to be handled entirely in the front- - end X server; however, it was found that this overly complicated the - rendering code and would have required sending potentially large - images to each back server that required them when copying from pixmap - to screen. Thus, pixmap state is mirrored in the back-end server just - as it is with regular window state. With this implementation, the - same rendering code that draws to windows can be used to draw to - pixmaps on the back-end server, and no large image transfers are - required to copy from pixmap to window. - - - - BB..22.. PPhhaassee IIII - - The second phase of development concentrates on performance - optimizations. These optimizations are documented here, with x11perf - data to show how the optimizations improve performance. - - - All benchmarks were performed by running Xdmx on a dual processor - 1.4GHz AMD Athlon machine with 1GB of RAM connecting over 100baseT to - two single-processor 1GHz Pentium III machines with 256MB of RAM and - ATI Rage 128 (RF) video cards. The front end was running Linux - 2.4.20-pre1-ac1 and the back ends were running Linux 2.4.7-10 and - version 4.2.99.1 of XFree86 pulled from the XFree86 CVS repository on - August 7, 2002. All systems were running Red Hat Linux 7.2. - - - BB..22..11.. MMoovviinngg ffrroomm XXFFrreeee8866 44..11..9999..11 ttoo 44..22..00..00 - - For phase II, the working source tree was moved to the branch tagged - with dmx-1-0-branch and was updated from version 4.1.99.1 (20 August - 2001) of the XFree86 sources to version 4.2.0.0 (18 January 2002). - After this update, the following tests were noted to be more than 10% - faster: - - 1.13 Fill 300x300 opaque stippled trapezoid (161x145 stipple) - 1.16 Fill 1x1 tiled trapezoid (161x145 tile) - 1.13 Fill 10x10 tiled trapezoid (161x145 tile) - 1.17 Fill 100x100 tiled trapezoid (161x145 tile) - 1.16 Fill 1x1 tiled trapezoid (216x208 tile) - 1.20 Fill 10x10 tiled trapezoid (216x208 tile) - 1.15 Fill 100x100 tiled trapezoid (216x208 tile) - 1.37 Circulate Unmapped window (200 kids) - - - - And the following tests were noted to be more than 10% slower: - - 0.88 Unmap window via parent (25 kids) - 0.75 Circulate Unmapped window (4 kids) - 0.79 Circulate Unmapped window (16 kids) - 0.80 Circulate Unmapped window (25 kids) - 0.82 Circulate Unmapped window (50 kids) - 0.85 Circulate Unmapped window (75 kids) - - - - These changes were not caused by any changes in the DMX system, and - may point to changes in the XFree86 tree or to tests that have more - "jitter" than most other x11perf tests. - - - BB..22..22.. GGlloobbaall cchhaannggeess - - During the development of the Phase II DMX server, several global - changes were made. These changes were also compared with the Phase I - server. The following tests were noted to be more than 10% faster: - - - - 1.13 Fill 300x300 opaque stippled trapezoid (161x145 stipple) - 1.15 Fill 1x1 tiled trapezoid (161x145 tile) - 1.13 Fill 10x10 tiled trapezoid (161x145 tile) - 1.17 Fill 100x100 tiled trapezoid (161x145 tile) - 1.16 Fill 1x1 tiled trapezoid (216x208 tile) - 1.19 Fill 10x10 tiled trapezoid (216x208 tile) - 1.15 Fill 100x100 tiled trapezoid (216x208 tile) - 1.15 Circulate Unmapped window (4 kids) - - - - The following tests were noted to be more than 10% slower: - - 0.69 Scroll 10x10 pixels - 0.68 Scroll 100x100 pixels - 0.68 Copy 10x10 from window to window - 0.68 Copy 100x100 from window to window - 0.76 Circulate Unmapped window (75 kids) - 0.83 Circulate Unmapped window (100 kids) - - - - For the remainder of this analysis, the baseline of comparison will be - the Phase II deliverable with all optimizations disabled (unless - otherwise noted). This will highlight how the optimizations in - isolation impact performance. - - - BB..22..33.. XXSSyynncc(()) BBaattcchhiinngg - - During the Phase I implementation, XSync() was called after every - protocol request made by the DMX server. This provided the DMX server - with an interactive feel, but defeated X11's protocol buffering system - and introduced round-trip wire latency into every operation. During - Phase II, DMX was changed so that protocol requests are no longer - followed by calls to XSync(). Instead, the need for an XSync() is - noted, and XSync() calls are only made every 100mS or when the DMX - server specifically needs to make a call to guarantee interactivity. - With this new system, X11 buffers protocol as much as possible during - a 100mS interval, and many unnecessary XSync() calls are avoided. - - - Out of more than 300 x11perf tests, 8 tests became more than 100 times - faster, with 68 more than 50X faster, 114 more than 10X faster, and - 181 more than 2X faster. See table below for summary. - - - The following tests were noted to be more than 10% slower with XSync() - batching on: - - 0.88 500x500 tiled rectangle (161x145 tile) - 0.89 Copy 500x500 from window to window - - - - BB..22..44.. OOffffssccrreeeenn OOppttiimmiizzaattiioonn - - Windows span one or more of the back-end servers' screens; however, - during Phase I development, windows were created on every back-end - server and every rendering request was sent to every window regardless - of whether or not that window was visible. With the offscreen - optimization, the DMX server tracks when a window is completely off of - a back-end server's screen and, in that case, it does not send - rendering requests to those back-end windows. This optimization saves - bandwidth between the front and back-end servers, and it reduces the - number of XSync() calls. The performance tests were run on a DMX - system with only two back-end servers. Greater performance gains will - be had as the number of back-end servers increases. - - - Out of more than 300 x11perf tests, 3 tests were at least twice as - fast, and 146 tests were at least 10% faster. Two tests were more - than 10% slower with the offscreen optimization: - - 0.88 Hide/expose window via popup (4 kids) - 0.89 Resize unmapped window (75 kids) - - - - BB..22..55.. LLaazzyy WWiinnddooww CCrreeaattiioonn OOppttiimmiizzaattiioonn - - As mentioned above, during Phase I, windows were created on every - back-end server even if they were not visible on that back-end. With - the lazy window creation optimization, the DMX server does not create - windows on a back-end server until they are either visible or they - become the parents of a visible window. This optimization builds on - the offscreen optimization (described above) and requires it to be - enabled. - - - The lazy window creation optimization works by creating the window - data structures in the front-end server when a client creates a - window, but delays creation of the window on the back-end server(s). - A private window structure in the DMX server saves the relevant window - data and tracks changes to the window's attributes and stacking order - for later use. The only times a window is created on a back-end - server are (1) when it is mapped and is at least partially overlapping - the back-end server's screen (tracked by the offscreen optimization), - or (2) when the window becomes the parent of a previously visible - window. The first case occurs when a window is mapped or when a - visible window is copied, moved or resized and now overlaps the back- - end server's screen. The second case occurs when starting a window - manager after having created windows to which the window manager needs - to add decorations. - - - When either case occurs, a window on the back-end server is created - using the data saved in the DMX server's window private data - structure. The stacking order is then adjusted to correctly place the - window on the back-end and lastly the window is mapped. From this - time forward, the window is handled exactly as if the window had been - created at the time of the client's request. - - - Note that when a window is no longer visible on a back-end server's - screen (e.g., it is moved offscreen), the window is not destroyed; - rather, it is kept and reused later if the window once again becomes - visible on the back-end server's screen. Originally with this - optimization, destroying windows was implemented but was later - rejected because it increased bandwidth when windows were opaquely - moved or resized, which is common in many window managers. - - - - The performance tests were run on a DMX system with only two back-end - servers. Greater performance gains will be had as the number of back- - end servers increases. - - - This optimization improved the following x11perf tests by more than - 10%: - - 1.10 500x500 rectangle outline - 1.12 Fill 100x100 stippled trapezoid (161x145 stipple) - 1.20 Circulate Unmapped window (50 kids) - 1.19 Circulate Unmapped window (75 kids) - - - - BB..22..66.. SSuubbddiivviiddiinngg RReennddeerriinngg PPrriimmiittiivveess - - X11 imaging requests transfer significant data between the client and - the X server. During Phase I, the DMX server would then transfer the - image data to each back-end server. Even with the offscreen - optimization (above), these requests still required transferring - significant data to each back-end server that contained a visible - portion of the window. For example, if the client uses XPutImage() to - copy an image to a window that overlaps the entire DMX screen, then - the entire image is copied by the DMX server to every back-end server. - - - To reduce the amount of data transferred between the DMX server and - the back-end servers when XPutImage() is called, the image data is - subdivided and only the data that will be visible on a back-end - server's screen is sent to that back-end server. Xinerama already - implements a subdivision algorithm for XGetImage() and no further - optimization was needed. - - - Other rendering primitives were analyzed, but the time required to - subdivide these primitives was a significant proportion of the time - required to send the entire rendering request to the back-end server, - so this optimization was rejected for the other rendering primitives. - - - Again, the performance tests were run on a DMX system with only two - back-end servers. Greater performance gains will be had as the number - of back-end servers increases. - - - This optimization improved the following x11perf tests by more than - 10%: - - 1.12 Fill 100x100 stippled trapezoid (161x145 stipple) - 1.26 PutImage 10x10 square - 1.83 PutImage 100x100 square - 1.91 PutImage 500x500 square - 1.40 PutImage XY 10x10 square - 1.48 PutImage XY 100x100 square - 1.50 PutImage XY 500x500 square - 1.45 Circulate Unmapped window (75 kids) - 1.74 Circulate Unmapped window (100 kids) - - - - The following test was noted to be more than 10% slower with this - optimization: - - 0.88 10-pixel fill chord partial circle - - - - BB..22..77.. SSuummmmaarryy ooff xx1111ppeerrff DDaattaa - - With all of the optimizations on, 53 x11perf tests are more than 100X - faster than the unoptimized Phase II deliverable, with 69 more than - 50X faster, 73 more than 10X faster, and 199 more than twice as fast. - No tests were more than 10% slower than the unoptimized Phase II - deliverable. (Compared with the Phase I deliverable, only Circulate - Unmapped window (100 kids) was more than 10% slower than the Phase II - deliverable. As noted above, this test seems to have wider - variability than other x11perf tests.) - - - The following table summarizes relative x11perf test changes for all - optimizations individually and collectively. Note that some of the - optimizations have a synergistic effect when used together. - - - - 1: XSync() batching only - 2: Off screen optimizations only - 3: Window optimizations only - 4: Subdivprims only - 5: All optimizations - - 1 2 3 4 5 Operation - ------ ---- ---- ---- ------ --------- - 2.14 1.85 1.00 1.00 4.13 Dot - 1.67 1.80 1.00 1.00 3.31 1x1 rectangle - 2.38 1.43 1.00 1.00 2.44 10x10 rectangle - 1.00 1.00 0.92 0.98 1.00 100x100 rectangle - 1.00 1.00 1.00 1.00 1.00 500x500 rectangle - 1.83 1.85 1.05 1.06 3.54 1x1 stippled rectangle (8x8 stipple) - 2.43 1.43 1.00 1.00 2.41 10x10 stippled rectangle (8x8 stipple) - 0.98 1.00 1.00 1.00 1.00 100x100 stippled rectangle (8x8 stipple) - 1.00 1.00 1.00 1.00 0.98 500x500 stippled rectangle (8x8 stipple) - 1.75 1.75 1.00 1.00 3.40 1x1 opaque stippled rectangle (8x8 stipple) - 2.38 1.42 1.00 1.00 2.34 10x10 opaque stippled rectangle (8x8 stipple) - 1.00 1.00 0.97 0.97 1.00 100x100 opaque stippled rectangle (8x8 stipple) - 1.00 1.00 1.00 1.00 0.99 500x500 opaque stippled rectangle (8x8 stipple) - 1.82 1.82 1.04 1.04 3.56 1x1 tiled rectangle (4x4 tile) - 2.33 1.42 1.00 1.00 2.37 10x10 tiled rectangle (4x4 tile) - 1.00 0.92 1.00 1.00 1.00 100x100 tiled rectangle (4x4 tile) - 1.00 1.00 1.00 1.00 1.00 500x500 tiled rectangle (4x4 tile) - 1.94 1.62 1.00 1.00 3.66 1x1 stippled rectangle (17x15 stipple) - 1.74 1.28 1.00 1.00 1.73 10x10 stippled rectangle (17x15 stipple) - 1.00 1.00 1.00 0.89 0.98 100x100 stippled rectangle (17x15 stipple) - 1.00 1.00 1.00 1.00 0.98 500x500 stippled rectangle (17x15 stipple) - 1.94 1.62 1.00 1.00 3.67 1x1 opaque stippled rectangle (17x15 stipple) - 1.69 1.26 1.00 1.00 1.66 10x10 opaque stippled rectangle (17x15 stipple) - 1.00 0.95 1.00 1.00 1.00 100x100 opaque stippled rectangle (17x15 stipple) - 1.00 1.00 1.00 1.00 0.97 500x500 opaque stippled rectangle (17x15 stipple) - 1.93 1.61 0.99 0.99 3.69 1x1 tiled rectangle (17x15 tile) - 1.73 1.27 1.00 1.00 1.72 10x10 tiled rectangle (17x15 tile) - 1.00 1.00 1.00 1.00 0.98 100x100 tiled rectangle (17x15 tile) - 1.00 1.00 0.97 0.97 1.00 500x500 tiled rectangle (17x15 tile) - 1.95 1.63 1.00 1.00 3.83 1x1 stippled rectangle (161x145 stipple) - 1.80 1.30 1.00 1.00 1.83 10x10 stippled rectangle (161x145 stipple) - 0.97 1.00 1.00 1.00 1.01 100x100 stippled rectangle (161x145 stipple) - 1.00 1.00 1.00 1.00 0.98 500x500 stippled rectangle (161x145 stipple) - 1.95 1.63 1.00 1.00 3.56 1x1 opaque stippled rectangle (161x145 stipple) - 1.65 1.25 1.00 1.00 1.68 10x10 opaque stippled rectangle (161x145 stipple) - 1.00 1.00 1.00 1.00 1.01 100x100 opaque stippled rectangle (161x145... - 1.00 1.00 1.00 1.00 0.97 500x500 opaque stippled rectangle (161x145... - 1.95 1.63 0.98 0.99 3.80 1x1 tiled rectangle (161x145 tile) - 1.67 1.26 1.00 1.00 1.67 10x10 tiled rectangle (161x145 tile) - 1.13 1.14 1.14 1.14 1.14 100x100 tiled rectangle (161x145 tile) - 0.88 1.00 1.00 1.00 0.99 500x500 tiled rectangle (161x145 tile) - 1.93 1.63 1.00 1.00 3.53 1x1 tiled rectangle (216x208 tile) - 1.69 1.26 1.00 1.00 1.66 10x10 tiled rectangle (216x208 tile) - 1.00 1.00 1.00 1.00 1.00 100x100 tiled rectangle (216x208 tile) - 1.00 1.00 1.00 1.00 1.00 500x500 tiled rectangle (216x208 tile) - 1.82 1.70 1.00 1.00 3.38 1-pixel line segment - 2.07 1.56 0.90 1.00 3.31 10-pixel line segment - 1.29 1.10 1.00 1.00 1.27 100-pixel line segment - 1.05 1.06 1.03 1.03 1.09 500-pixel line segment - 1.30 1.13 1.00 1.00 1.29 100-pixel line segment (1 kid) - 1.32 1.15 1.00 1.00 1.32 100-pixel line segment (2 kids) - 1.33 1.16 1.00 1.00 1.33 100-pixel line segment (3 kids) - 1.92 1.64 1.00 1.00 3.73 10-pixel dashed segment - 1.34 1.16 1.00 1.00 1.34 100-pixel dashed segment - 1.24 1.11 0.99 0.97 1.23 100-pixel double-dashed segment - 1.72 1.77 1.00 1.00 3.25 10-pixel horizontal line segment - 1.83 1.66 1.01 1.00 3.54 100-pixel horizontal line segment - 1.86 1.30 1.00 1.00 1.84 500-pixel horizontal line segment - 2.11 1.52 1.00 0.99 3.02 10-pixel vertical line segment - 1.21 1.10 1.00 1.00 1.20 100-pixel vertical line segment - 1.03 1.03 1.00 1.00 1.02 500-pixel vertical line segment - 4.42 1.68 1.00 1.01 4.64 10x1 wide horizontal line segment - 1.83 1.31 1.00 1.00 1.83 100x10 wide horizontal line segment - 1.07 1.00 0.96 1.00 1.07 500x50 wide horizontal line segment - 4.10 1.67 1.00 1.00 4.62 10x1 wide vertical line segment - 1.50 1.24 1.06 1.06 1.48 100x10 wide vertical line segment - 1.06 1.03 1.00 1.00 1.05 500x50 wide vertical line segment - 2.54 1.61 1.00 1.00 3.61 1-pixel line - 2.71 1.48 1.00 1.00 2.67 10-pixel line - 1.19 1.09 1.00 1.00 1.19 100-pixel line - 1.04 1.02 1.00 1.00 1.03 500-pixel line - 2.68 1.51 0.98 1.00 3.17 10-pixel dashed line - 1.23 1.11 0.99 0.99 1.23 100-pixel dashed line - 1.15 1.08 1.00 1.00 1.15 100-pixel double-dashed line - 2.27 1.39 1.00 1.00 2.23 10x1 wide line - 1.20 1.09 1.00 1.00 1.20 100x10 wide line - 1.04 1.02 1.00 1.00 1.04 500x50 wide line - 1.52 1.45 1.00 1.00 1.52 100x10 wide dashed line - 1.54 1.47 1.00 1.00 1.54 100x10 wide double-dashed line - 1.97 1.30 0.96 0.95 1.95 10x10 rectangle outline - 1.44 1.27 1.00 1.00 1.43 100x100 rectangle outline - 3.22 2.16 1.10 1.09 3.61 500x500 rectangle outline - 1.95 1.34 1.00 1.00 1.90 10x10 wide rectangle outline - 1.14 1.14 1.00 1.00 1.13 100x100 wide rectangle outline - 1.00 1.00 1.00 1.00 1.00 500x500 wide rectangle outline - 1.57 1.72 1.00 1.00 3.03 1-pixel circle - 1.96 1.35 1.00 1.00 1.92 10-pixel circle - 1.21 1.07 0.86 0.97 1.20 100-pixel circle - 1.08 1.04 1.00 1.00 1.08 500-pixel circle - 1.39 1.19 1.03 1.03 1.38 100-pixel dashed circle - 1.21 1.11 1.00 1.00 1.23 100-pixel double-dashed circle - 1.59 1.28 1.00 1.00 1.58 10-pixel wide circle - 1.22 1.12 0.99 1.00 1.22 100-pixel wide circle - 1.06 1.04 1.00 1.00 1.05 500-pixel wide circle - 1.87 1.84 1.00 1.00 1.85 100-pixel wide dashed circle - 1.90 1.93 1.01 1.01 1.90 100-pixel wide double-dashed circle - 2.13 1.43 1.00 1.00 2.32 10-pixel partial circle - 1.42 1.18 1.00 1.00 1.42 100-pixel partial circle - 1.92 1.85 1.01 1.01 1.89 10-pixel wide partial circle - 1.73 1.67 1.00 1.00 1.73 100-pixel wide partial circle - 1.36 1.95 1.00 1.00 2.64 1-pixel solid circle - 2.02 1.37 1.00 1.00 2.03 10-pixel solid circle - 1.19 1.09 1.00 1.00 1.19 100-pixel solid circle - 1.02 0.99 1.00 1.00 1.01 500-pixel solid circle - 1.74 1.28 1.00 0.88 1.73 10-pixel fill chord partial circle - 1.31 1.13 1.00 1.00 1.31 100-pixel fill chord partial circle - 1.67 1.31 1.03 1.03 1.72 10-pixel fill slice partial circle - 1.30 1.13 1.00 1.00 1.28 100-pixel fill slice partial circle - 2.45 1.49 1.01 1.00 2.71 10-pixel ellipse - 1.22 1.10 1.00 1.00 1.22 100-pixel ellipse - 1.09 1.04 1.00 1.00 1.09 500-pixel ellipse - 1.90 1.28 1.00 1.00 1.89 100-pixel dashed ellipse - 1.62 1.24 0.96 0.97 1.61 100-pixel double-dashed ellipse - 2.43 1.50 1.00 1.00 2.42 10-pixel wide ellipse - 1.61 1.28 1.03 1.03 1.60 100-pixel wide ellipse - 1.08 1.05 1.00 1.00 1.08 500-pixel wide ellipse - 1.93 1.88 1.00 1.00 1.88 100-pixel wide dashed ellipse - 1.94 1.89 1.01 1.00 1.94 100-pixel wide double-dashed ellipse - 2.31 1.48 1.00 1.00 2.67 10-pixel partial ellipse - 1.38 1.17 1.00 1.00 1.38 100-pixel partial ellipse - 2.00 1.85 0.98 0.97 1.98 10-pixel wide partial ellipse - 1.89 1.86 1.00 1.00 1.89 100-pixel wide partial ellipse - 3.49 1.60 1.00 1.00 3.65 10-pixel filled ellipse - 1.67 1.26 1.00 1.00 1.67 100-pixel filled ellipse - 1.06 1.04 1.00 1.00 1.06 500-pixel filled ellipse - 2.38 1.43 1.01 1.00 2.32 10-pixel fill chord partial ellipse - 2.06 1.30 1.00 1.00 2.05 100-pixel fill chord partial ellipse - 2.27 1.41 1.00 1.00 2.27 10-pixel fill slice partial ellipse - 1.98 1.33 1.00 0.97 1.97 100-pixel fill slice partial ellipse - 57.46 1.99 1.01 1.00 114.92 Fill 1x1 equivalent triangle - 56.94 1.98 1.01 1.00 73.89 Fill 10x10 equivalent triangle - 6.07 1.75 1.00 1.00 6.07 Fill 100x100 equivalent triangle - 51.12 1.98 1.00 1.00 102.81 Fill 1x1 trapezoid - 51.42 1.82 1.01 1.00 94.89 Fill 10x10 trapezoid - 6.47 1.80 1.00 1.00 6.44 Fill 100x100 trapezoid - 1.56 1.28 1.00 0.99 1.56 Fill 300x300 trapezoid - 51.27 1.97 0.96 0.97 102.54 Fill 1x1 stippled trapezoid (8x8 stipple) - 51.73 2.00 1.02 1.02 67.92 Fill 10x10 stippled trapezoid (8x8 stipple) - 5.36 1.72 1.00 1.00 5.36 Fill 100x100 stippled trapezoid (8x8 stipple) - 1.54 1.26 1.00 1.00 1.59 Fill 300x300 stippled trapezoid (8x8 stipple) - 51.41 1.94 1.01 1.00 102.82 Fill 1x1 opaque stippled trapezoid (8x8 stipple) - 50.71 1.95 0.99 1.00 65.44 Fill 10x10 opaque stippled trapezoid (8x8... - 5.33 1.73 1.00 1.00 5.36 Fill 100x100 opaque stippled trapezoid (8x8... - 1.58 1.25 1.00 1.00 1.58 Fill 300x300 opaque stippled trapezoid (8x8... - 51.56 1.96 0.99 0.90 103.68 Fill 1x1 tiled trapezoid (4x4 tile) - 51.59 1.99 1.01 1.01 62.25 Fill 10x10 tiled trapezoid (4x4 tile) - 5.38 1.72 1.00 1.00 5.38 Fill 100x100 tiled trapezoid (4x4 tile) - 1.54 1.25 1.00 0.99 1.58 Fill 300x300 tiled trapezoid (4x4 tile) - 51.70 1.98 1.01 1.01 103.98 Fill 1x1 stippled trapezoid (17x15 stipple) - 44.86 1.97 1.00 1.00 44.86 Fill 10x10 stippled trapezoid (17x15 stipple) - 2.74 1.56 1.00 1.00 2.73 Fill 100x100 stippled trapezoid (17x15 stipple) - 1.29 1.14 1.00 1.00 1.27 Fill 300x300 stippled trapezoid (17x15 stipple) - 51.41 1.96 0.96 0.95 103.39 Fill 1x1 opaque stippled trapezoid (17x15... - 45.14 1.96 1.01 1.00 45.14 Fill 10x10 opaque stippled trapezoid (17x15... - 2.68 1.56 1.00 1.00 2.68 Fill 100x100 opaque stippled trapezoid (17x15... - 1.26 1.10 1.00 1.00 1.28 Fill 300x300 opaque stippled trapezoid (17x15... - 51.13 1.97 1.00 0.99 103.39 Fill 1x1 tiled trapezoid (17x15 tile) - 47.58 1.96 1.00 1.00 47.86 Fill 10x10 tiled trapezoid (17x15 tile) - 2.74 1.56 1.00 1.00 2.74 Fill 100x100 tiled trapezoid (17x15 tile) - 1.29 1.14 1.00 1.00 1.28 Fill 300x300 tiled trapezoid (17x15 tile) - 51.13 1.97 0.99 0.97 103.39 Fill 1x1 stippled trapezoid (161x145 stipple) - 45.14 1.97 1.00 1.00 44.29 Fill 10x10 stippled trapezoid (161x145 stipple) - 3.02 1.77 1.12 1.12 3.38 Fill 100x100 stippled trapezoid (161x145 stipple) - 1.31 1.13 1.00 1.00 1.30 Fill 300x300 stippled trapezoid (161x145 stipple) - 51.27 1.97 1.00 1.00 103.10 Fill 1x1 opaque stippled trapezoid (161x145... - 45.01 1.97 1.00 1.00 45.01 Fill 10x10 opaque stippled trapezoid (161x145... - 2.67 1.56 1.00 1.00 2.69 Fill 100x100 opaque stippled trapezoid (161x145.. - 1.29 1.13 1.00 1.01 1.27 Fill 300x300 opaque stippled trapezoid (161x145.. - 51.41 1.96 1.00 0.99 103.39 Fill 1x1 tiled trapezoid (161x145 tile) - 45.01 1.96 0.98 1.00 45.01 Fill 10x10 tiled trapezoid (161x145 tile) - 2.62 1.36 1.00 1.00 2.69 Fill 100x100 tiled trapezoid (161x145 tile) - 1.27 1.13 1.00 1.00 1.22 Fill 300x300 tiled trapezoid (161x145 tile) - 51.13 1.98 1.00 1.00 103.39 Fill 1x1 tiled trapezoid (216x208 tile) - 45.14 1.97 1.01 0.99 45.14 Fill 10x10 tiled trapezoid (216x208 tile) - 2.62 1.55 1.00 1.00 2.71 Fill 100x100 tiled trapezoid (216x208 tile) - 1.28 1.13 1.00 1.00 1.20 Fill 300x300 tiled trapezoid (216x208 tile) - 50.71 1.95 1.00 1.00 54.70 Fill 10x10 equivalent complex polygon - 5.51 1.71 0.96 0.98 5.47 Fill 100x100 equivalent complex polygons - 8.39 1.97 1.00 1.00 16.75 Fill 10x10 64-gon (Convex) - 8.38 1.83 1.00 1.00 8.43 Fill 100x100 64-gon (Convex) - 8.50 1.96 1.00 1.00 16.64 Fill 10x10 64-gon (Complex) - 8.26 1.83 1.00 1.00 8.35 Fill 100x100 64-gon (Complex) - 14.09 1.87 1.00 1.00 14.05 Char in 80-char line (6x13) - 11.91 1.87 1.00 1.00 11.95 Char in 70-char line (8x13) - 11.16 1.85 1.01 1.00 11.10 Char in 60-char line (9x15) - 10.09 1.78 1.00 1.00 10.09 Char16 in 40-char line (k14) - 6.15 1.75 1.00 1.00 6.31 Char16 in 23-char line (k24) - 11.92 1.90 1.03 1.03 11.88 Char in 80-char line (TR 10) - 8.18 1.78 1.00 0.99 8.17 Char in 30-char line (TR 24) - 42.83 1.44 1.01 1.00 42.11 Char in 20/40/20 line (6x13, TR 10) - 27.45 1.43 1.01 1.01 27.45 Char16 in 7/14/7 line (k14, k24) - 12.13 1.85 1.00 1.00 12.05 Char in 80-char image line (6x13) - 10.00 1.84 1.00 1.00 10.00 Char in 70-char image line (8x13) - 9.18 1.83 1.00 1.00 9.12 Char in 60-char image line (9x15) - 9.66 1.82 0.98 0.95 9.66 Char16 in 40-char image line (k14) - 5.82 1.72 1.00 1.00 5.99 Char16 in 23-char image line (k24) - 8.70 1.80 1.00 1.00 8.65 Char in 80-char image line (TR 10) - 4.67 1.66 1.00 1.00 4.67 Char in 30-char image line (TR 24) - 84.43 1.47 1.00 1.00 124.18 Scroll 10x10 pixels - 3.73 1.50 1.00 0.98 3.73 Scroll 100x100 pixels - 1.00 1.00 1.00 1.00 1.00 Scroll 500x500 pixels - 84.43 1.51 1.00 1.00 134.02 Copy 10x10 from window to window - 3.62 1.51 0.98 0.98 3.62 Copy 100x100 from window to window - 0.89 1.00 1.00 1.00 1.00 Copy 500x500 from window to window - 57.06 1.99 1.00 1.00 88.64 Copy 10x10 from pixmap to window - 2.49 2.00 1.00 1.00 2.48 Copy 100x100 from pixmap to window - 1.00 0.91 1.00 1.00 0.98 Copy 500x500 from pixmap to window - 2.04 1.01 1.00 1.00 2.03 Copy 10x10 from window to pixmap - 1.05 1.00 1.00 1.00 1.05 Copy 100x100 from window to pixmap - 1.00 1.00 0.93 1.00 1.04 Copy 500x500 from window to pixmap - 58.52 1.03 1.03 1.02 57.95 Copy 10x10 from pixmap to pixmap - 2.40 1.00 1.00 1.00 2.45 Copy 100x100 from pixmap to pixmap - 1.00 1.00 1.00 1.00 1.00 Copy 500x500 from pixmap to pixmap - 51.57 1.92 1.00 1.00 85.75 Copy 10x10 1-bit deep plane - 6.37 1.75 1.01 1.01 6.37 Copy 100x100 1-bit deep plane - 1.26 1.11 1.00 1.00 1.24 Copy 500x500 1-bit deep plane - 4.23 1.63 0.98 0.97 4.38 Copy 10x10 n-bit deep plane - 1.04 1.02 1.00 1.00 1.04 Copy 100x100 n-bit deep plane - 1.00 1.00 1.00 1.00 1.00 Copy 500x500 n-bit deep plane - 6.45 1.98 1.00 1.26 12.80 PutImage 10x10 square - 1.10 1.87 1.00 1.83 2.11 PutImage 100x100 square - 1.02 1.93 1.00 1.91 1.91 PutImage 500x500 square - 4.17 1.78 1.00 1.40 7.18 PutImage XY 10x10 square - 1.27 1.49 0.97 1.48 2.10 PutImage XY 100x100 square - 1.00 1.50 1.00 1.50 1.52 PutImage XY 500x500 square - 1.07 1.01 1.00 1.00 1.06 GetImage 10x10 square - 1.01 1.00 1.00 1.00 1.01 GetImage 100x100 square - 1.00 1.00 1.00 1.00 1.00 GetImage 500x500 square - 1.56 1.00 0.99 0.97 1.56 GetImage XY 10x10 square - 1.02 1.00 1.00 1.00 1.02 GetImage XY 100x100 square - 1.00 1.00 1.00 1.00 1.00 GetImage XY 500x500 square - 1.00 1.00 1.01 0.98 0.95 X protocol NoOperation - 1.02 1.03 1.04 1.03 1.00 QueryPointer - 1.03 1.02 1.04 1.03 1.00 GetProperty - 100.41 1.51 1.00 1.00 198.76 Change graphics context - 45.81 1.00 0.99 0.97 57.10 Create and map subwindows (4 kids) - 78.45 1.01 1.02 1.02 63.07 Create and map subwindows (16 kids) - 73.91 1.01 1.00 1.00 56.37 Create and map subwindows (25 kids) - 73.22 1.00 1.00 1.00 49.07 Create and map subwindows (50 kids) - 72.36 1.01 0.99 1.00 32.14 Create and map subwindows (75 kids) - 70.34 1.00 1.00 1.00 30.12 Create and map subwindows (100 kids) - 55.00 1.00 1.00 0.99 23.75 Create and map subwindows (200 kids) - 55.30 1.01 1.00 1.00 141.03 Create unmapped window (4 kids) - 55.38 1.01 1.01 1.00 163.25 Create unmapped window (16 kids) - 54.75 0.96 1.00 0.99 166.95 Create unmapped window (25 kids) - 54.83 1.00 1.00 0.99 178.81 Create unmapped window (50 kids) - 55.38 1.01 1.01 1.00 181.20 Create unmapped window (75 kids) - 55.38 1.01 1.01 1.00 181.20 Create unmapped window (100 kids) - 54.87 1.01 1.01 1.00 182.05 Create unmapped window (200 kids) - 28.13 1.00 1.00 1.00 30.75 Map window via parent (4 kids) - 36.14 1.01 1.01 1.01 32.58 Map window via parent (16 kids) - 26.13 1.00 0.98 0.95 29.85 Map window via parent (25 kids) - 40.07 1.00 1.01 1.00 27.57 Map window via parent (50 kids) - 23.26 0.99 1.00 1.00 18.23 Map window via parent (75 kids) - 22.91 0.99 1.00 0.99 16.52 Map window via parent (100 kids) - 27.79 1.00 1.00 0.99 12.50 Map window via parent (200 kids) - 22.35 1.00 1.00 1.00 56.19 Unmap window via parent (4 kids) - 9.57 1.00 0.99 1.00 89.78 Unmap window via parent (16 kids) - 80.77 1.01 1.00 1.00 103.85 Unmap window via parent (25 kids) - 96.34 1.00 1.00 1.00 116.06 Unmap window via parent (50 kids) - 99.72 1.00 1.00 1.00 124.93 Unmap window via parent (75 kids) - 112.36 1.00 1.00 1.00 125.27 Unmap window via parent (100 kids) - 105.41 1.00 1.00 0.99 120.00 Unmap window via parent (200 kids) - 51.29 1.03 1.02 1.02 74.19 Destroy window via parent (4 kids) - 86.75 0.99 0.99 0.99 116.87 Destroy window via parent (16 kids) - 106.43 1.01 1.01 1.01 127.49 Destroy window via parent (25 kids) - 120.34 1.01 1.01 1.00 140.11 Destroy window via parent (50 kids) - 126.67 1.00 0.99 0.99 145.00 Destroy window via parent (75 kids) - 126.11 1.01 1.01 1.00 140.56 Destroy window via parent (100 kids) - 128.57 1.01 1.00 1.00 137.91 Destroy window via parent (200 kids) - 16.04 0.88 1.00 1.00 20.36 Hide/expose window via popup (4 kids) - 19.04 1.01 1.00 1.00 23.48 Hide/expose window via popup (16 kids) - 19.22 1.00 1.00 1.00 20.44 Hide/expose window via popup (25 kids) - 17.41 1.00 0.91 0.97 17.68 Hide/expose window via popup (50 kids) - 17.29 1.01 1.00 1.01 17.07 Hide/expose window via popup (75 kids) - 16.74 1.00 1.00 1.00 16.17 Hide/expose window via popup (100 kids) - 10.30 1.00 1.00 1.00 10.51 Hide/expose window via popup (200 kids) - 16.48 1.01 1.00 1.00 26.05 Move window (4 kids) - 17.01 0.95 1.00 1.00 23.97 Move window (16 kids) - 16.95 1.00 1.00 1.00 22.90 Move window (25 kids) - 16.05 1.01 1.00 1.00 21.32 Move window (50 kids) - 15.58 1.00 0.98 0.98 19.44 Move window (75 kids) - 14.98 1.02 1.03 1.03 18.17 Move window (100 kids) - 10.90 1.01 1.01 1.00 12.68 Move window (200 kids) - 49.42 1.00 1.00 1.00 198.27 Moved unmapped window (4 kids) - 50.72 0.97 1.00 1.00 193.66 Moved unmapped window (16 kids) - 50.87 1.00 0.99 1.00 195.09 Moved unmapped window (25 kids) - 50.72 1.00 1.00 1.00 189.34 Moved unmapped window (50 kids) - 50.87 1.00 1.00 1.00 191.33 Moved unmapped window (75 kids) - 50.87 1.00 1.00 0.90 186.71 Moved unmapped window (100 kids) - 50.87 1.00 1.00 1.00 179.19 Moved unmapped window (200 kids) - 41.04 1.00 1.00 1.00 56.61 Move window via parent (4 kids) - 69.81 1.00 1.00 1.00 130.82 Move window via parent (16 kids) - 95.81 1.00 1.00 1.00 141.92 Move window via parent (25 kids) - 95.98 1.00 1.00 1.00 149.43 Move window via parent (50 kids) - 96.59 1.01 1.01 1.00 153.98 Move window via parent (75 kids) - 97.19 1.00 1.00 1.00 157.30 Move window via parent (100 kids) - 96.67 1.00 0.99 0.96 159.44 Move window via parent (200 kids) - 17.75 1.01 1.00 1.00 27.61 Resize window (4 kids) - 17.94 1.00 1.00 0.99 25.42 Resize window (16 kids) - 17.92 1.01 1.00 1.00 24.47 Resize window (25 kids) - 17.24 0.97 1.00 1.00 24.14 Resize window (50 kids) - 16.81 1.00 1.00 0.99 22.75 Resize window (75 kids) - 16.08 1.00 1.00 1.00 21.20 Resize window (100 kids) - 12.92 1.00 0.99 1.00 16.26 Resize window (200 kids) - 52.94 1.01 1.00 1.00 327.12 Resize unmapped window (4 kids) - 53.60 1.01 1.01 1.01 333.71 Resize unmapped window (16 kids) - 52.99 1.00 1.00 1.00 337.29 Resize unmapped window (25 kids) - 51.98 1.00 1.00 1.00 329.38 Resize unmapped window (50 kids) - 53.05 0.89 1.00 1.00 322.60 Resize unmapped window (75 kids) - 53.05 1.00 1.00 1.00 318.08 Resize unmapped window (100 kids) - 53.11 1.00 1.00 0.99 306.21 Resize unmapped window (200 kids) - 16.76 1.00 0.96 1.00 19.46 Circulate window (4 kids) - 17.24 1.00 1.00 0.97 16.24 Circulate window (16 kids) - 16.30 1.03 1.03 1.03 15.85 Circulate window (25 kids) - 13.45 1.00 1.00 1.00 14.90 Circulate window (50 kids) - 12.91 1.00 1.00 1.00 13.06 Circulate window (75 kids) - 11.30 0.98 1.00 1.00 11.03 Circulate window (100 kids) - 7.58 1.01 1.01 0.99 7.47 Circulate window (200 kids) - 1.01 1.01 0.98 1.00 0.95 Circulate Unmapped window (4 kids) - 1.07 1.07 1.01 1.07 1.02 Circulate Unmapped window (16 kids) - 1.04 1.09 1.06 1.05 0.97 Circulate Unmapped window (25 kids) - 1.04 1.23 1.20 1.18 1.05 Circulate Unmapped window (50 kids) - 1.18 1.53 1.19 1.45 1.24 Circulate Unmapped window (75 kids) - 1.08 1.02 1.01 1.74 1.01 Circulate Unmapped window (100 kids) - 1.01 1.12 0.98 0.91 0.97 Circulate Unmapped window (200 kids) - - - - BB..22..88.. PPrrooffiilliinngg wwiitthh OOPPrrooffiillee - - OProfile (available from http://oprofile.sourceforge.net/) is a - system-wide profiler for Linux systems that uses processor-level - counters to collect sampling data. OProfile can provide information - that is similar to that provided by gprof, but without the necessity - of recompiling the program with special instrumentation (i.e., - OProfile can collect statistical profiling information about optimized - programs). A test harness was developed to collect OProfile data for - each x11perf test individually. - - - Test runs were performed using the RETIRED_INSNS counter on the AMD - Athlon and the CPU_CLK_HALTED counter on the Intel Pentium III (with a - test configuration different from the one described above). We have - examined OProfile output and have compared it with gprof output. This - investigation has not produced results that yield performance - increases in x11perf numbers. - - - - BB..22..99.. XX TTeesstt SSuuiittee - - The X Test Suite was run on the fully optimized DMX server using the - configuration described above. The following failures were noted: - - XListPixmapFormats: Test 1 [1] - XChangeWindowAttributes: Test 32 [1] - XCreateWindow: Test 30 [1] - XFreeColors: Test 4 [3] - XCopyArea: Test 13, 17, 21, 25, 30 [2] - XCopyPlane: Test 11, 15, 27, 31 [2] - XSetFontPath: Test 4 [1] - XChangeKeyboardControl: Test 9, 10 [1] - - [1] Previously documented errors expected from the Xinerama - implementation (see Phase I discussion). - [2] Newly noted errors that have been verified as expected - behavior of the Xinerama implementation. - [3] Newly noted error that has been verified as a Xinerama - implementation bug. - - - - BB..33.. PPhhaassee IIIIII - - During the third phase of development, support was provided for the - following extensions: SHAPE, RENDER, XKEYBOARD, XInput. - - - BB..33..11.. SSHHAAPPEE - - The SHAPE extension is supported. Test applications (e.g., xeyes and - oclock) and window managers that make use of the SHAPE extension will - work as expected. - - - BB..33..22.. RREENNDDEERR - - The RENDER extension is supported. The version included in the DMX - CVS tree is version 0.2, and this version is fully supported by Xdmx. - Applications using only version 0.2 functions will work correctly; - however, some apps that make use of functions from later versions do - not properly check the extension's major/minor version numbers. These - apps will fail with a Bad Implementation error when using post-version - 0.2 functions. This is expected behavior. When the DMX CVS tree is - updated to include newer versions of RENDER, support for these newer - functions will be added to the DMX X server. - - - BB..33..33.. XXKKEEYYBBOOAARRDD - - The XKEYBOARD extension is supported. If present on the back-end X - servers, the XKEYBOARD extension will be used to obtain information - about the type of the keyboard for initialization. Otherwise, the - keyboard will be initialized using defaults. Note that this departs - from older behavior: when Xdmx is compiled without XKEYBOARD support, - the map from the back-end X server will be preserved. With XKEYBOARD - support, the map is not preserved because better information and - control of the keyboard is available. - - - BB..33..44.. XXIInnppuutt - - The XInput extension is supported. Any device can be used as a core - device and be used as an XInput extension device, with the exception - of core devices on the back-end servers. This limitation is present - because cursor handling on the back-end requires that the back-end - cursor sometimes track the Xdmx core cursor -- behavior that is - incompatible with using the back-end pointer as a non-core device. - - - Currently, back-end extension devices are not available as Xdmx - extension devices, but this limitation should be removed in the - future. - - - To demonstrate the XInput extension, and to provide more examples for - low-level input device driver writers, USB device drivers have been - written for mice (usb-mou), keyboards (usb-kbd), and non-mouse/non- - keyboard USB devices (usb-oth). Please see the man page for - information on Linux kernel drivers that are required for using these - Xdmx drivers. - - - BB..33..55.. DDPPMMSS - - The DPMS extension is exported but does not do anything at this time. - - - BB..33..66.. OOtthheerr EExxtteennssiioonnss - - The LBX, SECURITY, XC-APPGROUP, and XFree86-Bigfont extensions do not - require any special Xdmx support and have been exported. - - - The BIG-REQUESTS, DEC-XTRAP, DOUBLE-BUFFER, Extended-Visual- - Information, FontCache, GLX, MIT-SCREEN-SAVER, MIT-SHM, MIT-SUNDRY- - NONSTANDARD, RECORD, SECURITY, SGI-GLX, SYNC, TOG-CUP, X-Resource, XC- - MISC, XFree86-DGA, XFree86-DRI, XFree86-Misc, - XFree86-VidModeExtension, and XVideo extensions are _n_o_t supported at - this time, but will be evaluated for inclusion in future DMX releases. - SSeeee bbeellooww ffoorr aaddddiittiioonnaall wwoorrkk oonn eexxtteennssiioonnss aafftteerr PPhhaassee IIIIII.. - - - BB..44.. PPhhaassee IIVV - - BB..44..11.. MMoovviinngg ttoo XXFFrreeee8866 44..33..00 - - For Phase IV, the recent release of XFree86 4.3.0 (27 February 2003) - was merged onto the dmx.sourceforge.net CVS trunk and all work is - proceeding using this tree. - - - BB..44..22.. EExxtteennssiioonnss - - BB..44..22..11.. XXCC--MMIISSCC ((ssuuppppoorrtteedd)) - - XC-MISC is used internally by the X library to recycle XIDs from the X - server. This is important for long-running X server sessions. Xdmx - supports this extension. The X Test Suite passed and failed the exact - same tests before and after this extension was enabled. - - - BB..44..22..22.. EExxtteennddeedd--VViissuuaall--IInnffoorrmmaattiioonn ((ssuuppppoorrtteedd)) - - The Extended-Visual-Information extension provides a method for an X - client to obtain detailed visual information. Xdmx supports this - extension. It was tested using the hw/dmx/examples/evi example - program. NNoottee tthhaatt tthhiiss eexxtteennssiioonn iiss nnoott XXiinneerraammaa--aawwaarree -- it will - return visual information for each screen even though Xinerama is - causing the X server to export a single logical screen. - - - BB..44..22..33.. RREESS ((ssuuppppoorrtteedd)) - - The X-Resource extension provides a mechanism for a client to obtain - detailed information about the resources used by other clients. This - extension was tested with the hw/dmx/examples/res program. The X Test - Suite passed and failed the exact same tests before and after this - extension was enabled. - - - BB..44..22..44.. BBIIGG--RREEQQUUEESSTTSS ((ssuuppppoorrtteedd)) - - This extension enables the X11 protocol to handle requests longer than - 262140 bytes. The X Test Suite passed and failed the exact same tests - before and after this extension was enabled. - - - BB..44..22..55.. XXSSYYNNCC ((ssuuppppoorrtteedd)) - - This extension provides facilities for two different X clients to - synchronize their requests. This extension was minimally tested with - xdpyinfo and the X Test Suite passed and failed the exact same tests - before and after this extension was enabled. - - - BB..44..22..66.. XXTTEESSTT,, RREECCOORRDD,, DDEECC--XXTTRRAAPP ((ssuuppppoorrtteedd)) aanndd XXTTeessttEExxtteennssiioonn11 - ((nnoott ssuuppppoorrtteedd)) - - The XTEST and RECORD extension were developed by the X Consortium for - use in the X Test Suite and are supported as a standard in the X11R6 - tree. They are also supported in Xdmx. When X Test Suite tests that - make use of the XTEST extension are run, Xdmx passes and fails exactly - the same tests as does a standard XFree86 X server. When the rcrdtest - test (a part of the X Test Suite that verifies the RECORD extension) - is run, Xdmx passes and fails exactly the same tests as does a - standard XFree86 X server. - - - There are two older XTEST-like extensions: DEC-XTRAP and - XTestExtension1. The XTestExtension1 extension was developed for use - by the X Testing Consortium for use with a test suite that eventually - became (part of?) the X Test Suite. Unlike XTEST, which only allows - events to be sent to the server, the XTestExtension1 extension also - allowed events to be recorded (similar to the RECORD extension). The - second is the DEC-XTRAP extension that was developed by the Digital - Equipment Corporation. - - - The DEC-XTRAP extension is available from Xdmx and has been tested - with the xtrap* tools which are distributed as standard X11R6 clients. - - - The XTestExtension1 is _n_o_t supported because it does not appear to be - used by any modern X clients (the few that support it also support - XTEST) and because there are no good methods available for testing - that it functions correctly (unlike XTEST and DEC-XTRAP, the code for - XTestExtension1 is not part of the standard X server source tree, so - additional testing is important). - - - Most of these extensions are documented in the X11R6 source tree. - Further, several original papers exist that this author was unable to - locate -- for completeness and historical interest, citations are - provide: - - XXRREECCOORRDD - Martha Zimet. Extending X For Recording. 8th Annual X Technical - Conference Boston, MA January 24-26, 1994. - - DDEECC--XXTTRRAAPP - Dick Annicchiarico, Robert Chesler, Alan Jamison. XTrap - Architecture. Digital Equipment Corporation, July 1991. - - XXTTeessttEExxtteennssiioonn11 - Larry Woestman. X11 Input Synthesis Extension Proposal. Hewlett - Packard, November 1991. - - - BB..44..22..77.. MMIITT--MMIISSCC ((nnoott ssuuppppoorrtteedd)) - - The MIT-MISC extension is used to control a bug-compatibility flag - that provides compatibility with xterm programs from X11R1 and X11R2. - There does not appear to be a single client available that makes use - of this extension and there is not way to verify that it works - correctly. The Xdmx server does _n_o_t support MIT-MISC. - - - BB..44..22..88.. SSCCRREEEENNSSAAVVEERR ((nnoott ssuuppppoorrtteedd)) - - This extension provides special support for the X screen saver. It - was tested with beforelight, which appears to be the only client that - works with it. When Xinerama was not active, beforelight behaved as - expected. However, when Xinerama was active, beforelight did not - behave as expected. Further, when this extension is not active, - xscreensaver (a widely-used X screen saver program) did not behave as - expected. Since this extension is not Xinerama-aware and is not - commonly used with expected results by clients, we have left this - extension disabled at this time. - - BB..44..22..99.. GGLLXX ((ssuuppppoorrtteedd)) - - The GLX extension provides OpenGL and GLX windowing support. In Xdmx, - the extension is called glxProxy, and it is Xinerama aware. It works - by either feeding requests forward through Xdmx to each of the back- - end servers or handling them locally. All rendering requests are - handled on the back-end X servers. This code was donated to the DMX - project by SGI. For the X Test Suite results comparison, see below. - - - BB..44..22..1100.. RREENNDDEERR ((ssuuppppoorrtteedd)) - - The X Rendering Extension (RENDER) provides support for digital image - composition. Geometric and text rendering are supported. RENDER is - partially Xinerama-aware, with text and the most basic compositing - operator; however, its higher level primitives (triangles, triangle - strips, and triangle fans) are not yet Xinerama-aware. The RENDER - extension is still under development, and is currently at version 0.8. - Additional support will be required in DMX as more primitives and/or - requests are added to the extension. - - - There is currently no test suite for the X Rendering Extension; - however, there has been discussion of developing a test suite as the - extension matures. When that test suite becomes available, additional - testing can be performed with Xdmx. The X Test Suite passed and - failed the exact same tests before and after this extension was - enabled. - - - BB..44..22..1111.. SSuummmmaarryy - - To summarize, the following extensions are currently supported: BIG- - REQUESTS, DEC-XTRAP, DMX, DPMS, Extended-Visual-Information, GLX, LBX, - RECORD, RENDER, SECURITY, SHAPE, SYNC, X-Resource, XC-APPGROUP, XC- - MISC, XFree86-Bigfont, XINERAMA, XInputExtension, XKEYBOARD, and - XTEST. - - - The following extensions are _n_o_t supported at this time: DOUBLE- - BUFFER, FontCache, MIT-SCREEN-SAVER, MIT-SHM, MIT-SUNDRY-NONSTANDARD, - TOG-CUP, XFree86-DGA, XFree86-Misc, XFree86-VidModeExtension, - XTestExtensionExt1, and XVideo. - - - BB..44..33.. AAddddiittiioonnaall TTeessttiinngg wwiitthh tthhee XX TTeesstt SSuuiittee - - BB..44..33..11.. XXFFrreeee8866 wwiitthhoouutt XXTTEESSTT - - After the release of XFree86 4.3.0, we retested the XFree86 X server - with and without using the XTEST extension. When the XTEST extension - was _n_o_t used for testing, the XFree86 4.3.0 server running on our - usual test system with a Radeon VE card reported unexpected failures - in the following tests: - - XListPixmapFormats: Test 1 - XChangeKeyboardControl: Tests 9, 10 - XGetDefault: Test 5 - XRebindKeysym: Test 1 - - - - BB..44..33..22.. XXFFrreeee8866 wwiitthh XXTTEESSTT - - When using the XTEST extension, the XFree86 4.3.0 server reported the - following errors: - - XListPixmapFormats: Test 1 - XChangeKeyboardControl: Tests 9, 10 - XGetDefault: Test 5 - XRebindKeysym: Test 1 - - XAllowEvents: Tests 20, 21, 24 - XGrabButton: Tests 5, 9-12, 14, 16, 19, 21-25 - XGrabKey: Test 8 - XSetPointerMapping: Test 3 - XUngrabButton: Test 4 - - - - While these errors may be important, they will probably be fixed - eventually in the XFree86 source tree. We are particularly interested - in demonstrating that the Xdmx server does not introduce additional - failures that are not known Xinerama failures. - - - BB..44..33..33.. XXddmmxx wwiitthh XXTTEESSTT,, wwiitthhoouutt XXiinneerraammaa,, wwiitthhoouutt GGLLXX - - Without Xinerama, but using the XTEST extension, the following errors - were reported from Xdmx (note that these are the same as for the - XFree86 4.3.0, except that XGetDefault no longer fails): - - XListPixmapFormats: Test 1 - XChangeKeyboardControl: Tests 9, 10 - XRebindKeysym: Test 1 - - XAllowEvents: Tests 20, 21, 24 - XGrabButton: Tests 5, 9-12, 14, 16, 19, 21-25 - XGrabKey: Test 8 - XSetPointerMapping: Test 3 - XUngrabButton: Test 4 - - - - BB..44..33..44.. XXddmmxx wwiitthh XXTTEESSTT,, wwiitthh XXiinneerraammaa,, wwiitthhoouutt GGLLXX - - With Xinerama, using the XTEST extension, the following errors were - reported from Xdmx: - - XListPixmapFormats: Test 1 - XChangeKeyboardControl: Tests 9, 10 - XRebindKeysym: Test 1 - - XAllowEvents: Tests 20, 21, 24 - XGrabButton: Tests 5, 9-12, 14, 16, 19, 21-25 - XGrabKey: Test 8 - XSetPointerMapping: Test 3 - XUngrabButton: Test 4 - - XCopyPlane: Tests 13, 22, 31 (well-known XTEST/Xinerama interaction issue) - XDrawLine: Test 67 - XDrawLines: Test 91 - XDrawSegments: Test 68 - - - - Note that the first two sets of errors are the same as for the XFree86 - 4.3.0 server, and that the XCopyPlane error is a well-known error - resulting from an XTEST/Xinerama interaction when the request crosses - a screen boundary. The XDraw* errors are resolved when the tests are - run individually and they do not cross a screen boundary. We will - investigate these errors further to determine their cause. - - - BB..44..33..55.. XXddmmxx wwiitthh XXTTEESSTT,, wwiitthh XXiinneerraammaa,, wwiitthh GGLLXX - - With GLX enabled, using the XTEST extension, the following errors were - reported from Xdmx (these results are from early during the Phase IV - development, but were confirmed with a late Phase IV snapshot): - - XListPixmapFormats: Test 1 - XChangeKeyboardControl: Tests 9, 10 - XRebindKeysym: Test 1 - - XAllowEvents: Tests 20, 21, 24 - XGrabButton: Tests 5, 9-12, 14, 16, 19, 21-25 - XGrabKey: Test 8 - XSetPointerMapping: Test 3 - XUngrabButton: Test 4 - - XClearArea: Test 8 - XCopyArea: Tests 4, 5, 11, 14, 17, 23, 25, 27, 30 - XCopyPlane: Tests 6, 7, 10, 19, 22, 31 - XDrawArcs: Tests 89, 100, 102 - XDrawLine: Test 67 - XDrawSegments: Test 68 - - - Note that the first two sets of errors are the same as for the XFree86 - 4.3.0 server, and that the third set has different failures than when - Xdmx does not include GLX support. Since the GLX extension adds new - visuals to support GLX's visual configs and the X Test Suite runs - tests over the entire set of visuals, additional rendering tests were - run and presumably more of them crossed a screen boundary. This con- - clusion is supported by the fact that nearly all of the rendering - errors reported are resolved when the tests are run individually and - they do no cross a screen boundary. - - - Further, when hardware rendering is disabled on the back-end displays, - many of the errors in the third set are eliminated, leaving only: - - XClearArea: Test 8 - XCopyArea: Test 4, 5, 11, 14, 17, 23, 25, 27, 30 - XCopyPlane: Test 6, 7, 10, 19, 22, 31 - - - - BB..44..33..66.. CCoonncclluussiioonn - - We conclude that all of the X Test Suite errors reported for Xdmx are - the result of errors in the back-end X server or the Xinerama - implementation. Further, all of these errors that can be reasonably - fixed at the Xdmx layer have been. (Where appropriate, we have - submitted patches to the XFree86 and Xinerama upstream maintainers.) - - - BB..44..44.. DDyynnaammiicc RReeccoonnffiigguurraattiioonn - - During this development phase, dynamic reconfiguration support was - added to DMX. This support allows an application to change the - position and offset of a back-end server's screen. For example, if - the application would like to shift a screen slightly to the left, it - could query Xdmx for the screen's <x,y> position and then dynamically - reconfigure that screen to be at position <x+10,y>. When a screen is - dynamically reconfigured, input handling and a screen's root window - dimensions are adjusted as needed. These adjustments are transparent - to the user. - - - BB..44..44..11.. DDyynnaammiicc rreeccoonnffiigguurraattiioonn eexxtteennssiioonn - - The application interface to DMX's dynamic reconfiguration is through - a function in the DMX extension library: - - Bool DMXReconfigureScreen(Display *dpy, int screen, int x, int y) - - - where _d_p_y is DMX server's display, _s_c_r_e_e_n is the number of the screen - to be reconfigured, and _x and _y are the new upper, left-hand coordi- - nates of the screen to be reconfigured. - - - The coordinates are not limited other than as required by the X - protocol, which limits all coordinates to a signed 16 bit number. In - addition, all coordinates within a screen must also be legal values. - Therefore, setting a screen's upper, left-hand coordinates such that - the right or bottom edges of the screen is greater than 32,767 is - illegal. - - - BB..44..44..22.. BBoouunnddiinngg bbooxx - - When the Xdmx server is started, a bounding box is calculated from the - screens' layout given either on the command line or in the - configuration file. This bounding box is currently fixed for the - lifetime of the Xdmx server. - - - While it is possible to move a screen outside of the bounding box, it - is currently not possible to change the dimensions of the bounding - box. For example, it is possible to specify coordinates of - <-100,-100> for the upper, left-hand corner of the bounding box, which - was previously at coordinates <0,0>. As expected, the screen is moved - down and to the right; however, since the bounding box is fixed, the - left side and upper portions of the screen exposed by the - reconfiguration are no longer accessible on that screen. Those - inaccessible regions are filled with black. - - - This fixed bounding box limitation will be addressed in a future - development phase. - - - BB..44..44..33.. SSaammppllee aapppplliiccaattiioonnss - - An example of where this extension is useful is in setting up a video - wall. It is not always possible to get everything perfectly aligned, - and sometimes the positions are changed (e.g., someone might bump into - a projector). Instead of physically moving projectors or monitors, it - is now possible to adjust the positions of the back-end server's - screens using the dynamic reconfiguration support in DMX. - - - Other applications, such as automatic setup and calibration tools, can - make use of dynamic reconfiguration to correct for projector alignment - problems, as long as the projectors are still arranged rectilinearly. - Horizontal and vertical keystone correction could be applied to - projectors to correct for non-rectilinear alignment problems; however, - this must be done external to Xdmx. - - - A sample test program is included in the DMX server's examples - directory to demonstrate the interface and how an application might - use dynamic reconfiguration. See dmxreconfig.c for details. - - - BB..44..44..44.. AAddddiittiioonnaall nnootteess - - In the original development plan, Phase IV was primarily devoted to - adding OpenGL support to DMX; however, SGI became interested in the - DMX project and developed code to support OpenGL/GLX. This code was - later donated to the DMX project and integrated into the DMX code - base, which freed the DMX developers to concentrate on dynamic - reconfiguration (as described above). - - - BB..44..55.. DDooxxyyggeenn ddooccuummeennttaattiioonn - - Doxygen is an open-source (GPL) documentation system for generating - browseable documentation from stylized comments in the source code. - We have placed all of the Xdmx server and DMX protocol source code - files under Doxygen so that comprehensive documentation for the Xdmx - source code is available in an easily browseable format. - - - BB..44..66.. VVaallggrriinndd - - Valgrind, an open-source (GPL) memory debugger for Linux, was used to - search for memory management errors. Several memory leaks were - detected and repaired. The following errors were not addressed: - - 1. When the X11 transport layer sends a reply to the client, only - those fields that are required by the protocol are filled in -- - unused fields are left as uninitialized memory and are therefore - noted by valgrind. These instances are not errors and were not - repaired. - - 2. At each server generation, glxInitVisuals allocates memory that is - never freed. The amount of memory lost each generation - approximately equal to 128 bytes for each back-end visual. Because - the code involved is automatically generated, this bug has not been - fixed and will be referred to SGI. - - 3. At each server generation, dmxRealizeFont calls XLoadQueryFont, - which allocates a font structure that is not freed. - dmxUnrealizeFont can free the font structure for the first screen, - but cannot free it for the other screens since they are already - closed by the time dmxUnrealizeFont could free them. The amount of - memory lost each generation is approximately equal to 80 bytes per - font per back-end. When this bug is fixed in the the X server's - device-independent (dix) code, DMX will be able to properly free - the memory allocated by XLoadQueryFont. - - - BB..44..77.. RRAATTSS - - RATS (Rough Auditing Tool for Security) is an open-source (GPL) - security analysis tool that scans source code for common security- - related programming errors (e.g., buffer overflows and TOCTOU races). - RATS was used to audit all of the code in the hw/dmx directory and all - "High" notations were checked manually. The code was either re- - written to eliminate the warning, or a comment containing "RATS" was - inserted on the line to indicate that a human had checked the code. - Unrepaired warnings are as follows: - - 1. Fixed-size buffers are used in many areas, but code has been added - to protect against buffer overflows (e.g., XmuSnprint). The only - instances that have not yet been fixed are in config/xdmxconfig.c - (which is not part of the Xdmx server) and input/usb-common.c. - - 2. vprintf and vfprintf are used in the logging routines. In general, - all uses of these functions (e.g., dmxLog) provide a constant - format string from a trusted source, so the use is relatively - benign. - - 3. glxProxy/glxscreens.c uses getenv and strcat. The use of these - functions is safe and will remain safe as long as ExtensionsString - is longer then GLXServerExtensions (ensuring this may not be ovious - to the casual programmer, but this is in automatically generated - code, so we hope that the generator enforces this constraint). - - - diff --git a/xorg-server/hw/dmx/doc/scaled.txt b/xorg-server/hw/dmx/doc/scaled.txt deleted file mode 100644 index d30105dd2..000000000 --- a/xorg-server/hw/dmx/doc/scaled.txt +++ /dev/null @@ -1,579 +0,0 @@ - Scaled Window Support in DMX - Rickard E. Faith and Kevin E. Martin - 15 October 2003 (created 19 September 2003) - - This document investigates the possibility of adding scaled window - support to the DMX X server, thereby allowing a window or some - selected part of the logical DMX area to be displayed using a scaling - factor. For example, this might allow the contents of a window to be - magnified for easier viewing. In particular, scaling for the VNC - client is explored. _C_o_p_y_r_i_g_h_t _2_0_0_3 _b_y _R_e_d _H_a_t_, _I_n_c_._, _R_a_l_e_i_g_h_, _N_o_r_t_h - _C_a_r_o_l_i_n_a - - ______________________________________________________________________ - - Table of Contents - - - 1. Introduction - 1.1 DMX - 1.2 Problem Statement - 1.3 Task - - 2. Previous Work - 2.1 VNC - 2.1.1 Scaling under VNC - 2.2 The X Video Extension - - 3. Possible Solutions - 3.1 VNC-like Scaling - 3.1.1 Software Scaling - 3.1.2 Scaling with the X Video Extension - 3.1.2.1 Implementing the X Video Extension for DMX - 3.1.2.2 Supporting RGB formats for the X Video Extension - 3.1.3 Scaling with an XPutImageScaled Extension - 3.1.4 Scaling with an XCopyAreaScaled Extension - 3.1.5 Scaling with OpenGL - 3.2 Application-transparent Scaling for DMX - 3.2.1 Back-end Scaling Without Disconnect/Reconnect - 3.2.2 Back-end Scaling With Disconnect/Reconnect - 3.2.3 Server-side Scaling - 3.3 XCreateScaledWindow API - 3.3.1 XCreateWindow - 3.3.2 XSetWindowAttributes - 3.3.3 XGetWindowAttributes, XGetGeometry - 3.3.4 Popup and Child window positions - 3.3.5 Events - 3.3.6 Implementation - - 4. Conclusion and Recommendations - - - ______________________________________________________________________ - - 11.. IInnttrroodduuccttiioonn - - 11..11.. DDMMXX - - The DMX X server (Xdmx) is a proxy server that is designed to allow X - servers on multiple machines to be combined into a single multi-headed - X server. Combined with Xinerama, these heads can appear as a single - very high-resolution screen. Typical applications include the - creation of a video wall with 16 1280x1024 displays arranged in a - rectangle, for a total resolution of of 5120x4096. - - - - 11..22.. PPrroobblleemm SSttaatteemmeenntt - - Applications displayed on a physically large video wall that provides - high pixel-resolution may be difficult to see, especially if the - application is designed for use on a typical desktop computer with a - relatively small display located close to the human operator. The - goal of this paper is to describe and discuss solutions to this - problem. - - The original driving problem for this work is to provide scaling for - the vncviewer application when displayed using DMX (VNC scaling is - currently available only with the Windows client, and there is no plan - to extend that capability to other clients). While this specific - problem will be addressed in this paper, the general solution space - will also be explored, since this may lead to a good solution not only - for vncviewer but also for other applications. - - 11..33.. TTaasskk - - For reference, here is the original description of the task this paper - addresses: - - +o Scaled window support (for VNC) - - +o Investigate possibility of implementing a "scaled window" - extension: - - +o Add XCreateScaledWindow call that could be used in place of - XCreateWindow - - +o All primitives drawn to scaled window would be scaled by - appropriate (integral?) scaling factor - - +o Alternate approach: special case VNC support - - 22.. PPrreevviioouuss WWoorrkk - - This section reviews relevant previous work. - - 22..11.. VVNNCC - - 22..11..11.. SSccaalliinngg uunnddeerr VVNNCC - - When using the vncviewer program for Windows, it is possible to - specify a scaling factor (as numerator and denominator). When scaling - is in effect, the viewer software uses StretchBlt (instead of BitBlt) - to display the pixels for the user. When this call is made, the - viewer already has received all of the pixel information (at full - unscaled resolution). - - The scaling in VNC is primitive. It does not conserve bandwidth, it - does not treat textual information differently (i.e., by using a - suitably scaled font), and it does not provide any anti-aliasing other - than that provided by the underlying (Windows-only) system library. - - 22..22.. TThhee XX VViiddeeoo EExxtteennssiioonn - - The X Video Extension is a widely-available extension to the X11 - protocol that provides support for streaming video. Integral to this - support is the ability to arbitrarily scale the output. In version - 2.2 of the X Video specification, support for scaled still images was - provided, using both shared memory and traditional transport. The API - for this support uses calls that are quite similar to XCreateWindow, - XPutImage, and XShmPutImage. Currently, most of the drivers - implemented in XFree86 only support data in various YUV formats. - However, several modern video adaptors support RGB as well. - Note, though, that the target output for this scaling is an overlay - plane -- so X Video provides functionality that is fundamentally - different from that provided by the Windows StrechBlt call. - - 33.. PPoossssiibbllee SSoolluuttiioonnss - - This section briefly discusses possible solutions, including major - advantages and disadvantages from both the implementation and the end- - user programmer standpoint. - - 33..11.. VVNNCC--lliikkee SSccaalliinngg - - 33..11..11.. SSooffttwwaarree SSccaalliinngg - - The vncviewer application could be modified to provide software - scaling. This is not a general solution, but it does solve one of the - goals of this work. - - A prototype of this solution was implemented and a patch against - vnc-3.3.7-unixsrc is available in the dmx/external directory. Because - of limited time available for this work, all of the edge cases were - not considered and the solution works well mainly for integer scaling. - - Currently, vncviewer writes to the X display with XPutImage, - XCopyArea, and XFillRectangle. All instances of these calls have to - be aware of scaling and must round correctly. In the prototype - solution, rounding is incorrect and can cause artifacts. - - A better solution would be to cache all updates to the desktop image - in vncviewer and only send the damaged area to the X display with - XPutImage. This would allow the damaged area to be computed so that - rounding errors do not create artifacts. This method is probably - similar to what is used in the Window client. (The whole VNC suite is - being re-written in C++ and the forthcoming version 4 has not been - evaluated.) - - 33..11..22.. SSccaalliinngg wwiitthh tthhee XX VViiddeeoo EExxtteennssiioonn - - The scaling in the Windows vncviewer application makes use of a scaled - blit that is supplied by the underlying system library. Several video - cards currently provide support for a scaled blit, and some X servers - (including XFree86) expose this capability to applications via the - XvPutImage interface of the X Video Extension. The capability exposed - by XvPutImage results in the scaled image being drawn to an overlay - plane. Most video cards also provide support for a scaled blit into - the normal output planes, but this is not exposed via XvPutImage. - - The vncviewer program could be modified to use the X Video Extension - to provide scaling under X11 that is similar to the scaling currently - provided under Windows. Unfortunately, Xdmx does not currently export - the X Video Extension, so this would not provide an immediate solution - usable with DMX. - - A very early-stage proof-of-concept prototype was implemented and a - preliminary patch against vnc-3.3.7-unixsrc is available in the - dmx/external directory. This prototype was implemented to better - understand the problems that must be solved to make this solution - viable: - - +o As noted under the software scaling section above, vncviewer writes - to the X display with several different calls. These calls write - to the normal output planes and are compatible with XvPutImage, - which writes to an overlay plane. To eliminate artifacts caused by - this problem, vncviewer should be modified so that a cached copy of - the desktop is available, either as a client-side image or a - server-side off-screen pixmap, so that XvPutImage would be the only - method for writing to the X display. - - +o - - Although several modern graphics adaptors support hardware scaling - using an RGB format (e.g., ATI Radeon, nVidia, etc.), XFree86 - drivers typically only implement YUV formats. YUV generally - compress the pixel information in some way. For example, two - commonly implemented formats, YUY2 and UYVY provide intensity - information for every RGB pixel, but only provide chroma and - luminance information for pairs of horizontal pixels. Since VNC - uses pixel-resolution for communicating updates on the wire, - additional artifacts are introduced (because there may not be - enough information from the wire to update a pair of pixels). - - Further, the well-known problem with YUV encoding is even more - evident when the image is a desktop instead of a movie. For - example, consider a 1-pixel-wide vertical window border. If the - border changes in color but not intensity (e.g., because a window - manager uses color to indicate focus), there may or may not be a - change in the YUY2 image, depending on the algorithm used for RGB - to YUV conversion and on how the border pixel is ordered in the - pair of pixels used by the algorithm. - - Many of these artifacts could be eliminated if vncviewer cached a - complete RGB image of the desktop, and only did the conversion to - YUV for properly aligned areas of damage. The remaining artifacts - could be eliminated if an RGB format was used with X Video (which - may require the extension of existing XFree86 drivers to support - RGB). - - +o Most modern video cards support exactly one overlay plane that is - suitable for use with X Video. Therefore, only one application can - use X Video at any given time. This is a severe limitation in a - desktop environment. - - 33..11..22..11.. IImmpplleemmeennttiinngg tthhee XX VViiddeeoo EExxtteennssiioonn ffoorr DDMMXX - - The user-level API for X Video is fairly simple, but the underlying - support required for the full specification is large. However, since - the API provides a method to query supported capabilities, a usable - subset of X Video can be implemented that would support XvPutImage and - little else. This would require support for the following: - - +o X Video Extension API calls, including the following: - - +o XvQueryExtension - - +o XvQueryAdaptors - - +o XvQueryPortAttributes - - +o XvFreeAdaptorInfo - - +o XvListImageFormats - - +o XvGrabPort - - +o XvCreateImage - - +o XvPutImage - - +o XvShmCreateImage - - +o XvShmPutImage - - +o Support for querying back-end X Video Extension capabilities. - - +o Support for sending the image to the back-ends. Because X Video - requires sending full images, there may be a trade-off between - bandwidth limitations and additional complexity to divide the image - up such that is scales properly. - - +o Possible support for a software fall-back. For example, if all of - the back-ends do not support the X Video Extension, software - scaling can be implemented such that the image is sent to the back- - end with XPutImage. This pathway would have poor performance. - - 33..11..22..22.. SSuuppppoorrttiinngg RRGGBB ffoorrmmaattss ffoorr tthhee XX VViiddeeoo EExxtteennssiioonn - - Assuming an XFree86 driver already supports the X Video Extension, and - assuming the target hardware supports an RGB format, then adding - support for that format is relatively simple and straightforward. - - 33..11..33.. SSccaalliinngg wwiitthh aann XXPPuuttIImmaaggeeSSccaalleedd EExxtteennssiioonn - - Instead of (or in addition to) implementing the X Video Extension in - DMX, one obvious solution would be to implement a new extension that - provides access to hardware-assisted scaled blits, similar to the - StretchBlt call available under Windows. This call would scale RGB - images and would not use the overlay plane (unlike the X Video - Extension). - - This approach has many of the same advantages and disadvantages as the - XCopyAreaScaled Extension, discussed in the next section. Discussion - of XPutImageScaled is deferred in favor of XCopyAreaScaled for the - following reasons: - - +o XPutImageScaled can be emulated with XCopyAreaScaled by first using - XPutImage to copy the image to an off-screen pixmap, and then - calling XCopyAreaScaled between that off-screen pixmap and the - target drawable. - - +o Since XCopyAreaScaled would copy between two areas of on-screen or - off-screen memory, it has additional uses and can be viewed as - efficiently providing a superset of XPutImageScaled functionality. - - 33..11..44.. SSccaalliinngg wwiitthh aann XXCCooppyyAArreeaaSSccaalleedd EExxtteennssiioonn - - As noted in the previous section, because XCopyAreaScaled provides a - superset of the functionality provided by XPutImageScaled, we will - consider this extension instead. - - First, XCopyAreaScaled would provide for RGB scaling between pixmaps - (i.e., on-screen or off-screen areas of memory that reside on the - video card). Unlike the X Video Extension, which writes into an - overlay plane, XCopyAreaScaled would write into the non-overlay areas - of the screen. Key points to consider are as follows: - - +o Because different planes are involved, the two scaling operations - are usually implemented in hardware differently, so an - XCopyAreaScaled extension could be added in a manner that would - neither conflict with nor interact with the X Video extension in - any way. - - +o The XCopyAreaScaled extension provides new functionality that the X - Video Extension does not provide. Based on anecdotal feedback, we - believe that many people outside the DMX and VNC communities would - be excited about this extension. - - +o The main drawback to this extension is that it is new and needs to - be implemented at the driver level in XFree86 for each video card - to be supported. At the present time, it is more likely that the X - Video Extension will be implemented for a particular piece hardware - because the X Video extension has multimedia uses. However, over - time, we would expect the XCopyAreaScaled extension to be - implemented along with the X Video extension, especially if it - becomes popular. - - +o Another drawback is that not all modern cards provide support for a - simple scaled blit operation. However, these cards usually do - provide a 3D pipeline which could be used to provide this - functionality in a manner that is transparent to the client - application that is using the XCopyAreaScaled extension. However, - this implementation pathway would make this extension somewhat more - difficult to implement on certain cards. - - 33..11..55.. SSccaalliinngg wwiitthh OOppeennGGLL - - Another general solution to the scaling problem is to use the texture - scaling found in all 3D hardware. This ability is already exposed - through OpenGL and can be exploited by clients without X server - modification (i.e., other than the ability to support OpenGL). An - application using OpenGL would transmit the non-scaled image to the X - server as a texture, and would then display a single non-transformed - rect using that texture. This also works around the single overlay - problem with the X Video Extension as well as the need to implement - additional scaled primitive extensions. - - The downside is that most OpenGL implementations require power of 2 - texture sizes and this can be very wasteful of memory if, for example, - the application needs to scale a 1025x1025 image, which would require - a 2048x2048 texture area (even a 640x480 image would require a - 1024x512 texture). Another downside is that some OpenGL - implementations have a limited about of texture memory and cannot - handle textures that are very large. For example, they might limit - the texture size to 1024x1024. - - 33..22.. AApppplliiccaattiioonn--ttrraannssppaarreenntt SSccaalliinngg ffoorr DDMMXX - - 33..22..11.. BBaacckk--eenndd SSccaalliinngg WWiitthhoouutt DDiissccoonnnneecctt//RReeccoonnnneecctt - - VNC does scaling on the client side (in the vncviewer application). - Implementing a similar solution for DMX would require support in the - back-end X servers and, therefore, is not a general solution. - - XFree86 already implements some support for "scaling" that could be - used with DMX: if, in the XF86Config file, multiple Modes are listed - in the Display Subsection of the Screen Section, then pressing Ctrl- - Alt-Plus and Ctrl-Alt-Minus can be used to iterate through the listed - modes. The display dimensions will change to the dimensions in the - Modes line, but the logical dimensions of the X server (i.e., the - dimensions that Xdmx knows about) will not change. - - Further, the dimensions of the XFree86 display are under software - control (via the XFree86-VidModeExtension), so the Xdmx server could - change the screen dimensions on a per-display basis, thereby scaling - the information on part of that display. - - However, this scaling appears to have limited use. For example, - assume a 4 by 4 display wall consisting of 16 1280x1024 displays. If - all of the back-end servers were simultaneously configured to display - 640x480, the left hand corner of each display would be magnified, but - the composite result would be unreadable. Magnifying one display at a - time could be usable, but could have limited utility, since the result - would still be no larger than a single display. - - - 33..22..22.. BBaacckk--eenndd SSccaalliinngg WWiitthh DDiissccoonnnneecctt//RReeccoonnnneecctt - - Disconnect and reconnect features are not currently supported in DMX, - but are scheduled to be implemented in the future. These features, - combined with the XFree86-VidModeExtension Extension, would allow an - application to do the following: - - +o Disconnect a specific back-end server (via the DMX Extension), - - +o reconfigure the XFree86 back-end server resolution, and - - +o reconnect the back-end server to DMX -- at a new origin with the - new screen resolution. - - For example, consider a display wall consisting of 16 1280x1024 - displays with a total resolution of 5120x4096. All of the screens - could be disconnected, repositioned, and reconnected each at a - resolution of 640x480. The total resolution of the display wall would - be 2560x1920, allowing a view of a selected area approximately one- - fourth of the size of the DMX display. This change would be - completely application independent (except, perhaps, for a DMX-aware - window manager). When work at the increased resolution was completed, - the back-end servers could be disconnected, reconfigured, and - reconnected for the original 5120x4096 view. - - Support for this type of scaling can be implemented in a DMX-aware X11 - client assuming the DMX server support arbitrary disconnect and - reconnect semantics. Because this application cannot be written - before disconnect/reconnect is implemented, this solution will not be - discussed further in this paper. - - 33..22..33.. SSeerrvveerr--ssiiddee SSccaalliinngg - - In earlier versions of DMX, a frame buffer was maintained on the - server side, and XPutImage was used to move the information from the - server to the client (similar to some early VNC implementations). The - use of a server-side frame buffer would allow the server to do - scaling, but is not a recommended solution because of overall - performance issues and server-side memory issues (i.e., the frame - buffer would be very large for large display walls). - - Exploration of this path is not recommended. - - 33..33.. XXCCrreeaatteeSSccaalleeddWWiinnddooww AAPPII - - The implementation of X Video Extension in DMX, and the use of - XvPutImage by applications requiring scaling requires significant - changes in DMX Further, XvPutImage is, essentially a scaled blit, and - it is only useful for applications which are already using (or can be - modified to use) XPutImage. Therefore, a more general API will be - discussed as another possibility. - - X applications typically create windows with the XCreateWindow call. - A new extension could provide an XCreateScaledWindow call that could - be used in place of the XCreateWindow call and be otherwise - transparent to the application. This would allow applications, even - those that do not depend on XPutImage, to take advantage of window - scaling. In this section we describe how the call would work, what - transparency it provides, and how to solve the potential problems that - transparency creates. - - 33..33..11.. XXCCrreeaatteeWWiinnddooww - - The XCreateWindow call takes width and height as parameters. An - XCreateScaledWindow call could take all the same parameters, with the - addition of a scaling factor. - 33..33..22.. XXSSeettWWiinnddoowwAAttttrriibbuutteess - - An X11 window has several attributes that would have to be scaled: - - +o Background and border pixmaps - - +o Border width - - +o Cursor - - 33..33..33.. XXGGeettWWiinnddoowwAAttttrriibbuutteess,, XXGGeettGGeeoommeettrryy - - For transparency, calls that query the window attributes should return - unscaled information. This suggests that all unscaled pixmaps and - window attributes should be cached. - - Unfortunately, a window manager requires the scaled geometry to - properly decorate the window. The X server can probably determine - which client is acting as the window manager (e.g., because that - client will select events that are used exclusively by the window - manager). However, other Scaled Window Extension aware clients may - also need to determine the scaled geometry. Therefore, at least two - additional extension calls should be implemented: - XGetScaledWindowAttributes and XGetScaledGeometry. - - 33..33..44.. PPooppuupp aanndd CChhiilldd wwiinnddooww ppoossiittiioonnss - - Some applications may position popup and child windows based on an - unscaled notion of the main window geometry. In this case, additional - modifications to the client would be required. - - 33..33..55.. EEvveennttss - - Most events (e.g., for mouse motion) return information about the - coordinates at which the even occurred. These coordinates would have - to be modified so that unscaled values were presented to the client. - - 33..33..66.. IImmpplleemmeennttaattiioonn - - There are many implementation issues, some of which are similar to the - issues involved in implementing the X Video Extension for DMX. The - window contents must be scaled, either by performing all operations to - a frame buffer and then writing the image to the display (perhaps - using hardware scaling support), or by modifying all of the various - drawing operations to perform scaling. Because of the complexity - involved, the frame buffer option is recommended. - - 44.. CCoonncclluussiioonn aanndd RReeccoommmmeennddaattiioonnss - - We recommend a three phase implementation strategy, based on how an - application could be written to take advantage of scaling: - - 1. - - The XCopyAreaScaled extension should be implemented, since this is - the ideal solution for applications like VNC, and since making use - of this extension will require minimal changes to applications that - already use XPutImage or XCopyArea. - - The initial implementation work would include the design of the X - protocol extension, writing this up in the usual format for - extension documentation, implementation of the protocol transport - pieces in XFree86, implementation of a software fall-back in - XFree86 and DMX, one example hardware implementation for XFree86, - and implementation of support for this extension in DMX. - - We suggest implementing the extension first on the ATI Radeon - cards. However, since these cards do not provide a 2D scaled blit - primitive, the implementation would have to make use of the 3D - texture engine to emulate a scaled blit. This is recommended, - since other modern graphics cards also do not provide a simple 2D - scaled blit operation and an example of the more difficult - implementation pathway would be helpful to others. - - 2. - - Until XCopyAreaScaled is widely supported, applications that - require scaling will have to fall back to another scaling method. - We suggest OpenGL as the first fall-back method because it is - widely available and supported by DMX. - - A project centered around OpenGL-based scaling would implement this - scaling in VNC as an example. This work would include re-writing - the vncviewer rendering engine to cache a master copy of the - desktop image for all operations. - - 3. - - Since OpenGL is not implemented everywhere, and may not provide - hardware-assisted performance in every implementation, an - application that requires scaling should also fall back to using - the X Video Extension. - - This project would add support for the X Video Extension to DMX and - would add support to VNC to take advantage of this extension - without introducing artifacts. This would require modifying the - vncviewer rendering engine to cache a master copy of the desktop - image for all operations. This project should also add support for - the RGB format to at least one XFree86 driver (e.g., ATI Radeon). - - The X Video Extension is one of the few popular extensions that DMX - does not support. We recommend implementing the X Video Extension - even if scaling is the specific goal of that work. - - We do nnoott recommend implementation of the XCreateScaledWindow - extension because of the complexity involved. We do nnoott recommend - implementation of the XPutImageScaled extension because it requires - the same amount of work as the XCopyAreaScaled extension, but provides - less functionality. Further, server-side scaling with a large frame - buffer is nnoott recommended because of the performance implications. - - The back-end scaling, especially with disconnect/reconnect support - should be explored in the future after disconnect/reconnect is - implemented, but not at the present time. - - - diff --git a/xorg-server/hw/vfb/InitOutput.c b/xorg-server/hw/vfb/InitOutput.c index 60915fdbf..29857877e 100644 --- a/xorg-server/hw/vfb/InitOutput.c +++ b/xorg-server/hw/vfb/InitOutput.c @@ -77,7 +77,6 @@ from The Open Group. typedef struct { - int scrnum; int width; int paddedBytesWidth; int paddedWidth; @@ -105,7 +104,15 @@ typedef struct } vfbScreenInfo, *vfbScreenInfoPtr; static int vfbNumScreens; -static vfbScreenInfo vfbScreens[MAXSCREENS]; +static vfbScreenInfo *vfbScreens; +static vfbScreenInfo defaultScreenInfo = { + .width = VFB_DEFAULT_WIDTH, + .height = VFB_DEFAULT_HEIGHT, + .depth = VFB_DEFAULT_DEPTH, + .blackPixel = VFB_DEFAULT_BLACKPIXEL, + .whitePixel = VFB_DEFAULT_WHITEPIXEL, + .lineBias = VFB_DEFAULT_LINEBIAS, +}; static Bool vfbPixmapDepths[33]; #ifdef HAS_MMAP static char *pfbdir = NULL; @@ -113,7 +120,6 @@ static char *pfbdir = NULL; typedef enum { NORMAL_MEMORY_FB, SHARED_MEMORY_FB, MMAPPED_FILE_FB } fbMemType; static fbMemType fbmemtype = NORMAL_MEMORY_FB; static char needswap = 0; -static int lastScreen = -1; static Bool Render = TRUE; #define swapcopy16(_dst, _src) \ @@ -134,25 +140,6 @@ vfbInitializePixmapDepths(void) vfbPixmapDepths[i] = FALSE; } -static void -vfbInitializeDefaultScreens(void) -{ - int i; - - for (i = 0; i < MAXSCREENS; i++) - { - vfbScreens[i].scrnum = i; - vfbScreens[i].width = VFB_DEFAULT_WIDTH; - vfbScreens[i].height = VFB_DEFAULT_HEIGHT; - vfbScreens[i].depth = VFB_DEFAULT_DEPTH; - vfbScreens[i].blackPixel = VFB_DEFAULT_BLACKPIXEL; - vfbScreens[i].whitePixel = VFB_DEFAULT_WHITEPIXEL; - vfbScreens[i].lineBias = VFB_DEFAULT_LINEBIAS; - vfbScreens[i].pfbMemory = NULL; - } - vfbNumScreens = 1; -} - static int vfbBitsPerPixel(int depth) { @@ -267,14 +254,20 @@ int ddxProcessArgument(int argc, char *argv[], int i) { static Bool firstTime = TRUE; + static int lastScreen = -1; + vfbScreenInfo *currentScreen; if (firstTime) { - vfbInitializeDefaultScreens(); vfbInitializePixmapDepths(); firstTime = FALSE; } + if (lastScreen == -1) + currentScreen = &defaultScreenInfo; + else + currentScreen = &vfbScreens[lastScreen]; + #define CHECK_FOR_REQUIRED_ARGUMENTS(num) \ if (((i + num) >= argc) || (!argv[i + num])) { \ ErrorF("Required argument to %s not specified\n", argv[i]); \ @@ -287,13 +280,23 @@ ddxProcessArgument(int argc, char *argv[], int i) int screenNum; CHECK_FOR_REQUIRED_ARGUMENTS(2); screenNum = atoi(argv[i+1]); - if (screenNum < 0 || screenNum >= MAXSCREENS) + if (screenNum < 0) { ErrorF("Invalid screen number %d\n", screenNum); UseMsg(); FatalError("Invalid screen number %d passed to -screen\n", screenNum); } + + if (vfbNumScreens <= screenNum) + { + vfbScreens = xrealloc(vfbScreens, sizeof(*vfbScreens) * (screenNum + 1)); + if (!vfbScreens) + FatalError("Not enough memory for screen %d\n", screenNum); + for (; vfbNumScreens <= screenNum; ++vfbNumScreens) + vfbScreens[vfbNumScreens] = defaultScreenInfo; + } + if (3 != sscanf(argv[i+2], "%dx%dx%d", &vfbScreens[screenNum].width, &vfbScreens[screenNum].height, @@ -305,8 +308,6 @@ ddxProcessArgument(int argc, char *argv[], int i) argv[i+2], screenNum); } - if (screenNum >= vfbNumScreens) - vfbNumScreens = screenNum + 1; lastScreen = screenNum; return 3; } @@ -348,61 +349,22 @@ ddxProcessArgument(int argc, char *argv[], int i) if (strcmp (argv[i], "-blackpixel") == 0) /* -blackpixel n */ { - Pixel pix; CHECK_FOR_REQUIRED_ARGUMENTS(1); - pix = atoi(argv[++i]); - if (-1 == lastScreen) - { - int i; - for (i = 0; i < MAXSCREENS; i++) - { - vfbScreens[i].blackPixel = pix; - } - } - else - { - vfbScreens[lastScreen].blackPixel = pix; - } + currentScreen->blackPixel = atoi(argv[++i]); return 2; } if (strcmp (argv[i], "-whitepixel") == 0) /* -whitepixel n */ { - Pixel pix; CHECK_FOR_REQUIRED_ARGUMENTS(1); - pix = atoi(argv[++i]); - if (-1 == lastScreen) - { - int i; - for (i = 0; i < MAXSCREENS; i++) - { - vfbScreens[i].whitePixel = pix; - } - } - else - { - vfbScreens[lastScreen].whitePixel = pix; - } + currentScreen->whitePixel = atoi(argv[++i]); return 2; } if (strcmp (argv[i], "-linebias") == 0) /* -linebias n */ { - unsigned int linebias; CHECK_FOR_REQUIRED_ARGUMENTS(1); - linebias = atoi(argv[++i]); - if (-1 == lastScreen) - { - int i; - for (i = 0; i < MAXSCREENS; i++) - { - vfbScreens[i].lineBias = linebias; - } - } - else - { - vfbScreens[lastScreen].lineBias = linebias; - } + currentScreen->lineBias = atoi(argv[++i]); return 2; } @@ -427,14 +389,18 @@ ddxProcessArgument(int argc, char *argv[], int i) return 0; } -static ColormapPtr InstalledMaps[MAXSCREENS]; +static int cmapScrPrivateKeyIndex; +static DevPrivateKey cmapScrPrivateKey = &cmapScrPrivateKeyIndex; + +#define GetInstalledColormap(s) ((ColormapPtr) dixLookupPrivate(&(s)->devPrivates, cmapScrPrivateKey)) +#define SetInstalledColormap(s,c) (dixSetPrivate(&(s)->devPrivates, cmapScrPrivateKey, c)) static int vfbListInstalledColormaps(ScreenPtr pScreen, Colormap *pmaps) { /* By the time we are processing requests, we can guarantee that there * is always a colormap installed */ - *pmaps = InstalledMaps[pScreen->myNum]->mid; + *pmaps = GetInstalledColormap(pScreen)->mid; return (1); } @@ -442,8 +408,7 @@ vfbListInstalledColormaps(ScreenPtr pScreen, Colormap *pmaps) static void vfbInstallColormap(ColormapPtr pmap) { - int index = pmap->pScreen->myNum; - ColormapPtr oldpmap = InstalledMaps[index]; + ColormapPtr oldpmap = GetInstalledColormap(pmap->pScreen); if (pmap != oldpmap) { @@ -459,7 +424,7 @@ vfbInstallColormap(ColormapPtr pmap) if(oldpmap != (ColormapPtr)None) WalkTree(pmap->pScreen, TellLostMap, (char *)&oldpmap->mid); /* Install pmap */ - InstalledMaps[index] = pmap; + SetInstalledColormap(pmap->pScreen, pmap); WalkTree(pmap->pScreen, TellGainedMap, (char *)&pmap->mid); entries = pmap->pVisual->ColormapEntries; @@ -500,7 +465,7 @@ vfbInstallColormap(ColormapPtr pmap) static void vfbUninstallColormap(ColormapPtr pmap) { - ColormapPtr curpmap = InstalledMaps[pmap->pScreen->myNum]; + ColormapPtr curpmap = GetInstalledColormap(pmap->pScreen); if(pmap == curpmap) { @@ -521,7 +486,7 @@ vfbStoreColors(ColormapPtr pmap, int ndef, xColorItem *pdefs) XWDColor *pXWDCmap; int i; - if (pmap != InstalledMaps[pmap->pScreen->myNum]) + if (pmap != GetInstalledColormap(pmap->pScreen)) { return; } @@ -595,7 +560,7 @@ vfbAllocateMmappedFramebuffer(vfbScreenInfoPtr pvfb) char dummyBuffer[DUMMY_BUFFER_SIZE]; int currentFileSize, writeThisTime; - sprintf(pvfb->mmap_file, "%s/Xvfb_screen%d", pfbdir, pvfb->scrnum); + sprintf(pvfb->mmap_file, "%s/Xvfb_screen%d", pfbdir, (int) (pvfb - vfbScreens)); if (-1 == (pvfb->mmap_fd = open(pvfb->mmap_file, O_CREAT|O_RDWR, 0666))) { perror("open"); @@ -668,7 +633,7 @@ vfbAllocateSharedMemoryFramebuffer(vfbScreenInfoPtr pvfb) return; } - ErrorF("screen %d shmid %d\n", pvfb->scrnum, pvfb->shmid); + ErrorF("screen %d shmid %d\n", (int) (pvfb - vfbScreens), pvfb->shmid); } #endif /* HAS_SHM */ @@ -830,10 +795,10 @@ vfbCloseScreen(int index, ScreenPtr pScreen) /* * XXX probably lots of stuff to clean. For now, - * clear InstalledMaps[] so that server reset works correctly. + * clear installed colormaps so that server reset works correctly. */ - for (i = 0; i < MAXSCREENS; i++) - InstalledMaps[i] = NULL; + for (i = 0; i < screenInfo.numScreens; i++) + SetInstalledColormap(screenInfo.screens[i], NULL); return pScreen->CloseScreen(index, pScreen); } @@ -992,6 +957,11 @@ InitOutput(ScreenInfo *screenInfo, int argc, char **argv) /* initialize screens */ + if (vfbNumScreens < 1) + { + vfbScreens = &defaultScreenInfo; + vfbNumScreens = 1; + } for (i = 0; i < vfbNumScreens; i++) { if (-1 == AddScreen(vfbScreenInit, argc, argv)) diff --git a/xorg-server/hw/xfree86/common/xf86DGA.c b/xorg-server/hw/xfree86/common/xf86DGA.c index 804fd37c1..1a1032786 100644 --- a/xorg-server/hw/xfree86/common/xf86DGA.c +++ b/xorg-server/hw/xfree86/common/xf86DGA.c @@ -731,7 +731,7 @@ DGAInstallCmap(ColormapPtr cmap) /* We rely on the extension to check that DGA is active */ if(!pScreenPriv->dgaColormap) - pScreenPriv->savedColormap = miInstalledMaps[pScreen->myNum]; + pScreenPriv->savedColormap = GetInstalledmiColormap(pScreen); pScreenPriv->dgaColormap = cmap; diff --git a/xorg-server/hw/xfree86/common/xf86Init.c b/xorg-server/hw/xfree86/common/xf86Init.c index 03a29ea0f..55d7a6209 100644 --- a/xorg-server/hw/xfree86/common/xf86Init.c +++ b/xorg-server/hw/xfree86/common/xf86Init.c @@ -552,9 +552,6 @@ InitOutput(ScreenInfo *pScreenInfo, int argc, char **argv) xf86Initialising = TRUE; if (serverGeneration == 1) { - - pScreenInfo->numScreens = 0; - if ((xf86ServerName = strrchr(argv[0], '/')) != 0) xf86ServerName++; else diff --git a/xorg-server/hw/xfree86/common/xf86Module.h b/xorg-server/hw/xfree86/common/xf86Module.h index bbf5786c9..d61758f78 100644 --- a/xorg-server/hw/xfree86/common/xf86Module.h +++ b/xorg-server/hw/xfree86/common/xf86Module.h @@ -82,9 +82,9 @@ typedef enum { * mask is 0xFFFF0000. */ #define ABI_ANSIC_VERSION SET_ABI_VERSION(0, 4) -#define ABI_VIDEODRV_VERSION SET_ABI_VERSION(7, 0) -#define ABI_XINPUT_VERSION SET_ABI_VERSION(9, 0) -#define ABI_EXTENSION_VERSION SET_ABI_VERSION(3, 0) +#define ABI_VIDEODRV_VERSION SET_ABI_VERSION(8, 0) +#define ABI_XINPUT_VERSION SET_ABI_VERSION(10, 0) +#define ABI_EXTENSION_VERSION SET_ABI_VERSION(4, 0) #define ABI_FONT_VERSION SET_ABI_VERSION(0, 6) #define MODINFOSTRING1 0xef23fdc5 diff --git a/xorg-server/hw/xfree86/common/xf86Xinput.c b/xorg-server/hw/xfree86/common/xf86Xinput.c index dba3370f3..a1a5527f4 100644 --- a/xorg-server/hw/xfree86/common/xf86Xinput.c +++ b/xorg-server/hw/xfree86/common/xf86Xinput.c @@ -825,7 +825,7 @@ NewInputDeviceRequest (InputOption *options, InputAttributes *attrs, } if (!idev->driver || !idev->identifier) { - xf86Msg(X_ERROR, "No input driver/identifier specified (ignoring)\n"); + xf86Msg(X_INFO, "No input driver/identifier specified (ignoring)\n"); rval = BadRequest; goto unwind; } diff --git a/xorg-server/hw/xfree86/common/xf86cmap.c b/xorg-server/hw/xfree86/common/xf86cmap.c index f60d96e7d..e266ffb6d 100644 --- a/xorg-server/hw/xfree86/common/xf86cmap.c +++ b/xorg-server/hw/xfree86/common/xf86cmap.c @@ -63,10 +63,10 @@ #define SCREEN_EPILOGUE(pScreen, field, wrapper)\ ((pScreen)->field = wrapper) -#define LOAD_PALETTE(pmap, index) \ - ((pmap == miInstalledMaps[index]) && \ +#define LOAD_PALETTE(pmap) \ + ((pmap == GetInstalledmiColormap(pmap->pScreen)) && \ ((pScreenPriv->flags & CMAP_LOAD_EVEN_IF_OFFSCREEN) || \ - xf86Screens[index]->vtSema || pScreenPriv->isDGAmode)) + xf86Screens[pmap->pScreen->myNum]->vtSema || pScreenPriv->isDGAmode)) typedef struct _CMapLink { @@ -221,7 +221,7 @@ Bool xf86HandleColormaps( } /* Force the initial map to be loaded */ - miInstalledMaps[pScreen->myNum] = NULL; + SetInstalledmiColormap(pScreen, NULL); CMapInstallColormap(pDefMap); return TRUE; } @@ -425,11 +425,10 @@ static void CMapInstallColormap(ColormapPtr pmap) { ScreenPtr pScreen = pmap->pScreen; - int index = pScreen->myNum; CMapScreenPtr pScreenPriv = (CMapScreenPtr)dixLookupPrivate( &pScreen->devPrivates, CMapScreenKey); - if (pmap == miInstalledMaps[index]) + if (pmap == GetInstalledmiColormap(pmap->pScreen)) return; pScreen->InstallColormap = pScreenPriv->InstallColormap; @@ -438,15 +437,15 @@ CMapInstallColormap(ColormapPtr pmap) /* Important. We let the lower layers, namely DGA, overwrite the choice of Colormap to install */ - if (miInstalledMaps[index]) - pmap = miInstalledMaps[index]; + if (GetInstalledmiColormap(pmap->pScreen)) + pmap = GetInstalledmiColormap(pmap->pScreen); if (!(pScreenPriv->flags & CMAP_PALETTED_TRUECOLOR) && (pmap->pVisual->class == TrueColor) && CMapColormapUseMax(pmap->pVisual, pScreenPriv)) return; - if(LOAD_PALETTE(pmap, index)) + if(LOAD_PALETTE(pmap)) CMapReinstallMap(pmap); } @@ -461,8 +460,8 @@ CMapEnterVT(int index, int flags) &pScreen->devPrivates, CMapScreenKey); if((*pScreenPriv->EnterVT)(index, flags)) { - if(miInstalledMaps[index]) - CMapReinstallMap(miInstalledMaps[index]); + if(GetInstalledmiColormap(pScreen)) + CMapReinstallMap(GetInstalledmiColormap(pScreen)); return TRUE; } return FALSE; @@ -477,8 +476,8 @@ CMapSwitchMode(int index, DisplayModePtr mode, int flags) &pScreen->devPrivates, CMapScreenKey); if((*pScreenPriv->SwitchMode)(index, mode, flags)) { - if(miInstalledMaps[index]) - CMapReinstallMap(miInstalledMaps[index]); + if(GetInstalledmiColormap(pScreen)) + CMapReinstallMap(GetInstalledmiColormap(pScreen)); return TRUE; } return FALSE; @@ -497,9 +496,9 @@ CMapSetDGAMode(int index, int num, DGADevicePtr dev) pScreenPriv->isDGAmode = DGAActive(index); - if(!pScreenPriv->isDGAmode && miInstalledMaps[index] + if(!pScreenPriv->isDGAmode && GetInstalledmiColormap(pScreen) && xf86Screens[pScreen->myNum]->vtSema) - CMapReinstallMap(miInstalledMaps[index]); + CMapReinstallMap(GetInstalledmiColormap(pScreen)); return ret; } @@ -649,7 +648,7 @@ CMapRefreshColors(ColormapPtr pmap, int defs, int* indices) } - if(LOAD_PALETTE(pmap, pmap->pScreen->myNum)) + if(LOAD_PALETTE(pmap)) (*pScrn->LoadPalette)(pScreenPriv->pScrn, defs, indices, colors, pmap->pVisual); @@ -802,7 +801,7 @@ CMapSetOverscan(ColormapPtr pmap, int defs, int *indices) } if (newOverscan) { pColPriv->overscan = overscan; - if (LOAD_PALETTE(pmap, pmap->pScreen->myNum)) { + if (LOAD_PALETTE(pmap)) { #ifdef DEBUGOVERSCAN ErrorF("SetOverscan() called from CmapSetOverscan\n"); #endif @@ -929,10 +928,10 @@ CMapChangeGamma( pLink = pLink->next; } - if(miInstalledMaps[pScreen->myNum] && + if(GetInstalledmiColormap(pScreen) && ((pScreenPriv->flags & CMAP_LOAD_EVEN_IF_OFFSCREEN) || pScrn->vtSema || pScreenPriv->isDGAmode)) { - ColormapPtr pMap = miInstalledMaps[pScreen->myNum]; + ColormapPtr pMap = GetInstalledmiColormap(pScreen); if (!(pScreenPriv->flags & CMAP_PALETTED_TRUECOLOR) && (pMap->pVisual->class == TrueColor) && @@ -951,9 +950,9 @@ CMapChangeGamma( if(pLink) { /* need to trick CMapRefreshColors() into thinking this is the currently installed map */ - miInstalledMaps[pScreen->myNum] = pLink->cmap; + SetInstalledmiColormap(pScreen, pLink->cmap); CMapReinstallMap(pLink->cmap); - miInstalledMaps[pScreen->myNum] = pMap; + SetInstalledmiColormap(pScreen, pMap); } } else CMapReinstallMap(pMap); @@ -1035,10 +1034,10 @@ xf86ChangeGammaRamp( pLink = pLink->next; } - if(miInstalledMaps[pScreen->myNum] && + if(GetInstalledmiColormap(pScreen) && ((pScreenPriv->flags & CMAP_LOAD_EVEN_IF_OFFSCREEN) || pScrn->vtSema || pScreenPriv->isDGAmode)) { - ColormapPtr pMap = miInstalledMaps[pScreen->myNum]; + ColormapPtr pMap = GetInstalledmiColormap(pScreen); if (!(pScreenPriv->flags & CMAP_PALETTED_TRUECOLOR) && (pMap->pVisual->class == TrueColor) && @@ -1057,9 +1056,9 @@ xf86ChangeGammaRamp( if(pLink) { /* need to trick CMapRefreshColors() into thinking this is the currently installed map */ - miInstalledMaps[pScreen->myNum] = pLink->cmap; + SetInstalledmiColormap(pScreen, pLink->cmap); CMapReinstallMap(pLink->cmap); - miInstalledMaps[pScreen->myNum] = pMap; + SetInstalledmiColormap(pScreen, pMap); } } else CMapReinstallMap(pMap); diff --git a/xorg-server/hw/xfree86/common/xf86xv.c b/xorg-server/hw/xfree86/common/xf86xv.c index bdcc4fc2b..2cc2f6093 100644 --- a/xorg-server/hw/xfree86/common/xf86xv.c +++ b/xorg-server/hw/xfree86/common/xf86xv.c @@ -186,7 +186,9 @@ typedef struct { int num; } OffscreenImageRec; -static OffscreenImageRec OffscreenImages[MAXSCREENS]; +static int OffscreenPrivateKeyIndex; +static DevPrivateKey OffscreenPrivateKey = &OffscreenPrivateKeyIndex; +#define GetOffscreenImage(pScreen) ((OffscreenImageRec *) dixLookupPrivate(&(pScreen)->devPrivates, OffscreenPrivateKey)) Bool xf86XVRegisterOffscreenImages( @@ -194,9 +196,18 @@ xf86XVRegisterOffscreenImages( XF86OffscreenImagePtr images, int num ){ - OffscreenImages[pScreen->myNum].num = num; - OffscreenImages[pScreen->myNum].images = images; - + OffscreenImageRec *OffscreenImage; + /* This function may be called before xf86XVScreenInit, so there's + * no better place than this to call dixRequestPrivate to ensure we + * have space reserved. After the first call it is a no-op. */ + if(!dixRequestPrivate(OffscreenPrivateKey, sizeof(OffscreenImageRec)) || + !(OffscreenImage = GetOffscreenImage(pScreen))) + /* Every X.org driver assumes this function always succeeds, so + * just die on allocation failure. */ + FatalError("Could not allocate private storage for XV offscreen images.\n"); + + OffscreenImage->num = num; + OffscreenImage->images = images; return TRUE; } @@ -205,8 +216,9 @@ xf86XVQueryOffscreenImages( ScreenPtr pScreen, int *num ){ - *num = OffscreenImages[pScreen->myNum].num; - return OffscreenImages[pScreen->myNum].images; + OffscreenImageRec *OffscreenImage = GetOffscreenImage(pScreen); + *num = OffscreenImage->num; + return OffscreenImage->images; } @@ -1177,9 +1189,6 @@ xf86XVCloseScreen(int i, ScreenPtr pScreen) XvAdaptorPtr pa; int c; - /* Clear offscreen images */ - memset(&OffscreenImages[pScreen->myNum], 0, sizeof(OffscreenImages[0])); - if(!ScreenPriv) return TRUE; if(ScreenPriv->videoGC) { diff --git a/xorg-server/hw/xfree86/dixmods/extmod/xf86dga2.c b/xorg-server/hw/xfree86/dixmods/extmod/xf86dga2.c index 5367bcc42..038551467 100644 --- a/xorg-server/hw/xfree86/dixmods/extmod/xf86dga2.c +++ b/xorg-server/hw/xfree86/dixmods/extmod/xf86dga2.c @@ -57,12 +57,12 @@ static void XDGAResetProc(ExtensionEntry *extEntry); static void DGAClientStateChange (CallbackListPtr*, pointer, pointer); -static ClientPtr DGAClients[MAXSCREENS]; - unsigned char DGAReqCode = 0; int DGAErrorBase; int DGAEventBase; +static int DGAScreenPrivateKeyIndex; +static DevPrivateKey DGAScreenPrivateKey = &DGAScreenPrivateKeyIndex; static int DGAClientPrivateKeyIndex; static DevPrivateKey DGAClientPrivateKey = &DGAClientPrivateKeyIndex; static int DGACallbackRefCount = 0; @@ -73,6 +73,11 @@ typedef struct { int minor; } DGAPrivRec, *DGAPrivPtr; +#define DGA_GETCLIENT(idx) ((ClientPtr) \ + dixLookupPrivate(&screenInfo.screens[idx]->devPrivates, DGAScreenPrivateKey)) +#define DGA_SETCLIENT(idx,p) \ + dixSetPrivate(&screenInfo.screens[idx]->devPrivates, DGAScreenPrivateKey, p) + #define DGA_GETPRIV(c) ((DGAPrivPtr) \ dixLookupPrivate(&(c)->devPrivates, DGAClientPrivateKey)) #define DGA_SETPRIV(c,p) \ @@ -93,9 +98,6 @@ XFree86DGAExtensionInit(INITARGS) StandardMinorOpcode))) { int i; - for(i = 0; i < MAXSCREENS; i++) - DGAClients[i] = NULL; - DGAReqCode = (unsigned char)extEntry->base; DGAErrorBase = extEntry->errorBase; DGAEventBase = extEntry->eventBase; @@ -282,7 +284,7 @@ DGAClientStateChange ( int i; for(i = 0; i < screenInfo.numScreens; i++) { - if(DGAClients[i] == pci->client) { + if(DGA_GETCLIENT(i) == pci->client) { client = pci->client; break; } @@ -294,7 +296,7 @@ DGAClientStateChange ( XDGAModeRec mode; PixmapPtr pPix; - DGAClients[i] = NULL; + DGA_SETCLIENT(i, NULL); DGASelectInput(i, NULL, 0); DGASetMode(i, 0, &mode, &pPix); @@ -311,10 +313,12 @@ ProcXDGASetMode(ClientPtr client) XDGAModeRec mode; xXDGAModeInfo info; PixmapPtr pPix; + ClientPtr owner; int size; if (stuff->screen > screenInfo.numScreens) return BadValue; + owner = DGA_GETCLIENT(stuff->screen); REQUEST_SIZE_MATCH(xXDGASetModeReq); rep.type = X_Reply; @@ -326,16 +330,15 @@ ProcXDGASetMode(ClientPtr client) if (!DGAAvailable(stuff->screen)) return DGAErrorBase + XF86DGANoDirectVideoMode; - if(DGAClients[stuff->screen] && - (DGAClients[stuff->screen] != client)) + if(owner && owner != client) return DGAErrorBase + XF86DGANoDirectVideoMode; if(!stuff->mode) { - if(DGAClients[stuff->screen]) { + if(owner) { if(--DGACallbackRefCount == 0) DeleteCallback(&ClientStateCallback, DGAClientStateChange, NULL); } - DGAClients[stuff->screen] = NULL; + DGA_SETCLIENT(stuff->screen, NULL); DGASelectInput(stuff->screen, NULL, 0); DGASetMode(stuff->screen, 0, &mode, &pPix); WriteToClient(client, sz_xXDGASetModeReply, (char*)&rep); @@ -345,12 +348,12 @@ ProcXDGASetMode(ClientPtr client) if(Success != DGASetMode(stuff->screen, stuff->mode, &mode, &pPix)) return BadValue; - if(!DGAClients[stuff->screen]) { + if(!owner) { if(DGACallbackRefCount++ == 0) AddCallback (&ClientStateCallback, DGAClientStateChange, NULL); } - DGAClients[stuff->screen] = client; + DGA_SETCLIENT(stuff->screen, client); if(pPix) { if(AddResource(stuff->pid, RT_PIXMAP, (pointer)(pPix))) { @@ -405,7 +408,7 @@ ProcXDGASetViewport(ClientPtr client) if (stuff->screen > screenInfo.numScreens) return BadValue; - if(DGAClients[stuff->screen] != client) + if(DGA_GETCLIENT(stuff->screen) != client) return DGAErrorBase + XF86DGADirectNotActivated; REQUEST_SIZE_MATCH(xXDGASetViewportReq); @@ -425,7 +428,7 @@ ProcXDGAInstallColormap(ClientPtr client) if (stuff->screen > screenInfo.numScreens) return BadValue; - if(DGAClients[stuff->screen] != client) + if(DGA_GETCLIENT(stuff->screen) != client) return DGAErrorBase + XF86DGADirectNotActivated; REQUEST_SIZE_MATCH(xXDGAInstallColormapReq); @@ -451,12 +454,12 @@ ProcXDGASelectInput(ClientPtr client) if (stuff->screen > screenInfo.numScreens) return BadValue; - if(DGAClients[stuff->screen] != client) + if(DGA_GETCLIENT(stuff->screen) != client) return DGAErrorBase + XF86DGADirectNotActivated; REQUEST_SIZE_MATCH(xXDGASelectInputReq); - if(DGAClients[stuff->screen] == client) + if(DGA_GETCLIENT(stuff->screen) == client) DGASelectInput(stuff->screen, client, stuff->mask); return (client->noClientException); @@ -471,7 +474,7 @@ ProcXDGAFillRectangle(ClientPtr client) if (stuff->screen > screenInfo.numScreens) return BadValue; - if(DGAClients[stuff->screen] != client) + if(DGA_GETCLIENT(stuff->screen) != client) return DGAErrorBase + XF86DGADirectNotActivated; REQUEST_SIZE_MATCH(xXDGAFillRectangleReq); @@ -491,7 +494,7 @@ ProcXDGACopyArea(ClientPtr client) if (stuff->screen > screenInfo.numScreens) return BadValue; - if(DGAClients[stuff->screen] != client) + if(DGA_GETCLIENT(stuff->screen) != client) return DGAErrorBase + XF86DGADirectNotActivated; REQUEST_SIZE_MATCH(xXDGACopyAreaReq); @@ -512,7 +515,7 @@ ProcXDGACopyTransparentArea(ClientPtr client) if (stuff->screen > screenInfo.numScreens) return BadValue; - if(DGAClients[stuff->screen] != client) + if(DGA_GETCLIENT(stuff->screen) != client) return DGAErrorBase + XF86DGADirectNotActivated; REQUEST_SIZE_MATCH(xXDGACopyTransparentAreaReq); @@ -534,7 +537,7 @@ ProcXDGAGetViewportStatus(ClientPtr client) if (stuff->screen > screenInfo.numScreens) return BadValue; - if(DGAClients[stuff->screen] != client) + if(DGA_GETCLIENT(stuff->screen) != client) return DGAErrorBase + XF86DGADirectNotActivated; REQUEST_SIZE_MATCH(xXDGAGetViewportStatusReq); @@ -557,7 +560,7 @@ ProcXDGASync(ClientPtr client) if (stuff->screen > screenInfo.numScreens) return BadValue; - if(DGAClients[stuff->screen] != client) + if(DGA_GETCLIENT(stuff->screen) != client) return DGAErrorBase + XF86DGADirectNotActivated; REQUEST_SIZE_MATCH(xXDGASyncReq); @@ -602,7 +605,7 @@ ProcXDGAChangePixmapMode(ClientPtr client) if (stuff->screen > screenInfo.numScreens) return BadValue; - if(DGAClients[stuff->screen] != client) + if(DGA_GETCLIENT(stuff->screen) != client) return DGAErrorBase + XF86DGADirectNotActivated; REQUEST_SIZE_MATCH(xXDGAChangePixmapModeReq); @@ -633,7 +636,7 @@ ProcXDGACreateColormap(ClientPtr client) if (stuff->screen > screenInfo.numScreens) return BadValue; - if(DGAClients[stuff->screen] != client) + if(DGA_GETCLIENT(stuff->screen) != client) return DGAErrorBase + XF86DGADirectNotActivated; REQUEST_SIZE_MATCH(xXDGACreateColormapReq); @@ -713,18 +716,19 @@ ProcXF86DGADirectVideo(ClientPtr client) int num; PixmapPtr pix; XDGAModeRec mode; + ClientPtr owner; REQUEST(xXF86DGADirectVideoReq); if (stuff->screen > screenInfo.numScreens) return BadValue; + owner = DGA_GETCLIENT(stuff->screen); REQUEST_SIZE_MATCH(xXF86DGADirectVideoReq); if (!DGAAvailable(stuff->screen)) return DGAErrorBase + XF86DGANoDirectVideoMode; - if (DGAClients[stuff->screen] && - (DGAClients[stuff->screen] != client)) + if (owner && owner != client) return DGAErrorBase + XF86DGANoDirectVideoMode; if (stuff->enable & XF86DGADirectGraphics) { @@ -743,19 +747,19 @@ ProcXF86DGADirectVideo(ClientPtr client) /* We need to track the client and attach the teardown callback */ if (stuff->enable & (XF86DGADirectGraphics | XF86DGADirectKeyb | XF86DGADirectMouse)) { - if (!DGAClients[stuff->screen]) { + if (!owner) { if (DGACallbackRefCount++ == 0) AddCallback (&ClientStateCallback, DGAClientStateChange, NULL); } - DGAClients[stuff->screen] = client; + DGA_SETCLIENT(stuff->screen, client); } else { - if (DGAClients[stuff->screen]) { + if (owner) { if (--DGACallbackRefCount == 0) DeleteCallback(&ClientStateCallback, DGAClientStateChange, NULL); } - DGAClients[stuff->screen] = NULL; + DGA_SETCLIENT(stuff->screen, NULL); } return (client->noClientException); @@ -800,7 +804,7 @@ ProcXF86DGASetViewPort(ClientPtr client) if (stuff->screen > screenInfo.numScreens) return BadValue; - if (DGAClients[stuff->screen] != client) + if (DGA_GETCLIENT(stuff->screen) != client) return DGAErrorBase + XF86DGADirectNotActivated; REQUEST_SIZE_MATCH(xXF86DGASetViewPortReq); @@ -864,7 +868,7 @@ ProcXF86DGAInstallColormap(ClientPtr client) if (stuff->screen > screenInfo.numScreens) return BadValue; - if (DGAClients[stuff->screen] != client) + if (DGA_GETCLIENT(stuff->screen) != client) return DGAErrorBase + XF86DGADirectNotActivated; REQUEST_SIZE_MATCH(xXF86DGAInstallColormapReq); @@ -913,7 +917,7 @@ ProcXF86DGAViewPortChanged(ClientPtr client) if (stuff->screen > screenInfo.numScreens) return BadValue; - if (DGAClients[stuff->screen] != client) + if (DGA_GETCLIENT(stuff->screen) != client) return DGAErrorBase + XF86DGADirectNotActivated; REQUEST_SIZE_MATCH(xXF86DGAViewPortChangedReq); diff --git a/xorg-server/hw/xfree86/doc/sgml/DESIGN.sgml b/xorg-server/hw/xfree86/doc/sgml/DESIGN.sgml index 5beff653f..e95df7999 100644 --- a/xorg-server/hw/xfree86/doc/sgml/DESIGN.sgml +++ b/xorg-server/hw/xfree86/doc/sgml/DESIGN.sgml @@ -1,5 +1,5 @@ <!DOCTYPE linuxdoc PUBLIC "-//Xorg//DTD linuxdoc//EN" [ - <!ENTITY % defs SYSTEM "defs.ent"> %defs; + <!ENTITY % defs SYSTEM "X11/defs.ent"> %defs; <!-- config file keyword markup --> <!ENTITY s.key STARTTAG "bf"> <!ENTITY e.key ENDTAG "bf"> diff --git a/xorg-server/hw/xfree86/ramdac/xf86Cursor.c b/xorg-server/hw/xfree86/ramdac/xf86Cursor.c index f5f087314..346e99490 100644 --- a/xorg-server/hw/xfree86/ramdac/xf86Cursor.c +++ b/xorg-server/hw/xfree86/ramdac/xf86Cursor.c @@ -312,6 +312,8 @@ xf86CursorSetCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCurs, xf86SetCursor(pScreen, NullCursor, x, y); ScreenPriv->isUp = FALSE; } + if (ScreenPriv->CurrentCursor) + FreeCursor(ScreenPriv->CurrentCursor, None); ScreenPriv->CurrentCursor = NullCursor; return; } diff --git a/xorg-server/hw/xfree86/vgahw/vgaCmap.c b/xorg-server/hw/xfree86/vgahw/vgaCmap.c index 5bd38b468..06eeb4ce1 100644 --- a/xorg-server/hw/xfree86/vgahw/vgaCmap.c +++ b/xorg-server/hw/xfree86/vgahw/vgaCmap.c @@ -50,7 +50,7 @@ vgaListInstalledColormaps(pScreen, pmaps) /* By the time we are processing requests, we can guarantee that there * is always a colormap installed */ - *pmaps = miInstalledMaps[pScreen->myNum]->mid; + *pmaps = GetInstalledmiColormap(pScreen)->mid; return(1); } @@ -62,13 +62,13 @@ vgaGetInstalledColormaps(pScreen, pmaps) /* By the time we are processing requests, we can guarantee that there * is always a colormap installed */ - *pmaps = miInstalledMaps[pScreen->myNum]; + *pmaps = GetInstalledmiColormap(pScreen); return(1); } int vgaCheckColorMap(ColormapPtr pmap) { - return (pmap != miInstalledMaps[pmap->pScreen->myNum]); + return (pmap != GetInstalledmiColormap(pmap->pScreen)); } @@ -217,7 +217,7 @@ void vgaInstallColormap(pmap) ColormapPtr pmap; { - ColormapPtr oldmap = miInstalledMaps[pmap->pScreen->myNum]; + ColormapPtr oldmap = GetInstalledmiColormap(pmap->pScreen); int entries; Pixel * ppix; xrgb * prgb; @@ -242,7 +242,7 @@ vgaInstallColormap(pmap) if ( oldmap != NOMAPYET) WalkTree( pmap->pScreen, TellLostMap, &oldmap->mid); - miInstalledMaps[pmap->pScreen->myNum] = pmap; + SetInstalledmiColormap(pmap->pScreen, pmap); for ( i=0; i<entries; i++) ppix[i] = i; @@ -273,13 +273,13 @@ vgaUninstallColormap(pmap) ColormapPtr defColormap; - if ( pmap != miInstalledMaps[pmap->pScreen->myNum] ) + if ( pmap != GetInstalledmiColormap(pmap->pScreen)) return; dixLookupResourceByType((pointer *)&defColormap, pmap->pScreen->defColormap, RT_COLORMAP, serverClient, DixInstallAccess); - if (defColormap == miInstalledMaps[pmap->pScreen->myNum]) + if (defColormap == GetInstalledmiColormap(pmap->pScreen)) return; (*pmap->pScreen->InstallColormap) (defColormap); diff --git a/xorg-server/hw/xnest/Color.c b/xorg-server/hw/xnest/Color.c index dc749478f..2e6de15e4 100644 --- a/xorg-server/hw/xnest/Color.c +++ b/xorg-server/hw/xnest/Color.c @@ -34,7 +34,11 @@ is" without express or implied warranty. #include "XNWindow.h" #include "Args.h" -static ColormapPtr InstalledMaps[MAXSCREENS]; +static int cmapScrPrivateKeyIndex; +static DevPrivateKey cmapScrPrivateKey = &cmapScrPrivateKeyIndex; + +#define GetInstalledColormap(s) ((ColormapPtr) dixLookupPrivate(&(s)->devPrivates, cmapScrPrivateKey)) +#define SetInstalledColormap(s,c) (dixSetPrivate(&(s)->devPrivates, cmapScrPrivateKey, c)) Bool xnestCreateColormap(ColormapPtr pCmap) @@ -332,11 +336,7 @@ xnestDirectUninstallColormaps(ScreenPtr pScreen) void xnestInstallColormap(ColormapPtr pCmap) { - int index; - ColormapPtr pOldCmap; - - index = pCmap->pScreen->myNum; - pOldCmap = InstalledMaps[index]; + ColormapPtr pOldCmap = GetInstalledColormap(pCmap->pScreen); if(pCmap != pOldCmap) { @@ -346,7 +346,7 @@ xnestInstallColormap(ColormapPtr pCmap) if(pOldCmap != (ColormapPtr)None) WalkTree(pCmap->pScreen, TellLostMap, (pointer)&pOldCmap->mid); - InstalledMaps[index] = pCmap; + SetInstalledColormap(pCmap->pScreen, pCmap); WalkTree(pCmap->pScreen, TellGainedMap, (pointer)&pCmap->mid); xnestSetInstalledColormapWindows(pCmap->pScreen); @@ -357,11 +357,7 @@ xnestInstallColormap(ColormapPtr pCmap) void xnestUninstallColormap(ColormapPtr pCmap) { - int index; - ColormapPtr pCurCmap; - - index = pCmap->pScreen->myNum; - pCurCmap = InstalledMaps[index]; + ColormapPtr pCurCmap = GetInstalledColormap(pCmap->pScreen); if(pCmap == pCurCmap) { @@ -382,7 +378,7 @@ int xnestListInstalledColormaps(ScreenPtr pScreen, Colormap *pCmapIDs) { if (xnestInstalledDefaultColormap) { - *pCmapIDs = InstalledMaps[pScreen->myNum]->mid; + *pCmapIDs = GetInstalledColormap(pScreen)->mid; return 1; } else diff --git a/xorg-server/hw/xquartz/GL/indirect.c b/xorg-server/hw/xquartz/GL/indirect.c index 70558ed20..ad9ebbdac 100644 --- a/xorg-server/hw/xquartz/GL/indirect.c +++ b/xorg-server/hw/xquartz/GL/indirect.c @@ -42,6 +42,8 @@ #define GL_GLEXT_WUNDEF_SUPPORT #include <OpenGL/OpenGL.h> +#include <OpenGL/gl.h> +#include <OpenGL/glext.h> #include <OpenGL/CGLContext.h> /* These next few GL_EXT pre-processing blocks are to explicitly define diff --git a/xorg-server/hw/xquartz/GL/visualConfigs.c b/xorg-server/hw/xquartz/GL/visualConfigs.c index bef27f048..cecc90265 100644 --- a/xorg-server/hw/xquartz/GL/visualConfigs.c +++ b/xorg-server/hw/xquartz/GL/visualConfigs.c @@ -35,9 +35,10 @@ #include "dri.h" #include <OpenGL/OpenGL.h> +#include <OpenGL/gl.h> +#include <OpenGL/glext.h> #include <OpenGL/CGLContext.h> -#include <GL/gl.h> #include <GL/glxproto.h> #include <windowstr.h> #include <resource.h> diff --git a/xorg-server/hw/xquartz/xpr/x-list.c b/xorg-server/hw/xquartz/xpr/x-list.c index 3596dd355..77c9309aa 100644 --- a/xorg-server/hw/xquartz/xpr/x-list.c +++ b/xorg-server/hw/xquartz/xpr/x-list.c @@ -97,6 +97,7 @@ X_PFX (list_prepend) (x_list *lst, void *data) int i; b = malloc (sizeof (x_list_block)); + assert(b != NULL); for (i = 0; i < NODES_PER_BLOCK - 1; i++) b->l[i].next = &(b->l[i+1]); diff --git a/xorg-server/hw/xwin/InitOutput.c b/xorg-server/hw/xwin/InitOutput.c index df5f1f221..2cd7bab08 100644 --- a/xorg-server/hw/xwin/InitOutput.c +++ b/xorg-server/hw/xwin/InitOutput.c @@ -1,1175 +1,1165 @@ -
-/*
-
-Copyright 1993, 1998 The Open Group
-Copyright (C) Colin Harrison 2005-2008
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation.
-
-The above copyright notice and this permission notice shall be included
-in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
-OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
-ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of The Open Group shall
-not be used in advertising or otherwise to promote the sale, use or
-other dealings in this Software without prior written authorization
-from The Open Group.
-
-*/
-
-#ifdef HAVE_XWIN_CONFIG_H
-#include <xwin-config.h>
-#endif
-#include "win.h"
-#include "winmsg.h"
-#include "winconfig.h"
-#include "winprefs.h"
-#ifdef XWIN_CLIPBOARD
-#include "X11/Xlocale.h"
-#endif
-#ifdef DPMSExtension
-#include "dpmsproc.h"
-#endif
-#ifdef __CYGWIN__
-#include <mntent.h>
-#endif
-#if defined(WIN32)
-#include "xkbsrv.h"
-#endif
-#ifdef RELOCATE_PROJECTROOT
-#undef Status
-#include <shlobj.h>
-typedef HRESULT (__stdcall * SHGETFOLDERPATHPROC)(
- HWND hwndOwner,
- int nFolder,
- HANDLE hToken,
- DWORD dwFlags,
- LPSTR pszPath
-);
-#endif
-
-
-/*
- * References to external symbols
- */
-
-extern int g_iNumScreens;
-extern winScreenInfo g_ScreenInfo[];
-extern int g_iLastScreen;
-extern char * g_pszCommandLine;
-extern Bool g_fSilentFatalError;
-
-extern const char * g_pszLogFile;
-extern Bool g_fLogFileChanged;
-extern int g_iLogVerbose;
-Bool g_fLogInited;
-
-extern Bool g_fXdmcpEnabled;
-extern Bool g_fAuthEnabled;
-#ifdef HAS_DEVWINDOWS
-extern int g_fdMessageQueue;
-#endif
-extern const char * g_pszQueryHost;
-extern HINSTANCE g_hInstance;
-
-#ifdef XWIN_CLIPBOARD
-extern Bool g_fUnicodeClipboard;
-extern Bool g_fClipboardLaunched;
-extern Bool g_fClipboardStarted;
-extern pthread_t g_ptClipboardProc;
-extern HWND g_hwndClipboard;
-extern Bool g_fClipboard;
-#endif
-
-extern HMODULE g_hmodDirectDraw;
-extern FARPROC g_fpDirectDrawCreate;
-extern FARPROC g_fpDirectDrawCreateClipper;
-
-extern HMODULE g_hmodCommonControls;
-extern FARPROC g_fpTrackMouseEvent;
-extern Bool g_fNoHelpMessageBox;
-extern Bool g_fSilentDupError;
-extern Bool g_fNativeGl;
-
-/*
- * Function prototypes
- */
-
-#ifdef XWIN_CLIPBOARD
-static void
-winClipboardShutdown (void);
-#endif
-
-#if defined(DDXOSVERRORF)
-void
-OsVendorVErrorF (const char *pszFormat, va_list va_args);
-#endif
-
-void
-winInitializeDefaultScreens (void);
-
-static Bool
-winCheckDisplayNumber (void);
-
-void
-winLogCommandLine (int argc, char *argv[]);
-
-void
-winLogVersionInfo (void);
-
-Bool
-winValidateArgs (void);
-
-#ifdef RELOCATE_PROJECTROOT
-const char *
-winGetBaseDir(void);
-#endif
-
-static
-void glx_debugging(void);
-
-/*
- * For the depth 24 pixmap we default to 32 bits per pixel, but
- * we change this pixmap format later if we detect that the display
- * is going to be running at 24 bits per pixel.
- *
- * FIXME: On second thought, don't DIBs only support 32 bits per pixel?
- * DIBs are the underlying bitmap used for DirectDraw surfaces, so it
- * seems that all pixmap formats with depth 24 would be 32 bits per pixel.
- * Confirm whether depth 24 DIBs can have 24 bits per pixel, then remove/keep
- * the bits per pixel adjustment and update this comment to reflect the
- * situation. Harold Hunt - 2002/07/02
- */
-
-static PixmapFormatRec g_PixmapFormats[] = {
- { 1, 1, BITMAP_SCANLINE_PAD },
- { 4, 8, BITMAP_SCANLINE_PAD },
- { 8, 8, BITMAP_SCANLINE_PAD },
- { 15, 16, BITMAP_SCANLINE_PAD },
- { 16, 16, BITMAP_SCANLINE_PAD },
- { 24, 32, BITMAP_SCANLINE_PAD },
- { 32, 32, BITMAP_SCANLINE_PAD }
-};
-
-const int NUMFORMATS = sizeof (g_PixmapFormats) / sizeof (g_PixmapFormats[0]);
-
-#ifdef XWIN_CLIPBOARD
-static void
-winClipboardShutdown (void)
-{
- /* Close down clipboard resources */
- if (g_fClipboard && g_fClipboardLaunched && g_fClipboardStarted)
- {
- /* Synchronously destroy the clipboard window */
- if (g_hwndClipboard != NULL)
- {
- SendMessage (g_hwndClipboard, WM_DESTROY, 0, 0);
- /* NOTE: g_hwndClipboard is set to NULL in winclipboardthread.c */
- }
- else
- return;
-
- /* Wait for the clipboard thread to exit */
- pthread_join (g_ptClipboardProc, NULL);
-
- winDebug ("winClipboardShutdown - Clipboard thread has exited.\n");
- }
-}
-#endif
-
-
-#if defined(DDXBEFORERESET)
-/*
- * Called right before KillAllClients when the server is going to reset,
- * allows us to shutdown our seperate threads cleanly.
- */
-
-void
-ddxBeforeReset (void)
-{
- winDebug ("ddxBeforeReset - Hello\n");
-
-#ifdef XWIN_CLIPBOARD
- winClipboardShutdown ();
-#endif
-}
-#endif
-
-
-/* See Porting Layer Definition - p. 57 */
-void
-ddxGiveUp (void)
-{
- int i;
-
- winDebug ("ddxGiveUp\n");
-
- /* Perform per-screen deinitialization */
- for (i = 0; i < g_iNumScreens; ++i)
- {
- /* Delete the tray icon */
- if (!g_ScreenInfo[i].fNoTrayIcon && g_ScreenInfo[i].pScreen)
- winDeleteNotifyIcon (winGetScreenPriv (g_ScreenInfo[i].pScreen));
- }
-
-#ifdef XWIN_MULTIWINDOW
- /* Notify the worker threads we're exiting */
- winDeinitMultiWindowWM ();
-#endif
-
-#ifdef HAS_DEVWINDOWS
- /* Close our handle to our message queue */
- if (g_fdMessageQueue != WIN_FD_INVALID)
- {
- /* Close /dev/windows */
- close (g_fdMessageQueue);
-
- /* Set the file handle to invalid */
- g_fdMessageQueue = WIN_FD_INVALID;
- }
-#endif
-
- if (!g_fLogInited) {
- g_pszLogFile = LogInit (g_pszLogFile, NULL);
- g_fLogInited = TRUE;
- }
- LogClose ();
-
- /*
- * At this point we aren't creating any new screens, so
- * we are guaranteed to not need the DirectDraw functions.
- */
- if (g_hmodDirectDraw != NULL)
- {
- FreeLibrary (g_hmodDirectDraw);
- g_hmodDirectDraw = NULL;
- g_fpDirectDrawCreate = NULL;
- g_fpDirectDrawCreateClipper = NULL;
- }
-
- /* Unload our TrackMouseEvent funtion pointer */
- if (g_hmodCommonControls != NULL)
- {
- FreeLibrary (g_hmodCommonControls);
- g_hmodCommonControls = NULL;
- g_fpTrackMouseEvent = (FARPROC) (void (*)(void))NoopDDA;
- }
-
- /* Free concatenated command line */
- if (g_pszCommandLine)
- {
- free (g_pszCommandLine);
- g_pszCommandLine = NULL;
- }
-
- /* Remove our keyboard hook if it is installed */
- winRemoveKeyboardHookLL ();
-
- /* Tell Windows that we want to end the app */
- PostQuitMessage (0);
-}
-
-
-/* See Porting Layer Definition - p. 57 */
-void
-AbortDDX (void)
-{
- winDebug ("AbortDDX\n");
- ddxGiveUp ();
-}
-
-#ifdef __CYGWIN__
-/* hasmntopt is currently not implemented for cygwin */
-static const char *winCheckMntOpt(const struct mntent *mnt, const char *opt)
-{
- const char *s;
- size_t len;
- if (mnt == NULL)
- return NULL;
- if (opt == NULL)
- return NULL;
- if (mnt->mnt_opts == NULL)
- return NULL;
-
- len = strlen(opt);
- s = strstr(mnt->mnt_opts, opt);
- if (s == NULL)
- return NULL;
- if ((s == mnt->mnt_opts || *(s-1) == ',') && (s[len] == 0 || s[len] == ','))
- return (char *)opt;
- return NULL;
-}
-
-static void
-winCheckMount(void)
-{
- FILE *mnt;
- struct mntent *ent;
-
- enum { none = 0, sys_root, user_root, sys_tmp, user_tmp }
- level = none, curlevel;
- BOOL binary = TRUE;
-
- mnt = setmntent("/etc/mtab", "r");
- if (mnt == NULL)
- {
- ErrorF("setmntent failed");
- return;
- }
-
- while ((ent = getmntent(mnt)) != NULL)
- {
- BOOL system = (winCheckMntOpt(ent, "user") != NULL);
- BOOL root = (strcmp(ent->mnt_dir, "/") == 0);
- BOOL tmp = (strcmp(ent->mnt_dir, "/tmp") == 0);
-
- if (system)
- {
- if (root)
- curlevel = sys_root;
- else if (tmp)
- curlevel = sys_tmp;
- else
- continue;
- }
- else
- {
- if (root)
- curlevel = user_root;
- else if (tmp)
- curlevel = user_tmp;
- else
- continue;
- }
-
- if (curlevel <= level)
- continue;
- level = curlevel;
-
- if ((winCheckMntOpt(ent, "binary") == NULL) &&
- (winCheckMntOpt(ent, "binmode") == NULL))
- binary = FALSE;
- else
- binary = TRUE;
- }
-
- if (endmntent(mnt) != 1)
- {
- ErrorF("endmntent failed");
- return;
- }
-
-#ifdef WINDBG
- if (!binary)
- winDebug("/tmp mounted in textmode\n");
-#endif
-}
-#else
-static void
-winCheckMount(void)
-{
-}
-#endif
-
-#ifdef RELOCATE_PROJECTROOT
-const char *
-winGetBaseDir(void)
-{
- static BOOL inited = FALSE;
- static char buffer[MAX_PATH];
- if (!inited)
- {
- char *fendptr;
- HMODULE module = GetModuleHandle(NULL);
- DWORD size = GetModuleFileName(module, buffer, sizeof(buffer));
- if (sizeof(buffer) > 0)
- buffer[sizeof(buffer)-1] = 0;
-
- fendptr = buffer + size;
- while (fendptr > buffer)
- {
- if (*fendptr == '\\' || *fendptr == '/')
- {
- *fendptr = 0;
- break;
- }
- fendptr--;
- }
- inited = TRUE;
- }
- return buffer;
-}
-#endif
-
-static void
-winFixupPaths (void)
-{
- BOOL changed_fontpath = FALSE;
- MessageType font_from = X_DEFAULT;
-#ifdef RELOCATE_PROJECTROOT
- const char *basedir = winGetBaseDir();
- size_t basedirlen = strlen(basedir);
-#endif
-
-#ifdef READ_FONTDIRS
- {
- /* Open fontpath configuration file */
-#if defined WIN32 && defined __MINGW32__
- static Bool once = False;
- char buffer[MAX_PATH];
- snprintf(buffer, sizeof(buffer), "%s\\font-dirs", basedir);
- buffer[sizeof(buffer)-1] = 0;
- FILE *fontdirs = fopen(buffer, "rt");
- if (once) fontdirs = NULL;
- else once = True;
-#else
- FILE *fontdirs = fopen(ETCX11DIR "/font-dirs", "rt");
-#endif
- if (fontdirs != NULL)
- {
- char buffer[256];
- int needs_sep = TRUE;
- int comment_block = FALSE;
-
- /* get defautl fontpath */
- char *fontpath = xstrdup(defaultFontPath);
- size_t size = strlen(fontpath);
-
- /* read all lines */
- while (!feof(fontdirs))
- {
- size_t blen;
- char *hashchar;
- char *str;
- int has_eol = FALSE;
-
- /* read one line */
- str = fgets(buffer, sizeof(buffer), fontdirs);
- if (str == NULL) /* stop on error or eof */
- break;
-
- if (strchr(str, '\n') != NULL)
- has_eol = TRUE;
-
- /* check if block is continued comment */
- if (comment_block)
- {
- /* ignore all input */
- *str = 0;
- blen = 0;
- if (has_eol) /* check if line ended in this block */
- comment_block = FALSE;
- }
- else
- {
- /* find comment character. ignore all trailing input */
- hashchar = strchr(str, '#');
- if (hashchar != NULL)
- {
- *hashchar = 0;
- if (!has_eol) /* mark next block as continued comment */
- comment_block = TRUE;
- }
- }
-
- /* strip whitespaces from beginning */
- while (*str == ' ' || *str == '\t')
- str++;
-
- /* get size, strip whitespaces from end */
- blen = strlen(str);
- while (blen > 0 && (str[blen-1] == ' ' ||
- str[blen-1] == '\t' || str[blen-1] == '\n'))
- {
- str[--blen] = 0;
- }
-
- /* still something left to add? */
- if (blen > 0)
- {
- size_t newsize = size + blen;
- /* reserve one character more for ',' */
- if (needs_sep)
- newsize++;
-
- /* allocate memory */
- if (fontpath == NULL)
- fontpath = malloc(newsize+1);
- else
- fontpath = realloc(fontpath, newsize+1);
-
- /* add separator */
- if (needs_sep)
- {
- fontpath[size] = ',';
- size++;
- needs_sep = FALSE;
- }
-
- /* mark next line as new entry */
- if (has_eol)
- needs_sep = TRUE;
-
- /* add block */
- strncpy(fontpath + size, str, blen);
- fontpath[newsize] = 0;
- size = newsize;
- }
- }
-
- /* cleanup */
- fclose(fontdirs);
- defaultFontPath = xstrdup(fontpath);
- free(fontpath);
- changed_fontpath = TRUE;
- font_from = X_CONFIG;
- }
- }
-#endif /* READ_FONTDIRS */
-#ifdef RELOCATE_PROJECTROOT
- {
- const char *libx11dir = PROJECTROOT "/lib/X11";
- size_t libx11dir_len = strlen(libx11dir);
- char *newfp = NULL;
- size_t newfp_len = 0;
- const char *endptr, *ptr, *oldptr = defaultFontPath;
-
- endptr = oldptr + strlen(oldptr);
- ptr = strchr(oldptr, ',');
- if (ptr == NULL)
- ptr = endptr;
- while (ptr != NULL)
- {
- size_t oldfp_len = (ptr - oldptr);
- size_t newsize = oldfp_len;
- char *newpath = malloc(newsize + 1);
- strncpy(newpath, oldptr, newsize);
- newpath[newsize] = 0;
-
-
- if (strncmp(libx11dir, newpath, libx11dir_len) == 0)
- {
- char *compose;
- newsize = newsize - libx11dir_len + basedirlen;
- compose = malloc(newsize + 1);
- strcpy(compose, basedir);
- strncat(compose, newpath + libx11dir_len, newsize - basedirlen);
- compose[newsize] = 0;
- free(newpath);
- newpath = compose;
- }
-
- oldfp_len = newfp_len;
- if (oldfp_len > 0)
- newfp_len ++; /* space for separator */
- newfp_len += newsize;
-
- if (newfp == NULL)
- newfp = malloc(newfp_len + 1);
- else
- newfp = realloc(newfp, newfp_len + 1);
-
- if (oldfp_len > 0)
- {
- strcpy(newfp + oldfp_len, ",");
- oldfp_len++;
- }
- strcpy(newfp + oldfp_len, newpath);
-
- free(newpath);
-
- if (*ptr == 0)
- {
- oldptr = ptr;
- ptr = NULL;
- } else
- {
- oldptr = ptr + 1;
- ptr = strchr(oldptr, ',');
- if (ptr == NULL)
- ptr = endptr;
- }
- }
-
- defaultFontPath = xstrdup(newfp);
- free(newfp);
- changed_fontpath = TRUE;
- }
-#endif /* RELOCATE_PROJECTROOT */
- if (changed_fontpath)
- winDebug ("FontPath set to \"%s\"\n", defaultFontPath);
-
-#ifdef RELOCATE_PROJECTROOT
- if (getenv("XKEYSYMDB") == NULL)
- {
- char buffer[MAX_PATH];
- snprintf(buffer, sizeof(buffer), "XKEYSYMDB=%s\\XKeysymDB",
- basedir);
- buffer[sizeof(buffer)-1] = 0;
- putenv(buffer);
- }
- if (getenv("XERRORDB") == NULL)
- {
- char buffer[MAX_PATH];
- snprintf(buffer, sizeof(buffer), "XERRORDB=%s\\XErrorDB",
- basedir);
- buffer[sizeof(buffer)-1] = 0;
- putenv(buffer);
- }
- if (getenv("XLOCALEDIR") == NULL)
- {
- char buffer[MAX_PATH];
- snprintf(buffer, sizeof(buffer), "XLOCALEDIR=%s\\locale",
- basedir);
- buffer[sizeof(buffer)-1] = 0;
- putenv(buffer);
- }
- if (getenv("XHOSTPREFIX") == NULL)
- {
- char buffer[MAX_PATH];
- snprintf(buffer, sizeof(buffer), "XHOSTPREFIX=%s\\X",
- basedir);
- buffer[sizeof(buffer)-1] = 0;
- putenv(buffer);
- }
- if (getenv("HOME") == NULL)
- {
- HMODULE shfolder;
- SHGETFOLDERPATHPROC shgetfolderpath = NULL;
- char buffer[MAX_PATH + 5];
- strncpy(buffer, "HOME=", 5);
-
- /* Try to load SHGetFolderPath from shfolder.dll and shell32.dll */
-
- shfolder = LoadLibrary("shfolder.dll");
- /* fallback to shell32.dll */
- if (shfolder == NULL)
- shfolder = LoadLibrary("shell32.dll");
-
- /* resolve SHGetFolderPath */
- if (shfolder != NULL)
- shgetfolderpath = (SHGETFOLDERPATHPROC)GetProcAddress(shfolder, "SHGetFolderPathA");
-
- /* query appdata directory */
- if (shgetfolderpath &&
- shgetfolderpath(NULL, CSIDL_APPDATA|CSIDL_FLAG_CREATE, NULL, 0,
- buffer + 5) == 0)
- {
- putenv(buffer);
- } else
- {
- ErrorF ("Can not determine HOME directory\n");
- }
- if (shfolder != NULL)
- FreeLibrary(shfolder);
- }
- if (!g_fLogFileChanged) {
- static char buffer[MAX_PATH];
- DWORD size = GetTempPath(sizeof(buffer), buffer);
- if (size && size < sizeof(buffer))
- {
- snprintf(buffer + size, sizeof(buffer) - size,
- "VCXSrv.%s.log", display);
- buffer[sizeof(buffer)-1] = 0;
- g_pszLogFile = buffer;
- GetLongPathName(buffer, buffer, MAX_PATH);
- winDebug ("Logfile set to \"%s\"\n", g_pszLogFile);
- }
- }
- {
- static char xkbbasedir[MAX_PATH];
-
- snprintf(xkbbasedir, sizeof(xkbbasedir), "%s\\xkbdata", basedir);
- if (sizeof(xkbbasedir) > 0)
- xkbbasedir[sizeof(xkbbasedir)-1] = 0;
- XkbBaseDirectory = xkbbasedir;
- XkbBinDirectory = basedir;
- }
-#endif /* RELOCATE_PROJECTROOT */
-}
-
-void
-OsVendorInit (void)
-{
- /* Re-initialize global variables on server reset */
- winInitializeGlobals ();
-
- winFixupPaths();
-
-#ifdef DDXOSVERRORF
- if (!OsVendorVErrorFProc)
- OsVendorVErrorFProc = OsVendorVErrorF;
-#endif
-
- if (!g_fLogInited) {
- /* keep this order. If LogInit fails it calls Abort which then calls
- * ddxGiveUp where LogInit is called again and creates an infinite
- * recursion. If we set g_fLogInited to TRUE before the init we
- * avoid the second call
- */
- g_fLogInited = TRUE;
- g_pszLogFile = LogInit (g_pszLogFile, NULL);
- }
- LogSetParameter (XLOG_FLUSH, 1);
- LogSetParameter (XLOG_VERBOSITY, g_iLogVerbose);
- LogSetParameter (XLOG_FILE_VERBOSITY, g_iLogVerbose);
-
- /* Log the version information */
- if (serverGeneration == 1)
- winLogVersionInfo ();
-
- winCheckMount();
-
- /* Add a default screen if no screens were specified */
- if (g_iNumScreens == 0)
- {
- winDebug ("OsVendorInit - Creating bogus screen 0\n");
-
- /*
- * We need to initialize default screens if no arguments
- * were processed. Otherwise, the default screens would
- * already have been initialized by ddxProcessArgument ().
- */
- winInitializeDefaultScreens ();
-
- /*
- * Add a screen 0 using the defaults set by
- * winInitializeDefaultScreens () and any additional parameters
- * processed by ddxProcessArgument ().
- */
- g_iNumScreens = 1;
- g_iLastScreen = 0;
-
- /* We have to flag this as an explicit screen, even though it isn't */
- g_ScreenInfo[0].fExplicitScreen = TRUE;
- }
-}
-
-
-static void
-winUseMsg (void)
-{
- ErrorF("\n");
- ErrorF("\n");
- ErrorF(EXECUTABLE_NAME " Device Dependent Usage:\n");
- ErrorF("\n");
-
-#ifdef XWIN_CLIPBOARD
- ErrorF ("-[no]clipboard\n"
- "\tEnable [disable] the clipboard integration. Default is enabled.\n");
-#endif
-
- ErrorF ("-clipupdates num_boxes\n"
- "\tUse a clipping region to constrain shadow update blits to\n"
- "\tthe updated region when num_boxes, or more, are in the\n"
- "\tupdated region.\n");
-
-#ifdef XWIN_XF86CONFIG
- ErrorF ("-config\n"
- "\tSpecify a configuration file.\n");
-
- ErrorF ("-configdir\n"
- "\tSpecify a configuration directory.\n");
-#endif
-
- ErrorF ("-depth bits_per_pixel\n"
- "\tSpecify an optional bitdepth to use in fullscreen mode\n"
- "\twith a DirectDraw engine.\n");
-
- ErrorF ("-emulate3buttons [timeout]\n"
- "\tEmulate 3 button mouse with an optional timeout in\n"
- "\tmilliseconds.\n");
-
-#ifdef XWIN_EMULATEPSEUDO
- ErrorF ("-emulatepseudo\n"
- "\tCreate a depth 8 PseudoColor visual when running in\n"
- "\tdepths 15, 16, 24, or 32, collectively known as TrueColor\n"
- "\tdepths. The PseudoColor visual does not have correct colors,\n"
- "\tand it may crash, but it at least allows you to run your\n"
- "\tapplication in TrueColor modes.\n");
-#endif
-
- ErrorF ("-engine engine_type_id\n"
- "\tOverride the server's automatically selected engine type:\n"
- "\t\t1 - Shadow GDI\n"
- "\t\t2 - Shadow DirectDraw\n"
- "\t\t4 - Shadow DirectDraw4 Non-Locking\n"
-#ifdef XWIN_PRIMARYFB
- "\t\t8 - Primary DirectDraw\n"
-#endif
-#ifdef XWIN_NATIVEGDI
- "\t\t16 - Native GDI - experimental\n"
-#endif
- );
-
- ErrorF ("-fullscreen\n"
- "\tRun the server in fullscreen mode.\n");
-
- ErrorF ("-ignoreinput\n"
- "\tIgnore keyboard and mouse input.\n");
-
-#ifdef XWIN_MULTIWINDOWEXTWM
- ErrorF ("-internalwm\n"
- "\tRun the internal window manager.\n");
-#endif
-
-#ifdef XWIN_XF86CONFIG
- ErrorF ("-keyboard\n"
- "\tSpecify a keyboard device from the configuration file.\n");
-#endif
-
- ErrorF ("-[no]keyhook\n"
- "\tGrab special Windows keypresses like Alt-Tab or the Menu "
- "key.\n");
-
- ErrorF ("-lesspointer\n"
- "\tHide the windows mouse pointer when it is over any\n"
- "\t" EXECUTABLE_NAME " window. This prevents ghost cursors appearing when\n"
- "\tthe Windows cursor is drawn on top of the X cursor\n");
-
- ErrorF ("-logfile filename\n"
- "\tWrite log messages to <filename>.\n");
-
- ErrorF ("-logverbose verbosity\n"
- "\tSet the verbosity of log messages. [NOTE: Only a few messages\n"
- "\trespect the settings yet]\n"
- "\t\t0 - only print fatal error.\n"
- "\t\t1 - print additional configuration information.\n"
- "\t\t2 - print additional runtime information [default].\n"
- "\t\t3 - print debugging and tracing information.\n");
-
- ErrorF ("-[no]multimonitors or -[no]multiplemonitors\n"
- "\tUse the entire virtual screen if multiple\n"
- "\tmonitors are present.\n");
-
-#ifdef XWIN_MULTIWINDOW
- ErrorF ("-multiwindow\n"
- "\tRun the server in multi-window mode.\n");
-#endif
-
-#ifdef XWIN_MULTIWINDOWEXTWM
- ErrorF ("-mwextwm\n"
- "\tRun the server in multi-window external window manager mode.\n");
-#endif
-
- ErrorF ("-nodecoration\n"
- "\tDo not draw a window border, title bar, etc. Windowed\n"
- "\tmode only.\n");
-
-#ifdef XWIN_CLIPBOARD
- ErrorF ("-nounicodeclipboard\n"
- "\tDo not use Unicode clipboard even if on a NT-based platform.\n");
-#endif
-
- ErrorF ("-refresh rate_in_Hz\n"
- "\tSpecify an optional refresh rate to use in fullscreen mode\n"
- "\twith a DirectDraw engine.\n");
-
- ErrorF ("-rootless\n"
- "\tRun the server in rootless mode.\n");
-
- ErrorF ("-screen scr_num [width height [x y] | [[WxH[+X+Y]][@m]] ]\n"
- "\tEnable screen scr_num and optionally specify a width and\n"
- "\theight and initial position for that screen. Additionally\n"
- "\ta monitor number can be specified to start the server on,\n"
- "\tat which point, all coordinates become relative to that\n"
- "\tmonitor (Not for Windows NT4 and 95). Examples:\n"
- "\t -screen 0 800x600+100+100@2 ; 2nd monitor offset 100,100 size 800x600\n"
- "\t -screen 0 1024x768@3 ; 3rd monitor size 1024x768\n"
- "\t -screen 0 @1 ; on 1st monitor using its full resolution (the default)\n");
-
- ErrorF ("-scrollbars\n"
- "\tIn windowed mode, allow screens bigger than the Windows desktop.\n"
- "\tMoreover, if the window has decorations, one can now resize\n"
- "\tit.\n");
-
- ErrorF ("-silent-dup-error\n"
- "\tIf another instance of " EXECUTABLE_NAME " with the same display number is running\n"
- "\texit silently and don’t display any error message.\n");
-
- ErrorF ("-swcursor\n"
- "\tDisable the usage of the Windows cursor and use the X11 software\n"
- "\tcursor instead.\n");
-
- ErrorF ("-[no]trayicon\n"
- "\tDo not create a tray icon. Default is to create one\n"
- "\ticon per screen. You can globally disable tray icons with\n"
- "\t-notrayicon, then enable it for specific screens with\n"
- "\t-trayicon for those screens.\n");
-
- ErrorF ("-[no]unixkill\n"
- "\tCtrl+Alt+Backspace exits the X Server.\n");
-
-#ifdef XWIN_GLX_WINDOWS
- ErrorF ("-[no]wgl\n"
- "\tEnable the GLX extension to use the native Windows WGL interface for accelerated OpenGL\n");
-#endif
-
- ErrorF ("-[no]winkill\n"
- "\tAlt+F4 exits the X Server.\n");
-
- ErrorF ("-xkblayout XKBLayout\n"
- "\tEquivalent to XKBLayout in XF86Config files.\n"
- "\tFor example: -xkblayout de\n");
-
- ErrorF ("-xkbmodel XKBModel\n"
- "\tEquivalent to XKBModel in XF86Config files.\n");
-
- ErrorF ("-xkboptions XKBOptions\n"
- "\tEquivalent to XKBOptions in XF86Config files.\n");
-
- ErrorF ("-xkbrules XKBRules\n"
- "\tEquivalent to XKBRules in XF86Config files.\n");
-
- ErrorF ("-xkbvariant XKBVariant\n"
- "\tEquivalent to XKBVariant in XF86Config files.\n"
- "\tFor example: -xkbvariant nodeadkeys\n");
-}
-
-/* See Porting Layer Definition - p. 57 */
-void
-ddxUseMsg(void)
-{
- /* Set a flag so that FatalError won't give duplicate warning message */
- g_fSilentFatalError = TRUE;
-
- winUseMsg();
-
- /* Log file will not be opened for UseMsg unless we open it now */
- if (!g_fLogInited) {
- g_pszLogFile = LogInit (g_pszLogFile, NULL);
- g_fLogInited = TRUE;
- }
- LogClose ();
-
- /* Notify user where UseMsg text can be found.*/
- if (!g_fNoHelpMessageBox)
- winMessageBoxF ("The " PROJECT_NAME " help text has been printed to "
- "%s.\n"
- "Please open %s to read the help text.\n",
- MB_ICONINFORMATION, g_pszLogFile, g_pszLogFile);
-}
-
-/* See Porting Layer Definition - p. 20 */
-/*
- * Do any global initialization, then initialize each screen.
- *
- * NOTE: We use ddxProcessArgument, so we don't need to touch argc and argv
- */
-
-void
-InitOutput (ScreenInfo *screenInfo, int argc, char *argv[])
-{
- int i;
-
- /* Log the command line */
- winLogCommandLine (argc, argv);
-
- winDebug ("InitOutput\n");
-
- /* Validate command-line arguments */
- if (serverGeneration == 1 && !winValidateArgs ())
- {
- FatalError ("InitOutput - Invalid command-line arguments found. "
- "Exiting.\n");
- }
-
- /* Check for duplicate invocation on same display number.*/
- if (serverGeneration == 1 && !winCheckDisplayNumber ())
- {
- if (g_fSilentDupError)
- g_fSilentFatalError = TRUE;
- FatalError ("InitOutput - Duplicate invocation on display "
- "number: %s. Exiting.\n", display);
- }
-
-#ifdef XWIN_XF86CONFIG
- /* Try to read the xorg.conf-style configuration file */
- if (!winReadConfigfile ())
- ErrorF ("InitOutput - Error reading config file\n");
-#else
- winConfigFiles ();
-#endif
-
- /* Load preferences from XWinrc file */
- LoadPreferences();
-
- /* Setup global screen info parameters */
- screenInfo->imageByteOrder = IMAGE_BYTE_ORDER;
- screenInfo->bitmapScanlinePad = BITMAP_SCANLINE_PAD;
- screenInfo->bitmapScanlineUnit = BITMAP_SCANLINE_UNIT;
- screenInfo->bitmapBitOrder = BITMAP_BIT_ORDER;
- screenInfo->numPixmapFormats = NUMFORMATS;
-
- /* Describe how we want common pixmap formats padded */
- for (i = 0; i < NUMFORMATS; i++)
- {
- screenInfo->formats[i] = g_PixmapFormats[i];
- }
-
- /* Load pointers to DirectDraw functions */
- winGetDDProcAddresses ();
-
- /* Detect supported engines */
- winDetectSupportedEngines ();
-
- /* Load common controls library */
- g_hmodCommonControls = LoadLibraryEx ("comctl32.dll", NULL, 0);
-
- /* Load TrackMouseEvent function pointer */
- g_fpTrackMouseEvent = GetProcAddress (g_hmodCommonControls,
- "_TrackMouseEvent");
- if (g_fpTrackMouseEvent == NULL)
- {
- ErrorF ("InitOutput - Could not get pointer to function\n"
- "\t_TrackMouseEvent in comctl32.dll. Try installing\n"
- "\tInternet Explorer 3.0 or greater if you have not\n"
- "\talready.\n");
-
- /* Free the library since we won't need it */
- FreeLibrary (g_hmodCommonControls);
- g_hmodCommonControls = NULL;
-
- /* Set function pointer to point to no operation function */
- g_fpTrackMouseEvent = (FARPROC) (void (*)(void))NoopDDA;
- }
-
- /* Store the instance handle */
- g_hInstance = GetModuleHandle (NULL);
-
- /* Initialize each screen */
- for (i = 0; i < g_iNumScreens; ++i)
- {
- /* Initialize the screen */
- if (-1 == AddScreen (winScreenInit, argc, argv))
- {
- FatalError ("InitOutput - Couldn't add screen %d", i);
- }
- }
-
-#if defined(XWIN_CLIPBOARD) || defined(XWIN_MULTIWINDOW)
-
- /* Generate a cookie used by internal clients for authorization */
- if (g_fXdmcpEnabled || g_fAuthEnabled)
- winGenerateAuthorization ();
-
- /* Perform some one time initialization */
- if (1 == serverGeneration)
- {
- /*
- * setlocale applies to all threads in the current process.
- * Apply locale specified in LANG environment variable.
- */
- setlocale (LC_ALL, "");
-
- glx_debugging();
- }
-#endif
-
- winDebug ("InitOutput - Returning.\n");
-}
-
-
-/*
- * winCheckDisplayNumber - Check if another instance of Cygwin/X is
- * already running on the same display number. If no one exists,
- * make a mutex to prevent new instances from running on the same display.
- *
- * return FALSE if the display number is already used.
- */
-
-static Bool
-winCheckDisplayNumber (void)
-{
- int nDisp;
- HANDLE mutex;
- char name[MAX_PATH];
- char * pszPrefix = '\0';
- OSVERSIONINFO osvi = {0};
-
- /* Check display range */
- nDisp = atoi (display);
- if (nDisp < 0 || nDisp > 59535)
- {
- ErrorF ("winCheckDisplayNumber - Bad display number: %d\n", nDisp);
- return FALSE;
- }
-
- /* Set first character of mutex name to null */
- name[0] = '\0';
-
- /* Get operating system version information */
- osvi.dwOSVersionInfoSize = sizeof (osvi);
- GetVersionEx (&osvi);
-
- /* Want a mutex shared among all terminals on NT > 4.0 */
- if (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT
- && osvi.dwMajorVersion >= 5)
- {
- pszPrefix = "Global\\";
- }
-
- /* Setup Cygwin/X specific part of name */
- snprintf (name, sizeof(name), "%sCYGWINX_DISPLAY:%d", pszPrefix, nDisp);
-
- /* Windows automatically releases the mutex when this process exits */
- mutex = CreateMutex (NULL, FALSE, name);
- if (!mutex)
- {
- LPVOID lpMsgBuf;
-
- /* Display a fancy error message */
- FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER |
- FORMAT_MESSAGE_FROM_SYSTEM |
- FORMAT_MESSAGE_IGNORE_INSERTS,
- NULL,
- GetLastError (),
- MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
- (LPTSTR) &lpMsgBuf,
- 0, NULL);
- ErrorF ("winCheckDisplayNumber - CreateMutex failed: %s\n",
- (LPSTR)lpMsgBuf);
- LocalFree (lpMsgBuf);
-
- return FALSE;
- }
- if (GetLastError () == ERROR_ALREADY_EXISTS)
- {
- ErrorF ("winCheckDisplayNumber - "
- "VCXsrv, Xming or Cygwin/X is already running on display %d\n",
- nDisp);
- return FALSE;
- }
-
- return TRUE;
-}
-
-/* GLX debugging helpers */
-#include <../glx/glapi.h>
-
-static
-void warn_func(void * p1, const char *format, ...) {
- va_list v;
- va_start(v, format);
- vfprintf(stderr, format, v);
- va_end(v);
- fprintf(stderr,"\n");
-}
-
-static
-void glx_debugging(void)
-{
- _glapi_set_warning_func(warn_func);
- _glapi_noop_enable_warnings(TRUE);
-}
+ +/* + +Copyright 1993, 1998 The Open Group +Copyright (C) Colin Harrison 2005-2008 + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. + +*/ + +#ifdef HAVE_XWIN_CONFIG_H +#include <xwin-config.h> +#endif +#include "win.h" +#include "winmsg.h" +#include "winconfig.h" +#include "winprefs.h" +#ifdef XWIN_CLIPBOARD +#include "X11/Xlocale.h" +#endif +#ifdef DPMSExtension +#include "dpmsproc.h" +#endif +#ifdef __CYGWIN__ +#include <mntent.h> +#endif +#if defined(WIN32) +#include "xkbsrv.h" +#endif +#ifdef RELOCATE_PROJECTROOT +#undef Status +#include <shlobj.h> +typedef HRESULT (__stdcall * SHGETFOLDERPATHPROC)( + HWND hwndOwner, + int nFolder, + HANDLE hToken, + DWORD dwFlags, + LPSTR pszPath +); +#endif + + +/* + * References to external symbols + */ + +extern int g_iNumScreens; +extern winScreenInfo * g_ScreenInfo; +extern char * g_pszCommandLine; +extern Bool g_fSilentFatalError; + +extern const char * g_pszLogFile; +extern Bool g_fLogFileChanged; +extern int g_iLogVerbose; +Bool g_fLogInited; + +extern Bool g_fXdmcpEnabled; +extern Bool g_fAuthEnabled; +#ifdef HAS_DEVWINDOWS +extern int g_fdMessageQueue; +#endif +extern const char * g_pszQueryHost; +extern HINSTANCE g_hInstance; + +#ifdef XWIN_CLIPBOARD +extern Bool g_fUnicodeClipboard; +extern Bool g_fClipboardLaunched; +extern Bool g_fClipboardStarted; +extern pthread_t g_ptClipboardProc; +extern HWND g_hwndClipboard; +extern Bool g_fClipboard; +#endif + +extern HMODULE g_hmodDirectDraw; +extern FARPROC g_fpDirectDrawCreate; +extern FARPROC g_fpDirectDrawCreateClipper; + +extern HMODULE g_hmodCommonControls; +extern FARPROC g_fpTrackMouseEvent; +extern Bool g_fNoHelpMessageBox; +extern Bool g_fSilentDupError; +extern Bool g_fNativeGl; + +/* + * Function prototypes + */ + +#ifdef XWIN_CLIPBOARD +static void +winClipboardShutdown (void); +#endif + +#if defined(DDXOSVERRORF) +void +OsVendorVErrorF (const char *pszFormat, va_list va_args); +#endif + +static Bool +winCheckDisplayNumber (void); + +void +winLogCommandLine (int argc, char *argv[]); + +void +winLogVersionInfo (void); + +Bool +winValidateArgs (void); + +#ifdef RELOCATE_PROJECTROOT +const char * +winGetBaseDir(void); +#endif + +static +void glx_debugging(void); + +/* + * For the depth 24 pixmap we default to 32 bits per pixel, but + * we change this pixmap format later if we detect that the display + * is going to be running at 24 bits per pixel. + * + * FIXME: On second thought, don't DIBs only support 32 bits per pixel? + * DIBs are the underlying bitmap used for DirectDraw surfaces, so it + * seems that all pixmap formats with depth 24 would be 32 bits per pixel. + * Confirm whether depth 24 DIBs can have 24 bits per pixel, then remove/keep + * the bits per pixel adjustment and update this comment to reflect the + * situation. Harold Hunt - 2002/07/02 + */ + +static PixmapFormatRec g_PixmapFormats[] = { + { 1, 1, BITMAP_SCANLINE_PAD }, + { 4, 8, BITMAP_SCANLINE_PAD }, + { 8, 8, BITMAP_SCANLINE_PAD }, + { 15, 16, BITMAP_SCANLINE_PAD }, + { 16, 16, BITMAP_SCANLINE_PAD }, + { 24, 32, BITMAP_SCANLINE_PAD }, + { 32, 32, BITMAP_SCANLINE_PAD } +}; + +const int NUMFORMATS = sizeof (g_PixmapFormats) / sizeof (g_PixmapFormats[0]); + +#ifdef XWIN_CLIPBOARD +static void +winClipboardShutdown (void) +{ + /* Close down clipboard resources */ + if (g_fClipboard && g_fClipboardLaunched && g_fClipboardStarted) + { + /* Synchronously destroy the clipboard window */ + if (g_hwndClipboard != NULL) + { + SendMessage (g_hwndClipboard, WM_DESTROY, 0, 0); + /* NOTE: g_hwndClipboard is set to NULL in winclipboardthread.c */ + } + else + return; + + /* Wait for the clipboard thread to exit */ + pthread_join (g_ptClipboardProc, NULL); + + winDebug ("winClipboardShutdown - Clipboard thread has exited.\n"); + } +} +#endif + + +#if defined(DDXBEFORERESET) +/* + * Called right before KillAllClients when the server is going to reset, + * allows us to shutdown our seperate threads cleanly. + */ + +void +ddxBeforeReset (void) +{ + winDebug ("ddxBeforeReset - Hello\n"); + +#ifdef XWIN_CLIPBOARD + winClipboardShutdown (); +#endif +} +#endif + + +/* See Porting Layer Definition - p. 57 */ +void +ddxGiveUp (void) +{ + int i; + + winDebug ("ddxGiveUp\n"); + + /* Perform per-screen deinitialization */ + for (i = 0; i < g_iNumScreens; ++i) + { + /* Delete the tray icon */ + if (!g_ScreenInfo[i].fNoTrayIcon && g_ScreenInfo[i].pScreen) + winDeleteNotifyIcon (winGetScreenPriv (g_ScreenInfo[i].pScreen)); + } + +#ifdef XWIN_MULTIWINDOW + /* Notify the worker threads we're exiting */ + winDeinitMultiWindowWM (); +#endif + +#ifdef HAS_DEVWINDOWS + /* Close our handle to our message queue */ + if (g_fdMessageQueue != WIN_FD_INVALID) + { + /* Close /dev/windows */ + close (g_fdMessageQueue); + + /* Set the file handle to invalid */ + g_fdMessageQueue = WIN_FD_INVALID; + } +#endif + + if (!g_fLogInited) { + g_pszLogFile = LogInit (g_pszLogFile, NULL); + g_fLogInited = TRUE; + } + LogClose (); + + /* + * At this point we aren't creating any new screens, so + * we are guaranteed to not need the DirectDraw functions. + */ + if (g_hmodDirectDraw != NULL) + { + FreeLibrary (g_hmodDirectDraw); + g_hmodDirectDraw = NULL; + g_fpDirectDrawCreate = NULL; + g_fpDirectDrawCreateClipper = NULL; + } + + /* Unload our TrackMouseEvent funtion pointer */ + if (g_hmodCommonControls != NULL) + { + FreeLibrary (g_hmodCommonControls); + g_hmodCommonControls = NULL; + g_fpTrackMouseEvent = (FARPROC) (void (*)(void))NoopDDA; + } + + /* Free concatenated command line */ + if (g_pszCommandLine) + { + free (g_pszCommandLine); + g_pszCommandLine = NULL; + } + + /* Remove our keyboard hook if it is installed */ + winRemoveKeyboardHookLL (); + + /* Tell Windows that we want to end the app */ + PostQuitMessage (0); +} + + +/* See Porting Layer Definition - p. 57 */ +void +AbortDDX (void) +{ + winDebug ("AbortDDX\n"); + ddxGiveUp (); +} + +#ifdef __CYGWIN__ +/* hasmntopt is currently not implemented for cygwin */ +static const char *winCheckMntOpt(const struct mntent *mnt, const char *opt) +{ + const char *s; + size_t len; + if (mnt == NULL) + return NULL; + if (opt == NULL) + return NULL; + if (mnt->mnt_opts == NULL) + return NULL; + + len = strlen(opt); + s = strstr(mnt->mnt_opts, opt); + if (s == NULL) + return NULL; + if ((s == mnt->mnt_opts || *(s-1) == ',') && (s[len] == 0 || s[len] == ',')) + return (char *)opt; + return NULL; +} + +static void +winCheckMount(void) +{ + FILE *mnt; + struct mntent *ent; + + enum { none = 0, sys_root, user_root, sys_tmp, user_tmp } + level = none, curlevel; + BOOL binary = TRUE; + + mnt = setmntent("/etc/mtab", "r"); + if (mnt == NULL) + { + ErrorF("setmntent failed"); + return; + } + + while ((ent = getmntent(mnt)) != NULL) + { + BOOL system = (winCheckMntOpt(ent, "user") != NULL); + BOOL root = (strcmp(ent->mnt_dir, "/") == 0); + BOOL tmp = (strcmp(ent->mnt_dir, "/tmp") == 0); + + if (system) + { + if (root) + curlevel = sys_root; + else if (tmp) + curlevel = sys_tmp; + else + continue; + } + else + { + if (root) + curlevel = user_root; + else if (tmp) + curlevel = user_tmp; + else + continue; + } + + if (curlevel <= level) + continue; + level = curlevel; + + if ((winCheckMntOpt(ent, "binary") == NULL) && + (winCheckMntOpt(ent, "binmode") == NULL)) + binary = FALSE; + else + binary = TRUE; + } + + if (endmntent(mnt) != 1) + { + ErrorF("endmntent failed"); + return; + } + +#ifdef WINDBG + if (!binary) + winDebug("/tmp mounted in textmode\n"); +#endif +} +#else +static void +winCheckMount(void) +{ +} +#endif + +#ifdef RELOCATE_PROJECTROOT +const char * +winGetBaseDir(void) +{ + static BOOL inited = FALSE; + static char buffer[MAX_PATH]; + if (!inited) + { + char *fendptr; + HMODULE module = GetModuleHandle(NULL); + DWORD size = GetModuleFileName(module, buffer, sizeof(buffer)); + if (sizeof(buffer) > 0) + buffer[sizeof(buffer)-1] = 0; + + fendptr = buffer + size; + while (fendptr > buffer) + { + if (*fendptr == '\\' || *fendptr == '/') + { + *fendptr = 0; + break; + } + fendptr--; + } + inited = TRUE; + } + return buffer; +} +#endif + +static void +winFixupPaths (void) +{ + BOOL changed_fontpath = FALSE; + MessageType font_from = X_DEFAULT; +#ifdef RELOCATE_PROJECTROOT + const char *basedir = winGetBaseDir(); + size_t basedirlen = strlen(basedir); +#endif + +#ifdef READ_FONTDIRS + { + /* Open fontpath configuration file */ +#if defined WIN32 && defined __MINGW32__ + static Bool once = False; + char buffer[MAX_PATH]; + snprintf(buffer, sizeof(buffer), "%s\\font-dirs", basedir); + buffer[sizeof(buffer)-1] = 0; + FILE *fontdirs = fopen(buffer, "rt"); + if (once) fontdirs = NULL; + else once = True; +#else + FILE *fontdirs = fopen(ETCX11DIR "/font-dirs", "rt"); +#endif + if (fontdirs != NULL) + { + char buffer[256]; + int needs_sep = TRUE; + int comment_block = FALSE; + + /* get defautl fontpath */ + char *fontpath = xstrdup(defaultFontPath); + size_t size = strlen(fontpath); + + /* read all lines */ + while (!feof(fontdirs)) + { + size_t blen; + char *hashchar; + char *str; + int has_eol = FALSE; + + /* read one line */ + str = fgets(buffer, sizeof(buffer), fontdirs); + if (str == NULL) /* stop on error or eof */ + break; + + if (strchr(str, '\n') != NULL) + has_eol = TRUE; + + /* check if block is continued comment */ + if (comment_block) + { + /* ignore all input */ + *str = 0; + blen = 0; + if (has_eol) /* check if line ended in this block */ + comment_block = FALSE; + } + else + { + /* find comment character. ignore all trailing input */ + hashchar = strchr(str, '#'); + if (hashchar != NULL) + { + *hashchar = 0; + if (!has_eol) /* mark next block as continued comment */ + comment_block = TRUE; + } + } + + /* strip whitespaces from beginning */ + while (*str == ' ' || *str == '\t') + str++; + + /* get size, strip whitespaces from end */ + blen = strlen(str); + while (blen > 0 && (str[blen-1] == ' ' || + str[blen-1] == '\t' || str[blen-1] == '\n')) + { + str[--blen] = 0; + } + + /* still something left to add? */ + if (blen > 0) + { + size_t newsize = size + blen; + /* reserve one character more for ',' */ + if (needs_sep) + newsize++; + + /* allocate memory */ + if (fontpath == NULL) + fontpath = malloc(newsize+1); + else + fontpath = realloc(fontpath, newsize+1); + + /* add separator */ + if (needs_sep) + { + fontpath[size] = ','; + size++; + needs_sep = FALSE; + } + + /* mark next line as new entry */ + if (has_eol) + needs_sep = TRUE; + + /* add block */ + strncpy(fontpath + size, str, blen); + fontpath[newsize] = 0; + size = newsize; + } + } + + /* cleanup */ + fclose(fontdirs); + defaultFontPath = xstrdup(fontpath); + free(fontpath); + changed_fontpath = TRUE; + font_from = X_CONFIG; + } + } +#endif /* READ_FONTDIRS */ +#ifdef RELOCATE_PROJECTROOT + { + const char *libx11dir = PROJECTROOT "/lib/X11"; + size_t libx11dir_len = strlen(libx11dir); + char *newfp = NULL; + size_t newfp_len = 0; + const char *endptr, *ptr, *oldptr = defaultFontPath; + + endptr = oldptr + strlen(oldptr); + ptr = strchr(oldptr, ','); + if (ptr == NULL) + ptr = endptr; + while (ptr != NULL) + { + size_t oldfp_len = (ptr - oldptr); + size_t newsize = oldfp_len; + char *newpath = malloc(newsize + 1); + strncpy(newpath, oldptr, newsize); + newpath[newsize] = 0; + + + if (strncmp(libx11dir, newpath, libx11dir_len) == 0) + { + char *compose; + newsize = newsize - libx11dir_len + basedirlen; + compose = malloc(newsize + 1); + strcpy(compose, basedir); + strncat(compose, newpath + libx11dir_len, newsize - basedirlen); + compose[newsize] = 0; + free(newpath); + newpath = compose; + } + + oldfp_len = newfp_len; + if (oldfp_len > 0) + newfp_len ++; /* space for separator */ + newfp_len += newsize; + + if (newfp == NULL) + newfp = malloc(newfp_len + 1); + else + newfp = realloc(newfp, newfp_len + 1); + + if (oldfp_len > 0) + { + strcpy(newfp + oldfp_len, ","); + oldfp_len++; + } + strcpy(newfp + oldfp_len, newpath); + + free(newpath); + + if (*ptr == 0) + { + oldptr = ptr; + ptr = NULL; + } else + { + oldptr = ptr + 1; + ptr = strchr(oldptr, ','); + if (ptr == NULL) + ptr = endptr; + } + } + + defaultFontPath = xstrdup(newfp); + free(newfp); + changed_fontpath = TRUE; + } +#endif /* RELOCATE_PROJECTROOT */ + if (changed_fontpath) + winDebug ("FontPath set to \"%s\"\n", defaultFontPath); + +#ifdef RELOCATE_PROJECTROOT + if (getenv("XKEYSYMDB") == NULL) + { + char buffer[MAX_PATH]; + snprintf(buffer, sizeof(buffer), "XKEYSYMDB=%s\\XKeysymDB", + basedir); + buffer[sizeof(buffer)-1] = 0; + putenv(buffer); + } + if (getenv("XERRORDB") == NULL) + { + char buffer[MAX_PATH]; + snprintf(buffer, sizeof(buffer), "XERRORDB=%s\\XErrorDB", + basedir); + buffer[sizeof(buffer)-1] = 0; + putenv(buffer); + } + if (getenv("XLOCALEDIR") == NULL) + { + char buffer[MAX_PATH]; + snprintf(buffer, sizeof(buffer), "XLOCALEDIR=%s\\locale", + basedir); + buffer[sizeof(buffer)-1] = 0; + putenv(buffer); + } + if (getenv("XHOSTPREFIX") == NULL) + { + char buffer[MAX_PATH]; + snprintf(buffer, sizeof(buffer), "XHOSTPREFIX=%s\\X", + basedir); + buffer[sizeof(buffer)-1] = 0; + putenv(buffer); + } + if (getenv("HOME") == NULL) + { + HMODULE shfolder; + SHGETFOLDERPATHPROC shgetfolderpath = NULL; + char buffer[MAX_PATH + 5]; + strncpy(buffer, "HOME=", 5); + + /* Try to load SHGetFolderPath from shfolder.dll and shell32.dll */ + + shfolder = LoadLibrary("shfolder.dll"); + /* fallback to shell32.dll */ + if (shfolder == NULL) + shfolder = LoadLibrary("shell32.dll"); + + /* resolve SHGetFolderPath */ + if (shfolder != NULL) + shgetfolderpath = (SHGETFOLDERPATHPROC)GetProcAddress(shfolder, "SHGetFolderPathA"); + + /* query appdata directory */ + if (shgetfolderpath && + shgetfolderpath(NULL, CSIDL_APPDATA|CSIDL_FLAG_CREATE, NULL, 0, + buffer + 5) == 0) + { + putenv(buffer); + } else + { + ErrorF ("Can not determine HOME directory\n"); + } + if (shfolder != NULL) + FreeLibrary(shfolder); + } + if (!g_fLogFileChanged) { + static char buffer[MAX_PATH]; + DWORD size = GetTempPath(sizeof(buffer), buffer); + if (size && size < sizeof(buffer)) + { + snprintf(buffer + size, sizeof(buffer) - size, + "VCXSrv.%s.log", display); + buffer[sizeof(buffer)-1] = 0; + g_pszLogFile = buffer; + GetLongPathName(buffer, buffer, MAX_PATH); + winDebug ("Logfile set to \"%s\"\n", g_pszLogFile); + } + } + { + static char xkbbasedir[MAX_PATH]; + + snprintf(xkbbasedir, sizeof(xkbbasedir), "%s\\xkbdata", basedir); + if (sizeof(xkbbasedir) > 0) + xkbbasedir[sizeof(xkbbasedir)-1] = 0; + XkbBaseDirectory = xkbbasedir; + XkbBinDirectory = basedir; + } +#endif /* RELOCATE_PROJECTROOT */ +} + +void +OsVendorInit (void) +{ + /* Re-initialize global variables on server reset */ + winInitializeGlobals (); + + winFixupPaths(); + +#ifdef DDXOSVERRORF + if (!OsVendorVErrorFProc) + OsVendorVErrorFProc = OsVendorVErrorF; +#endif + + if (!g_fLogInited) { + /* keep this order. If LogInit fails it calls Abort which then calls + * ddxGiveUp where LogInit is called again and creates an infinite + * recursion. If we set g_fLogInited to TRUE before the init we + * avoid the second call + */ + g_fLogInited = TRUE; + g_pszLogFile = LogInit (g_pszLogFile, NULL); + } + LogSetParameter (XLOG_FLUSH, 1); + LogSetParameter (XLOG_VERBOSITY, g_iLogVerbose); + LogSetParameter (XLOG_FILE_VERBOSITY, g_iLogVerbose); + + /* Log the version information */ + if (serverGeneration == 1) + winLogVersionInfo (); + + winCheckMount(); + + /* Add a default screen if no screens were specified */ + if (g_iNumScreens == 0) + { + winDebug ("OsVendorInit - Creating default screen 0\n"); + + /* + * We need to initialize the default screen 0 if no -screen + * arguments were processed. + * + * Add a screen 0 using the defaults set by winInitializeDefaultScreens() + * and any additional default screen parameters given + */ + winInitializeScreens(1); + + /* We have to flag this as an explicit screen, even though it isn't */ + g_ScreenInfo[0].fExplicitScreen = TRUE; + } +} + + +static void +winUseMsg (void) +{ + ErrorF("\n"); + ErrorF("\n"); + ErrorF(EXECUTABLE_NAME " Device Dependent Usage:\n"); + ErrorF("\n"); + +#ifdef XWIN_CLIPBOARD + ErrorF ("-[no]clipboard\n" + "\tEnable [disable] the clipboard integration. Default is enabled.\n"); +#endif + + ErrorF ("-clipupdates num_boxes\n" + "\tUse a clipping region to constrain shadow update blits to\n" + "\tthe updated region when num_boxes, or more, are in the\n" + "\tupdated region.\n"); + +#ifdef XWIN_XF86CONFIG + ErrorF ("-config\n" + "\tSpecify a configuration file.\n"); + + ErrorF ("-configdir\n" + "\tSpecify a configuration directory.\n"); +#endif + + ErrorF ("-depth bits_per_pixel\n" + "\tSpecify an optional bitdepth to use in fullscreen mode\n" + "\twith a DirectDraw engine.\n"); + + ErrorF ("-emulate3buttons [timeout]\n" + "\tEmulate 3 button mouse with an optional timeout in\n" + "\tmilliseconds.\n"); + +#ifdef XWIN_EMULATEPSEUDO + ErrorF ("-emulatepseudo\n" + "\tCreate a depth 8 PseudoColor visual when running in\n" + "\tdepths 15, 16, 24, or 32, collectively known as TrueColor\n" + "\tdepths. The PseudoColor visual does not have correct colors,\n" + "\tand it may crash, but it at least allows you to run your\n" + "\tapplication in TrueColor modes.\n"); +#endif + + ErrorF ("-engine engine_type_id\n" + "\tOverride the server's automatically selected engine type:\n" + "\t\t1 - Shadow GDI\n" + "\t\t2 - Shadow DirectDraw\n" + "\t\t4 - Shadow DirectDraw4 Non-Locking\n" +#ifdef XWIN_PRIMARYFB + "\t\t8 - Primary DirectDraw\n" +#endif +#ifdef XWIN_NATIVEGDI + "\t\t16 - Native GDI - experimental\n" +#endif + ); + + ErrorF ("-fullscreen\n" + "\tRun the server in fullscreen mode.\n"); + + ErrorF ("-ignoreinput\n" + "\tIgnore keyboard and mouse input.\n"); + +#ifdef XWIN_MULTIWINDOWEXTWM + ErrorF ("-internalwm\n" + "\tRun the internal window manager.\n"); +#endif + +#ifdef XWIN_XF86CONFIG + ErrorF ("-keyboard\n" + "\tSpecify a keyboard device from the configuration file.\n"); +#endif + + ErrorF ("-[no]keyhook\n" + "\tGrab special Windows keypresses like Alt-Tab or the Menu " + "key.\n"); + + ErrorF ("-lesspointer\n" + "\tHide the windows mouse pointer when it is over any\n" + "\t" EXECUTABLE_NAME " window. This prevents ghost cursors appearing when\n" + "\tthe Windows cursor is drawn on top of the X cursor\n"); + + ErrorF ("-logfile filename\n" + "\tWrite log messages to <filename>.\n"); + + ErrorF ("-logverbose verbosity\n" + "\tSet the verbosity of log messages. [NOTE: Only a few messages\n" + "\trespect the settings yet]\n" + "\t\t0 - only print fatal error.\n" + "\t\t1 - print additional configuration information.\n" + "\t\t2 - print additional runtime information [default].\n" + "\t\t3 - print debugging and tracing information.\n"); + + ErrorF ("-[no]multimonitors or -[no]multiplemonitors\n" + "\tUse the entire virtual screen if multiple\n" + "\tmonitors are present.\n"); + +#ifdef XWIN_MULTIWINDOW + ErrorF ("-multiwindow\n" + "\tRun the server in multi-window mode.\n"); +#endif + +#ifdef XWIN_MULTIWINDOWEXTWM + ErrorF ("-mwextwm\n" + "\tRun the server in multi-window external window manager mode.\n"); +#endif + + ErrorF ("-nodecoration\n" + "\tDo not draw a window border, title bar, etc. Windowed\n" + "\tmode only.\n"); + +#ifdef XWIN_CLIPBOARD + ErrorF ("-nounicodeclipboard\n" + "\tDo not use Unicode clipboard even if on a NT-based platform.\n"); +#endif + + ErrorF ("-refresh rate_in_Hz\n" + "\tSpecify an optional refresh rate to use in fullscreen mode\n" + "\twith a DirectDraw engine.\n"); + + ErrorF ("-rootless\n" + "\tRun the server in rootless mode.\n"); + + ErrorF ("-screen scr_num [width height [x y] | [[WxH[+X+Y]][@m]] ]\n" + "\tEnable screen scr_num and optionally specify a width and\n" + "\theight and initial position for that screen. Additionally\n" + "\ta monitor number can be specified to start the server on,\n" + "\tat which point, all coordinates become relative to that\n" + "\tmonitor (Not for Windows NT4 and 95). Examples:\n" + "\t -screen 0 800x600+100+100@2 ; 2nd monitor offset 100,100 size 800x600\n" + "\t -screen 0 1024x768@3 ; 3rd monitor size 1024x768\n" + "\t -screen 0 @1 ; on 1st monitor using its full resolution (the default)\n"); + + ErrorF ("-scrollbars\n" + "\tIn windowed mode, allow screens bigger than the Windows desktop.\n" + "\tMoreover, if the window has decorations, one can now resize\n" + "\tit.\n"); + + ErrorF ("-silent-dup-error\n" + "\tIf another instance of " EXECUTABLE_NAME " with the same display number is running\n" + "\texit silently and don’t display any error message.\n"); + + ErrorF ("-swcursor\n" + "\tDisable the usage of the Windows cursor and use the X11 software\n" + "\tcursor instead.\n"); + + ErrorF ("-[no]trayicon\n" + "\tDo not create a tray icon. Default is to create one\n" + "\ticon per screen. You can globally disable tray icons with\n" + "\t-notrayicon, then enable it for specific screens with\n" + "\t-trayicon for those screens.\n"); + + ErrorF ("-[no]unixkill\n" + "\tCtrl+Alt+Backspace exits the X Server.\n"); + +#ifdef XWIN_GLX_WINDOWS + ErrorF ("-[no]wgl\n" + "\tEnable the GLX extension to use the native Windows WGL interface for accelerated OpenGL\n"); +#endif + + ErrorF ("-[no]winkill\n" + "\tAlt+F4 exits the X Server.\n"); + + ErrorF ("-xkblayout XKBLayout\n" + "\tEquivalent to XKBLayout in XF86Config files.\n" + "\tFor example: -xkblayout de\n"); + + ErrorF ("-xkbmodel XKBModel\n" + "\tEquivalent to XKBModel in XF86Config files.\n"); + + ErrorF ("-xkboptions XKBOptions\n" + "\tEquivalent to XKBOptions in XF86Config files.\n"); + + ErrorF ("-xkbrules XKBRules\n" + "\tEquivalent to XKBRules in XF86Config files.\n"); + + ErrorF ("-xkbvariant XKBVariant\n" + "\tEquivalent to XKBVariant in XF86Config files.\n" + "\tFor example: -xkbvariant nodeadkeys\n"); +} + +/* See Porting Layer Definition - p. 57 */ +void +ddxUseMsg(void) +{ + /* Set a flag so that FatalError won't give duplicate warning message */ + g_fSilentFatalError = TRUE; + + winUseMsg(); + + /* Log file will not be opened for UseMsg unless we open it now */ + if (!g_fLogInited) { + g_pszLogFile = LogInit (g_pszLogFile, NULL); + g_fLogInited = TRUE; + } + LogClose (); + + /* Notify user where UseMsg text can be found.*/ + if (!g_fNoHelpMessageBox) + winMessageBoxF ("The " PROJECT_NAME " help text has been printed to " + "%s.\n" + "Please open %s to read the help text.\n", + MB_ICONINFORMATION, g_pszLogFile, g_pszLogFile); +} + +/* See Porting Layer Definition - p. 20 */ +/* + * Do any global initialization, then initialize each screen. + * + * NOTE: We use ddxProcessArgument, so we don't need to touch argc and argv + */ + +void +InitOutput (ScreenInfo *screenInfo, int argc, char *argv[]) +{ + int i; + + /* Log the command line */ + winLogCommandLine (argc, argv); + + winDebug ("InitOutput\n"); + + /* Validate command-line arguments */ + if (serverGeneration == 1 && !winValidateArgs ()) + { + FatalError ("InitOutput - Invalid command-line arguments found. " + "Exiting.\n"); + } + + /* Check for duplicate invocation on same display number.*/ + if (serverGeneration == 1 && !winCheckDisplayNumber ()) + { + if (g_fSilentDupError) + g_fSilentFatalError = TRUE; + FatalError ("InitOutput - Duplicate invocation on display " + "number: %s. Exiting.\n", display); + } + +#ifdef XWIN_XF86CONFIG + /* Try to read the xorg.conf-style configuration file */ + if (!winReadConfigfile ()) + ErrorF ("InitOutput - Error reading config file\n"); +#else + winConfigFiles (); +#endif + + /* Load preferences from XWinrc file */ + LoadPreferences(); + + /* Setup global screen info parameters */ + screenInfo->imageByteOrder = IMAGE_BYTE_ORDER; + screenInfo->bitmapScanlinePad = BITMAP_SCANLINE_PAD; + screenInfo->bitmapScanlineUnit = BITMAP_SCANLINE_UNIT; + screenInfo->bitmapBitOrder = BITMAP_BIT_ORDER; + screenInfo->numPixmapFormats = NUMFORMATS; + + /* Describe how we want common pixmap formats padded */ + for (i = 0; i < NUMFORMATS; i++) + { + screenInfo->formats[i] = g_PixmapFormats[i]; + } + + /* Load pointers to DirectDraw functions */ + winGetDDProcAddresses (); + + /* Detect supported engines */ + winDetectSupportedEngines (); + + /* Load common controls library */ + g_hmodCommonControls = LoadLibraryEx ("comctl32.dll", NULL, 0); + + /* Load TrackMouseEvent function pointer */ + g_fpTrackMouseEvent = GetProcAddress (g_hmodCommonControls, + "_TrackMouseEvent"); + if (g_fpTrackMouseEvent == NULL) + { + ErrorF ("InitOutput - Could not get pointer to function\n" + "\t_TrackMouseEvent in comctl32.dll. Try installing\n" + "\tInternet Explorer 3.0 or greater if you have not\n" + "\talready.\n"); + + /* Free the library since we won't need it */ + FreeLibrary (g_hmodCommonControls); + g_hmodCommonControls = NULL; + + /* Set function pointer to point to no operation function */ + g_fpTrackMouseEvent = (FARPROC) (void (*)(void))NoopDDA; + } + + /* Store the instance handle */ + g_hInstance = GetModuleHandle (NULL); + + /* Initialize each screen */ + for (i = 0; i < g_iNumScreens; ++i) + { + /* Initialize the screen */ + if (-1 == AddScreen (winScreenInit, argc, argv)) + { + FatalError ("InitOutput - Couldn't add screen %d", i); + } + } + +#if defined(XWIN_CLIPBOARD) || defined(XWIN_MULTIWINDOW) + + /* Generate a cookie used by internal clients for authorization */ + if (g_fXdmcpEnabled || g_fAuthEnabled) + winGenerateAuthorization (); + + /* Perform some one time initialization */ + if (1 == serverGeneration) + { + /* + * setlocale applies to all threads in the current process. + * Apply locale specified in LANG environment variable. + */ + setlocale (LC_ALL, ""); + + glx_debugging(); + } +#endif + + winDebug ("InitOutput - Returning.\n"); +} + + +/* + * winCheckDisplayNumber - Check if another instance of Cygwin/X is + * already running on the same display number. If no one exists, + * make a mutex to prevent new instances from running on the same display. + * + * return FALSE if the display number is already used. + */ + +static Bool +winCheckDisplayNumber (void) +{ + int nDisp; + HANDLE mutex; + char name[MAX_PATH]; + char * pszPrefix = '\0'; + OSVERSIONINFO osvi = {0}; + + /* Check display range */ + nDisp = atoi (display); + if (nDisp < 0 || nDisp > 59535) + { + ErrorF ("winCheckDisplayNumber - Bad display number: %d\n", nDisp); + return FALSE; + } + + /* Set first character of mutex name to null */ + name[0] = '\0'; + + /* Get operating system version information */ + osvi.dwOSVersionInfoSize = sizeof (osvi); + GetVersionEx (&osvi); + + /* Want a mutex shared among all terminals on NT > 4.0 */ + if (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT + && osvi.dwMajorVersion >= 5) + { + pszPrefix = "Global\\"; + } + + /* Setup Cygwin/X specific part of name */ + snprintf (name, sizeof(name), "%sCYGWINX_DISPLAY:%d", pszPrefix, nDisp); + + /* Windows automatically releases the mutex when this process exits */ + mutex = CreateMutex (NULL, FALSE, name); + if (!mutex) + { + LPVOID lpMsgBuf; + + /* Display a fancy error message */ + FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + GetLastError (), + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPTSTR) &lpMsgBuf, + 0, NULL); + ErrorF ("winCheckDisplayNumber - CreateMutex failed: %s\n", + (LPSTR)lpMsgBuf); + LocalFree (lpMsgBuf); + + return FALSE; + } + if (GetLastError () == ERROR_ALREADY_EXISTS) + { + ErrorF ("winCheckDisplayNumber - " + "VCXsrv, Xming or Cygwin/X is already running on display %d\n", + nDisp); + return FALSE; + } + + return TRUE; +} + +/* GLX debugging helpers */ +#include <../glx/glapi.h> + +static +void warn_func(void * p1, const char *format, ...) { + va_list v; + va_start(v, format); + vfprintf(stderr, format, v); + va_end(v); + fprintf(stderr,"\n"); +} + +static +void glx_debugging(void) +{ + _glapi_set_warning_func(warn_func); + _glapi_noop_enable_warnings(TRUE); +} diff --git a/xorg-server/hw/xwin/win.h b/xorg-server/hw/xwin/win.h index 1adee2136..bb069afce 100644 --- a/xorg-server/hw/xwin/win.h +++ b/xorg-server/hw/xwin/win.h @@ -590,7 +590,7 @@ typedef struct { * Extern declares for general global variables */ -extern winScreenInfo g_ScreenInfo[]; +extern winScreenInfo * g_ScreenInfo; extern miPointerScreenFuncRec g_winPointerCursorFuncs; extern DWORD g_dwEvents; #ifdef HAS_DEVWINDOWS @@ -1422,6 +1422,12 @@ Bool winInitCursor (ScreenPtr pScreen); /* + * winprocarg.c + */ +void +winInitializeScreens(int maxscreens); + +/* * windisplay.c */ diff --git a/xorg-server/hw/xwin/winglobals.c b/xorg-server/hw/xwin/winglobals.c index ce9c8aba4..09b75031e 100644 --- a/xorg-server/hw/xwin/winglobals.c +++ b/xorg-server/hw/xwin/winglobals.c @@ -1,146 +1,144 @@ -/*
- *Copyright (C) 2003-2004 Harold L Hunt II All Rights Reserved.
- *Copyright (C) Colin Harrison 2005-2008
- *
- *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 HAROLD L HUNT II 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 Harold L Hunt II
- *shall not be used in advertising or otherwise to promote the sale, use
- *or other dealings in this Software without prior written authorization
- *from Harold L Hunt II.
- *
- * Authors: Harold L Hunt II
- * Colin Harrison
- */
-
-#ifdef HAVE_XWIN_CONFIG_H
-#include <xwin-config.h>
-#endif
-#include "win.h"
-
-
-/*
- * General global variables
- */
-
-int g_iNumScreens = 0;
-winScreenInfo g_ScreenInfo[MAXSCREENS];
-int g_iLastScreen = -1;
-#ifdef HAS_DEVWINDOWS
-int g_fdMessageQueue = WIN_FD_INVALID;
-#endif
-static int g_iScreenPrivateKeyIndex;
-DevPrivateKey g_iScreenPrivateKey = &g_iScreenPrivateKeyIndex;
-static int g_iCmapPrivateKeyIndex;
-DevPrivateKey g_iCmapPrivateKey = &g_iCmapPrivateKeyIndex;
-static int g_iGCPrivateKeyIndex;
-DevPrivateKey g_iGCPrivateKey = &g_iGCPrivateKeyIndex;
-static int g_iPixmapPrivateKeyIndex;
-DevPrivateKey g_iPixmapPrivateKey = &g_iPixmapPrivateKeyIndex;
-static int g_iWindowPrivateKeyIndex;
-DevPrivateKey g_iWindowPrivateKey = &g_iWindowPrivateKeyIndex;
-unsigned long g_ulServerGeneration = 0;
-Bool g_fInitializedDefaultScreens = FALSE;
-DWORD g_dwEnginesSupported = 0;
-HINSTANCE g_hInstance = 0;
-HWND g_hDlgDepthChange = NULL;
-HWND g_hDlgExit = NULL;
-HWND g_hDlgAbout = NULL;
-const char * g_pszQueryHost = NULL;
-Bool g_fXdmcpEnabled = FALSE;
-Bool g_fAuthEnabled = FALSE;
-HICON g_hIconX = NULL;
-HICON g_hSmallIconX = NULL;
-#ifndef RELOCATE_PROJECTROOT
-const char * g_pszLogFile = DEFAULT_LOGDIR "/XWin.%s.log";
-#else
-const char * g_pszLogFile = "XWin.log";
-Bool g_fLogFileChanged = FALSE;
-#endif
-int g_iLogVerbose = 2;
-Bool g_fLogInited = FALSE;
-char * g_pszCommandLine = NULL;
-Bool g_fSilentFatalError = FALSE;
-DWORD g_dwCurrentThreadID = 0;
-Bool g_fKeyboardHookLL = FALSE;
-HHOOK g_hhookKeyboardLL = NULL;
-HWND g_hwndKeyboardFocus = NULL;
-Bool g_fNoHelpMessageBox = FALSE;
-Bool g_fSoftwareCursor = FALSE;
-Bool g_fSilentDupError = FALSE;
-Bool g_fNativeGl = FALSE;
-
-/*
- * Global variables for dynamically loaded libraries and
- * their function pointers
- */
-
-HMODULE g_hmodDirectDraw = NULL;
-FARPROC g_fpDirectDrawCreate = NULL;
-FARPROC g_fpDirectDrawCreateClipper = NULL;
-
-HMODULE g_hmodCommonControls = NULL;
-FARPROC g_fpTrackMouseEvent = (FARPROC) (void (*)(void))NoopDDA;
-
-
-#ifdef XWIN_CLIPBOARD
-/*
- * Wrapped DIX functions
- */
-winDispatchProcPtr winProcEstablishConnectionOrig = NULL;
-winDispatchProcPtr winProcQueryTreeOrig = NULL;
-winDispatchProcPtr winProcSetSelectionOwnerOrig = NULL;
-
-
-/*
- * Clipboard variables
- */
-
-Bool g_fUnicodeClipboard = TRUE;
-Bool g_fClipboard = TRUE;
-Bool g_fClipboardLaunched = FALSE;
-Bool g_fClipboardStarted = FALSE;
-pthread_t g_ptClipboardProc;
-HWND g_hwndClipboard = NULL;
-void *g_pClipboardDisplay = NULL;
-Window g_iClipboardWindow = None;
-Atom g_atomLastOwnedSelection = None;
-#endif
-
-
-/*
- * Re-initialize global variables that are invalidated
- * by a server reset.
- */
-
-void
-winInitializeGlobals (void)
-{
- g_dwCurrentThreadID = GetCurrentThreadId ();
- g_hwndKeyboardFocus = NULL;
-#ifdef XWIN_CLIPBOARD
- g_fClipboardLaunched = FALSE;
- g_fClipboardStarted = FALSE;
- g_iClipboardWindow = None;
- g_pClipboardDisplay = NULL;
- g_atomLastOwnedSelection = None;
- g_hwndClipboard = NULL;
-#endif
-}
+/* + *Copyright (C) 2003-2004 Harold L Hunt II All Rights Reserved. + *Copyright (C) Colin Harrison 2005-2008 + * + *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 HAROLD L HUNT II 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 Harold L Hunt II + *shall not be used in advertising or otherwise to promote the sale, use + *or other dealings in this Software without prior written authorization + *from Harold L Hunt II. + * + * Authors: Harold L Hunt II + * Colin Harrison + */ + +#ifdef HAVE_XWIN_CONFIG_H +#include <xwin-config.h> +#endif +#include "win.h" + + +/* + * General global variables + */ + +int g_iNumScreens = 0; +winScreenInfo * g_ScreenInfo = 0; +#ifdef HAS_DEVWINDOWS +int g_fdMessageQueue = WIN_FD_INVALID; +#endif +static int g_iScreenPrivateKeyIndex; +DevPrivateKey g_iScreenPrivateKey = &g_iScreenPrivateKeyIndex; +static int g_iCmapPrivateKeyIndex; +DevPrivateKey g_iCmapPrivateKey = &g_iCmapPrivateKeyIndex; +static int g_iGCPrivateKeyIndex; +DevPrivateKey g_iGCPrivateKey = &g_iGCPrivateKeyIndex; +static int g_iPixmapPrivateKeyIndex; +DevPrivateKey g_iPixmapPrivateKey = &g_iPixmapPrivateKeyIndex; +static int g_iWindowPrivateKeyIndex; +DevPrivateKey g_iWindowPrivateKey = &g_iWindowPrivateKeyIndex; +unsigned long g_ulServerGeneration = 0; +DWORD g_dwEnginesSupported = 0; +HINSTANCE g_hInstance = 0; +HWND g_hDlgDepthChange = NULL; +HWND g_hDlgExit = NULL; +HWND g_hDlgAbout = NULL; +const char * g_pszQueryHost = NULL; +Bool g_fXdmcpEnabled = FALSE; +Bool g_fAuthEnabled = FALSE; +HICON g_hIconX = NULL; +HICON g_hSmallIconX = NULL; +#ifndef RELOCATE_PROJECTROOT +const char * g_pszLogFile = DEFAULT_LOGDIR "/XWin.%s.log"; +#else +const char * g_pszLogFile = "XWin.log"; +Bool g_fLogFileChanged = FALSE; +#endif +int g_iLogVerbose = 2; +Bool g_fLogInited = FALSE; +char * g_pszCommandLine = NULL; +Bool g_fSilentFatalError = FALSE; +DWORD g_dwCurrentThreadID = 0; +Bool g_fKeyboardHookLL = FALSE; +HHOOK g_hhookKeyboardLL = NULL; +HWND g_hwndKeyboardFocus = NULL; +Bool g_fNoHelpMessageBox = FALSE; +Bool g_fSoftwareCursor = FALSE; +Bool g_fSilentDupError = FALSE; +Bool g_fNativeGl = FALSE; + +/* + * Global variables for dynamically loaded libraries and + * their function pointers + */ + +HMODULE g_hmodDirectDraw = NULL; +FARPROC g_fpDirectDrawCreate = NULL; +FARPROC g_fpDirectDrawCreateClipper = NULL; + +HMODULE g_hmodCommonControls = NULL; +FARPROC g_fpTrackMouseEvent = (FARPROC) (void (*)(void))NoopDDA; + + +#ifdef XWIN_CLIPBOARD +/* + * Wrapped DIX functions + */ +winDispatchProcPtr winProcEstablishConnectionOrig = NULL; +winDispatchProcPtr winProcQueryTreeOrig = NULL; +winDispatchProcPtr winProcSetSelectionOwnerOrig = NULL; + + +/* + * Clipboard variables + */ + +Bool g_fUnicodeClipboard = TRUE; +Bool g_fClipboard = TRUE; +Bool g_fClipboardLaunched = FALSE; +Bool g_fClipboardStarted = FALSE; +pthread_t g_ptClipboardProc; +HWND g_hwndClipboard = NULL; +void *g_pClipboardDisplay = NULL; +Window g_iClipboardWindow = None; +Atom g_atomLastOwnedSelection = None; +#endif + + +/* + * Re-initialize global variables that are invalidated + * by a server reset. + */ + +void +winInitializeGlobals (void) +{ + g_dwCurrentThreadID = GetCurrentThreadId (); + g_hwndKeyboardFocus = NULL; +#ifdef XWIN_CLIPBOARD + g_fClipboardLaunched = FALSE; + g_fClipboardStarted = FALSE; + g_iClipboardWindow = None; + g_pClipboardDisplay = NULL; + g_atomLastOwnedSelection = None; + g_hwndClipboard = NULL; +#endif +} diff --git a/xorg-server/hw/xwin/winprocarg.c b/xorg-server/hw/xwin/winprocarg.c index 3cd9353db..50e15ec10 100644 --- a/xorg-server/hw/xwin/winprocarg.c +++ b/xorg-server/hw/xwin/winprocarg.c @@ -1,1572 +1,1252 @@ -/*
-
-Copyright 1993, 1998 The Open Group
-Copyright (C) Colin Harrison 2005-2008
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation.
-
-The above copyright notice and this permission notice shall be included
-in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
-OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
-ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of The Open Group shall
-not be used in advertising or otherwise to promote the sale, use or
-other dealings in this Software without prior written authorization
-from The Open Group.
-
-*/
-
-#ifdef HAVE_XWIN_CONFIG_H
-#include <xwin-config.h>
-#endif
-#ifdef XVENDORNAME
-#define VENDOR_STRING XVENDORNAME
-#define VENDOR_CONTACT BUILDERADDR
-#endif
-#include <../xfree86/common/xorgVersion.h>
-#include "win.h"
-#include "winconfig.h"
-#include "winprefs.h"
-#include "winmsg.h"
-#define COMPILE_MULTIMON_STUBS
-#include <multimon.h>
-/*
- * References to external symbols
- */
-
-extern int g_iNumScreens;
-extern winScreenInfo g_ScreenInfo[];
-extern int g_iLastScreen;
-extern Bool g_fInitializedDefaultScreens;
-#ifdef XWIN_CLIPBOARD
-extern Bool g_fUnicodeClipboard;
-extern Bool g_fClipboard;
-#endif
-extern int g_iLogVerbose;
-extern const char * g_pszLogFile;
-#ifdef RELOCATE_PROJECTROOT
-extern Bool g_fLogFileChanged;
-#endif
-extern Bool g_fXdmcpEnabled;
-extern Bool g_fAuthEnabled;
-extern char * g_pszCommandLine;
-extern Bool g_fKeyboardHookLL;
-extern Bool g_fNoHelpMessageBox;
-extern Bool g_fSoftwareCursor;
-extern Bool g_fSilentDupError;
-extern Bool g_fNativeGl;
-
-/* globals required by callback function for monitor information */
-struct GetMonitorInfoData {
- int requestedMonitor;
- int monitorNum;
- Bool bUserSpecifiedMonitor;
- Bool bMonitorSpecifiedExists;
- int monitorOffsetX;
- int monitorOffsetY;
- int monitorHeight;
- int monitorWidth;
-};
-
-wBOOL CALLBACK getMonitorInfo(HMONITOR hMonitor, HDC hdc, LPRECT rect, LPARAM _data);
-
-static Bool QueryMonitor(int index, struct GetMonitorInfoData *data)
-{
- /* prepare data */
- if (data == NULL)
- return FALSE;
- memset(data, 0, sizeof(*data));
- data->requestedMonitor = index;
-
- /* query information */
- xEnumDisplayMonitors(NULL, NULL, getMonitorInfo, (LPARAM) data);
-
- return TRUE;
-}
-
-/*
- * Function prototypes
- */
-
-void
-winLogCommandLine (int argc, char *argv[]);
-
-void
-winLogVersionInfo (void);
-
-#ifdef DDXOSVERRORF
-void OsVendorVErrorF (const char *pszFormat, va_list va_args);
-#endif
-
-void
-winInitializeDefaultScreens (void);
-
-/*
- * Process arguments on the command line
- */
-
-void
-winInitializeDefaultScreens (void)
-{
- int i;
- DWORD dwWidth, dwHeight;
-
- /* Bail out early if default screens have already been initialized */
- if (g_fInitializedDefaultScreens)
- return;
-
- /* Zero the memory used for storing the screen info */
- ZeroMemory (g_ScreenInfo, MAXSCREENS * sizeof (winScreenInfo));
-
- /* Get default width and height */
- /*
- * NOTE: These defaults will cause the window to cover only
- * the primary monitor in the case that we have multiple monitors.
- */
- dwWidth = GetSystemMetrics (SM_CXSCREEN);
- dwHeight = GetSystemMetrics (SM_CYSCREEN);
-
- winDebug ("winInitializeDefaultScreens - w %d h %d\n",
- (int) dwWidth, (int) dwHeight);
-
- /* Set a default DPI, if no parameter was passed */
- if (monitorResolution == 0)
- monitorResolution = WIN_DEFAULT_DPI;
-
- for (i = 0; i < MAXSCREENS; ++i)
- {
- g_ScreenInfo[i].dwScreen = i;
- g_ScreenInfo[i].dwWidth = dwWidth;
- g_ScreenInfo[i].dwHeight = dwHeight;
- g_ScreenInfo[i].dwUserWidth = dwWidth;
- g_ScreenInfo[i].dwUserHeight = dwHeight;
- g_ScreenInfo[i].fUserGaveHeightAndWidth
- = WIN_DEFAULT_USER_GAVE_HEIGHT_AND_WIDTH;
- g_ScreenInfo[i].fUserGavePosition = FALSE;
- g_ScreenInfo[i].dwBPP = WIN_DEFAULT_BPP;
- g_ScreenInfo[i].dwClipUpdatesNBoxes = WIN_DEFAULT_CLIP_UPDATES_NBOXES;
-#ifdef XWIN_EMULATEPSEUDO
- g_ScreenInfo[i].fEmulatePseudo = WIN_DEFAULT_EMULATE_PSEUDO;
-#endif
- g_ScreenInfo[i].dwRefreshRate = WIN_DEFAULT_REFRESH;
- g_ScreenInfo[i].pfb = NULL;
- g_ScreenInfo[i].fFullScreen = FALSE;
- g_ScreenInfo[i].fDecoration = TRUE;
-#ifdef XWIN_MULTIWINDOWEXTWM
- g_ScreenInfo[i].fMWExtWM = FALSE;
- g_ScreenInfo[i].fInternalWM = FALSE;
-#endif
- g_ScreenInfo[i].fRootless = FALSE;
-#ifdef XWIN_MULTIWINDOW
- g_ScreenInfo[i].fMultiWindow = FALSE;
-#endif
-#if defined(XWIN_MULTIWINDOW) || defined(XWIN_MULTIWINDOWEXTWM)
- g_ScreenInfo[i].fMultiMonitorOverride = FALSE;
-#endif
- g_ScreenInfo[i].fMultipleMonitors = FALSE;
- g_ScreenInfo[i].fLessPointer = FALSE;
- g_ScreenInfo[i].fScrollbars = FALSE;
- g_ScreenInfo[i].fNoTrayIcon = FALSE;
- g_ScreenInfo[i].iE3BTimeout = WIN_E3B_OFF;
- g_ScreenInfo[i].dwWidth_mm = (dwWidth / WIN_DEFAULT_DPI)
- * 25.4;
- g_ScreenInfo[i].dwHeight_mm = (dwHeight / WIN_DEFAULT_DPI)
- * 25.4;
- g_ScreenInfo[i].fUseWinKillKey = WIN_DEFAULT_WIN_KILL;
- g_ScreenInfo[i].fUseUnixKillKey = WIN_DEFAULT_UNIX_KILL;
- g_ScreenInfo[i].fIgnoreInput = FALSE;
- g_ScreenInfo[i].fExplicitScreen = FALSE;
- }
-
- /* Signal that the default screens have been initialized */
- g_fInitializedDefaultScreens = TRUE;
-
- winDebug ("winInitializeDefaultScreens - Returning\n");
-}
-
-/* See Porting Layer Definition - p. 57 */
-/*
- * INPUT
- * argv: pointer to an array of null-terminated strings, one for
- * each token in the X Server command line; the first token
- * is 'XWin.exe', or similar.
- * argc: a count of the number of tokens stored in argv.
- * i: a zero-based index into argv indicating the current token being
- * processed.
- *
- * OUTPUT
- * return: return the number of tokens processed correctly.
- *
- * NOTE
- * When looking for n tokens, check that i + n is less than argc. Or,
- * you may check if i is greater than or equal to argc, in which case
- * you should display the UseMsg () and return 0.
- */
-
-/* Check if enough arguments are given for the option */
-#define CHECK_ARGS(count) if (i + count >= argc) { UseMsg (); return 0; }
-
-/* Compare the current option with the string. */
-#define IS_OPTION(name) (strcmp (argv[i], name) == 0)
-
-int
-ddxProcessArgument (int argc, char *argv[], int i)
-{
- static Bool s_fBeenHere = FALSE;
-
- /* Initialize once */
- if (!s_fBeenHere)
- {
-#ifdef DDXOSVERRORF
- /*
- * This initialises our hook into VErrorF () for catching log messages
- * that are generated before OsInit () is called.
- */
- OsVendorVErrorFProc = OsVendorVErrorF;
-#endif
-
- s_fBeenHere = TRUE;
-
- /* Initialize only if option is not -help */
- if (!IS_OPTION("-help") && !IS_OPTION("-h") && !IS_OPTION("--help") &&
- !IS_OPTION("-version") && !IS_OPTION("--version"))
- {
-
- /* Log the version information */
- winLogVersionInfo ();
-
- /* Log the command line */
- winLogCommandLine (argc, argv);
-
- /*
- * Initialize default screen settings. We have to do this before
- * OsVendorInit () gets called, otherwise we will overwrite
- * settings changed by parameters such as -fullscreen, etc.
- */
- winDebug ("ddxProcessArgument - Initializing default "
- "screens\n");
- winInitializeDefaultScreens ();
- }
- }
-
- winDebug ("ddxProcessArgument - arg: %s\n", argv[i]);
-
- /*
- * Look for the '-help' and similar options
- */
- if (IS_OPTION ("-help") || IS_OPTION("-h") || IS_OPTION("--help"))
- {
- /* Reset logfile. We don't need that helpmessage in the logfile */
- g_pszLogFile = NULL;
- g_fNoHelpMessageBox = TRUE;
- UseMsg();
- exit (0);
- return 1;
- }
-
- if (IS_OPTION ("-version") || IS_OPTION("--version"))
- {
- /* Reset logfile. We don't need that versioninfo in the logfile */
- g_pszLogFile = NULL;
- winLogVersionInfo ();
- exit (0);
- return 1;
- }
-
- /*
- * Look for the '-screen scr_num [width height]' argument
- */
- if (IS_OPTION ("-screen"))
- {
- int iArgsProcessed = 1;
- int nScreenNum;
- int iWidth, iHeight, iX, iY;
- int iMonitor;
-
- winDebug ("ddxProcessArgument - screen - argc: %d i: %d\n",
- argc, i);
-
- /* Display the usage message if the argument is malformed */
- if (i + 1 >= argc)
- {
- return 0;
- }
-
- /* Grab screen number */
- nScreenNum = atoi (argv[i + 1]);
-
- /* Validate the specified screen number */
- if (nScreenNum < 0 || nScreenNum >= MAXSCREENS)
- {
- ErrorF ("ddxProcessArgument - screen - Invalid screen number %d\n",
- nScreenNum);
- UseMsg ();
- return 0;
- }
-
- /* look for @m where m is monitor number */
- if (i + 2 < argc
- && 1 == sscanf(argv[i + 2], "@%d", (int *) &iMonitor))
- {
- struct GetMonitorInfoData data;
- if (!QueryMonitor(iMonitor, &data))
- {
- ErrorF ("ddxProcessArgument - screen - "
- "Querying monitors is not supported on NT4 and Win95\n");
- } else if (data.bMonitorSpecifiedExists == TRUE)
- {
- winDebug("ddxProcessArgument - screen - Found Valid ``@Monitor'' = %d arg\n", iMonitor);
- iArgsProcessed = 3;
- g_ScreenInfo[nScreenNum].fUserGaveHeightAndWidth = FALSE;
- g_ScreenInfo[nScreenNum].fUserGavePosition = TRUE;
- g_ScreenInfo[nScreenNum].dwWidth = data.monitorWidth;
- g_ScreenInfo[nScreenNum].dwHeight = data.monitorHeight;
- g_ScreenInfo[nScreenNum].dwUserWidth = data.monitorWidth;
- g_ScreenInfo[nScreenNum].dwUserHeight = data.monitorHeight;
- g_ScreenInfo[nScreenNum].dwInitialX = data.monitorOffsetX;
- g_ScreenInfo[nScreenNum].dwInitialY = data.monitorOffsetY;
- }
- else
- {
- /* monitor does not exist, error out */
- ErrorF ("ddxProcessArgument - screen - Invalid monitor number %d\n",
- iMonitor);
- UseMsg ();
- exit (0);
- return 0;
- }
- }
-
- /* Look for 'WxD' or 'W D' */
- else if (i + 2 < argc
- && 2 == sscanf (argv[i + 2], "%dx%d",
- (int *) &iWidth,
- (int *) &iHeight))
- {
- winDebug ("ddxProcessArgument - screen - Found ``WxD'' arg\n");
- iArgsProcessed = 3;
- g_ScreenInfo[nScreenNum].fUserGaveHeightAndWidth = TRUE;
- g_ScreenInfo[nScreenNum].dwWidth = iWidth;
- g_ScreenInfo[nScreenNum].dwHeight = iHeight;
- g_ScreenInfo[nScreenNum].dwUserWidth = iWidth;
- g_ScreenInfo[nScreenNum].dwUserHeight = iHeight;
- /* Look for WxD+X+Y */
- if (2 == sscanf (argv[i + 2], "%*dx%*d+%d+%d",
- (int *) &iX,
- (int *) &iY))
- {
- winDebug("ddxProcessArgument - screen - Found ``X+Y'' arg\n");
- g_ScreenInfo[nScreenNum].fUserGavePosition = TRUE;
- g_ScreenInfo[nScreenNum].dwInitialX = iX;
- g_ScreenInfo[nScreenNum].dwInitialY = iY;
-
- /* look for WxD+X+Y@m where m is monitor number. take X,Y to be offsets from monitor's root position */
- if (1 == sscanf (argv[i + 2], "%*dx%*d+%*d+%*d@%d",
- (int *) &iMonitor))
- {
- struct GetMonitorInfoData data;
- if (!QueryMonitor(iMonitor, &data))
- {
- ErrorF ("ddxProcessArgument - screen - "
- "Querying monitors is not supported on NT4 and Win95\n");
- } else if (data.bMonitorSpecifiedExists == TRUE)
- {
- g_ScreenInfo[nScreenNum].dwInitialX += data.monitorOffsetX;
- g_ScreenInfo[nScreenNum].dwInitialY += data.monitorOffsetY;
- }
- else
- {
- /* monitor does not exist, error out */
- ErrorF ("ddxProcessArgument - screen - Invalid monitor number %d\n",
- iMonitor);
- UseMsg ();
- exit (0);
- return 0;
- }
-
- }
- }
-
- /* look for WxD@m where m is monitor number */
- else if (1 == sscanf(argv[i + 2], "%*dx%*d@%d",
- (int *) &iMonitor))
- {
- struct GetMonitorInfoData data;
- if (!QueryMonitor(iMonitor, &data))
- {
- ErrorF ("ddxProcessArgument - screen - "
- "Querying monitors is not supported on NT4 and Win95\n");
- } else if (data.bMonitorSpecifiedExists == TRUE)
- {
- winDebug ("ddxProcessArgument - screen - Found Valid ``@Monitor'' = %d arg\n", iMonitor);
- g_ScreenInfo[nScreenNum].fUserGavePosition = TRUE;
- g_ScreenInfo[nScreenNum].dwInitialX = data.monitorOffsetX;
- g_ScreenInfo[nScreenNum].dwInitialY = data.monitorOffsetY;
- }
- else
- {
- /* monitor does not exist, error out */
- ErrorF ("ddxProcessArgument - screen - Invalid monitor number %d\n",
- iMonitor);
- UseMsg ();
- exit (0);
- return 0;
- }
-
- }
- }
- else if (i + 3 < argc
- && 1 == sscanf (argv[i + 2], "%d",
- (int *) &iWidth)
- && 1 == sscanf (argv[i + 3], "%d",
- (int *) &iHeight))
- {
- winDebug ("ddxProcessArgument - screen - Found ``W D'' arg\n");
- iArgsProcessed = 4;
- g_ScreenInfo[nScreenNum].fUserGaveHeightAndWidth = TRUE;
- g_ScreenInfo[nScreenNum].dwWidth = iWidth;
- g_ScreenInfo[nScreenNum].dwHeight = iHeight;
- g_ScreenInfo[nScreenNum].dwUserWidth = iWidth;
- g_ScreenInfo[nScreenNum].dwUserHeight = iHeight;
- if (i + 5 < argc
- && 1 == sscanf (argv[i + 4], "%d",
- (int *) &iX)
- && 1 == sscanf (argv[i + 5], "%d",
- (int *) &iY))
- {
- winDebug ("ddxProcessArgument - screen - Found ``X Y'' arg\n");
- iArgsProcessed = 6;
- g_ScreenInfo[nScreenNum].fUserGavePosition = TRUE;
- g_ScreenInfo[nScreenNum].dwInitialX = iX;
- g_ScreenInfo[nScreenNum].dwInitialY = iY;
- }
- }
- else
- {
- ErrorF ("ddxProcessArgument - screen - Did not find size arg. "
- "dwWidth: %d dwHeight: %d\n",
- (int) g_ScreenInfo[nScreenNum].dwWidth,
- (int) g_ScreenInfo[nScreenNum].dwHeight);
- iArgsProcessed = 2;
- g_ScreenInfo[nScreenNum].fUserGaveHeightAndWidth = FALSE;
- }
-
- /* Calculate the screen width and height in millimeters */
- if (g_ScreenInfo[nScreenNum].fUserGaveHeightAndWidth)
- {
- g_ScreenInfo[nScreenNum].dwWidth_mm
- = (g_ScreenInfo[nScreenNum].dwWidth
- / monitorResolution) * 25.4;
- g_ScreenInfo[nScreenNum].dwHeight_mm
- = (g_ScreenInfo[nScreenNum].dwHeight
- / monitorResolution) * 25.4;
- }
-
- /* Flag that this screen was explicity specified by the user */
- g_ScreenInfo[nScreenNum].fExplicitScreen = TRUE;
-
- /*
- * Keep track of the last screen number seen, as parameters seen
- * before a screen number apply to all screens, whereas parameters
- * seen after a screen number apply to that screen number only.
- */
- g_iLastScreen = nScreenNum;
-
- /* Keep a count of the number of screens */
- ++g_iNumScreens;
-
- return iArgsProcessed;
- }
-
- /*
- * Look for the '-engine n' argument
- */
- if (IS_OPTION ("-engine"))
- {
- DWORD dwEngine = 0;
- CARD8 c8OnBits = 0;
-
- /* Display the usage message if the argument is malformed */
- if (++i >= argc)
- {
- UseMsg ();
- return 0;
- }
-
- /* Grab the argument */
- dwEngine = atoi (argv[i]);
-
- /* Count the one bits in the engine argument */
- c8OnBits = winCountBits (dwEngine);
-
- /* Argument should only have a single bit on */
- if (c8OnBits != 1)
- {
- UseMsg ();
- return 0;
- }
-
- /* Is this parameter attached to a screen or global? */
- if (-1 == g_iLastScreen)
- {
- int j;
-
- /* Parameter is for all screens */
- for (j = 0; j < MAXSCREENS; j++)
- {
- g_ScreenInfo[j].dwEnginePreferred = dwEngine;
- }
- }
- else
- {
- /* Parameter is for a single screen */
- g_ScreenInfo[g_iLastScreen].dwEnginePreferred = dwEngine;
- }
-
- /* Indicate that we have processed the argument */
- return 2;
- }
-
- /*
- * Look for the '-fullscreen' argument
- */
- if (IS_OPTION ("-fullscreen"))
- {
- /* Is this parameter attached to a screen or is it global? */
- if (-1 == g_iLastScreen)
- {
- int j;
-
- /* Parameter is for all screens */
- for (j = 0; j < MAXSCREENS; j++)
- {
-#if defined(XWIN_MULTIWINDOW) || defined(XWIN_MULTIWINDOWEXTWM)
- if (!g_ScreenInfo[j].fMultiMonitorOverride)
- g_ScreenInfo[j].fMultipleMonitors = FALSE;
-#endif
- g_ScreenInfo[j].fFullScreen = TRUE;
- }
- }
- else
- {
- /* Parameter is for a single screen */
-#if defined(XWIN_MULTIWINDOW) || defined(XWIN_MULTIWINDOWEXTWM)
- if (!g_ScreenInfo[g_iLastScreen].fMultiMonitorOverride)
- g_ScreenInfo[g_iLastScreen].fMultipleMonitors = FALSE;
-#endif
- g_ScreenInfo[g_iLastScreen].fFullScreen = TRUE;
- }
-
- /* Indicate that we have processed this argument */
- return 1;
- }
-
- /*
- * Look for the '-lesspointer' argument
- */
- if (IS_OPTION ("-lesspointer"))
- {
- /* Is this parameter attached to a screen or is it global? */
- if (-1 == g_iLastScreen)
- {
- int j;
-
- /* Parameter is for all screens */
- for (j = 0; j < MAXSCREENS; j++)
- {
- g_ScreenInfo[j].fLessPointer = TRUE;
- }
- }
- else
- {
- /* Parameter is for a single screen */
- g_ScreenInfo[g_iLastScreen].fLessPointer = TRUE;
- }
-
- /* Indicate that we have processed this argument */
- return 1;
- }
-
- /*
- * Look for the '-nodecoration' argument
- */
- if (IS_OPTION ("-nodecoration"))
- {
- /* Is this parameter attached to a screen or is it global? */
- if (-1 == g_iLastScreen)
- {
- int j;
-
- /* Parameter is for all screens */
- for (j = 0; j < MAXSCREENS; j++)
- {
-#if defined(XWIN_MULTIWINDOW) || defined(XWIN_MULTIWINDOWEXTWM)
- if (!g_ScreenInfo[j].fMultiMonitorOverride)
- g_ScreenInfo[j].fMultipleMonitors = FALSE;
-#endif
- g_ScreenInfo[j].fDecoration = FALSE;
- }
- }
- else
- {
- /* Parameter is for a single screen */
-#if defined(XWIN_MULTIWINDOW) || defined(XWIN_MULTIWINDOWEXTWM)
- if (!g_ScreenInfo[g_iLastScreen].fMultiMonitorOverride)
- g_ScreenInfo[g_iLastScreen].fMultipleMonitors = FALSE;
-#endif
- g_ScreenInfo[g_iLastScreen].fDecoration = FALSE;
- }
-
- /* Indicate that we have processed this argument */
- return 1;
- }
-
-#ifdef XWIN_MULTIWINDOWEXTWM
- /*
- * Look for the '-mwextwm' argument
- */
- if (IS_OPTION ("-mwextwm"))
- {
- /* Is this parameter attached to a screen or is it global? */
- if (-1 == g_iLastScreen)
- {
- int j;
-
- /* Parameter is for all screens */
- for (j = 0; j < MAXSCREENS; j++)
- {
- if (!g_ScreenInfo[j].fMultiMonitorOverride)
- g_ScreenInfo[j].fMultipleMonitors = TRUE;
- g_ScreenInfo[j].fMWExtWM = TRUE;
- }
- }
- else
- {
- /* Parameter is for a single screen */
- if (!g_ScreenInfo[g_iLastScreen].fMultiMonitorOverride)
- g_ScreenInfo[g_iLastScreen].fMultipleMonitors = TRUE;
- g_ScreenInfo[g_iLastScreen].fMWExtWM = TRUE;
- }
-
- /* Indicate that we have processed this argument */
- return 1;
- }
- /*
- * Look for the '-internalwm' argument
- */
- if (IS_OPTION ("-internalwm"))
- {
- /* Is this parameter attached to a screen or is it global? */
- if (-1 == g_iLastScreen)
- {
- int j;
-
- /* Parameter is for all screens */
- for (j = 0; j < MAXSCREENS; j++)
- {
- if (!g_ScreenInfo[j].fMultiMonitorOverride)
- g_ScreenInfo[j].fMultipleMonitors = TRUE;
- g_ScreenInfo[j].fMWExtWM = TRUE;
- g_ScreenInfo[j].fInternalWM = TRUE;
- }
- }
- else
- {
- /* Parameter is for a single screen */
- if (!g_ScreenInfo[g_iLastScreen].fMultiMonitorOverride)
- g_ScreenInfo[g_iLastScreen].fMultipleMonitors = TRUE;
- g_ScreenInfo[g_iLastScreen].fMWExtWM = TRUE;
- g_ScreenInfo[g_iLastScreen].fInternalWM = TRUE;
- }
-
- /* Indicate that we have processed this argument */
- return 1;
- }
-#endif
-
- /*
- * Look for the '-rootless' argument
- */
- if (IS_OPTION ("-rootless"))
- {
- /* Is this parameter attached to a screen or is it global? */
- if (-1 == g_iLastScreen)
- {
- int j;
-
- /* Parameter is for all screens */
- for (j = 0; j < MAXSCREENS; j++)
- {
-#if defined(XWIN_MULTIWINDOW) || defined(XWIN_MULTIWINDOWEXTWM)
- if (!g_ScreenInfo[j].fMultiMonitorOverride)
- g_ScreenInfo[j].fMultipleMonitors = FALSE;
-#endif
- g_ScreenInfo[j].fRootless = TRUE;
- }
- }
- else
- {
- /* Parameter is for a single screen */
-#if defined(XWIN_MULTIWINDOW) || defined(XWIN_MULTIWINDOWEXTWM)
- if (!g_ScreenInfo[g_iLastScreen].fMultiMonitorOverride)
- g_ScreenInfo[g_iLastScreen].fMultipleMonitors = FALSE;
-#endif
- g_ScreenInfo[g_iLastScreen].fRootless = TRUE;
- }
-
- /* Indicate that we have processed this argument */
- return 1;
- }
-
-#ifdef XWIN_MULTIWINDOW
- /*
- * Look for the '-multiwindow' argument
- */
- if (IS_OPTION ("-multiwindow"))
- {
- /* Is this parameter attached to a screen or is it global? */
- if (-1 == g_iLastScreen)
- {
- int j;
-
- /* Parameter is for all screens */
- for (j = 0; j < MAXSCREENS; j++)
- {
-#if defined(XWIN_MULTIWINDOW) || defined(XWIN_MULTIWINDOWEXTWM)
- if (!g_ScreenInfo[j].fMultiMonitorOverride)
- g_ScreenInfo[j].fMultipleMonitors = TRUE;
-#endif
- g_ScreenInfo[j].fMultiWindow = TRUE;
- }
- }
- else
- {
- /* Parameter is for a single screen */
-#if defined(XWIN_MULTIWINDOW) || defined(XWIN_MULTIWINDOWEXTWM)
- if (!g_ScreenInfo[g_iLastScreen].fMultiMonitorOverride)
- g_ScreenInfo[g_iLastScreen].fMultipleMonitors = TRUE;
-#endif
- g_ScreenInfo[g_iLastScreen].fMultiWindow = TRUE;
- }
-
- /* Indicate that we have processed this argument */
- return 1;
- }
-#endif
-
- /*
- * Look for the '-multiplemonitors' argument
- */
- if (IS_OPTION ("-multiplemonitors")
- || IS_OPTION ("-multimonitors"))
- {
- /* Is this parameter attached to a screen or is it global? */
- if (-1 == g_iLastScreen)
- {
- int j;
-
- /* Parameter is for all screens */
- for (j = 0; j < MAXSCREENS; j++)
- {
-#if defined(XWIN_MULTIWINDOW) || defined(XWIN_MULTIWINDOWEXTWM)
- g_ScreenInfo[j].fMultiMonitorOverride = TRUE;
-#endif
- g_ScreenInfo[j].fMultipleMonitors = TRUE;
- }
- }
- else
- {
- /* Parameter is for a single screen */
-#if defined(XWIN_MULTIWINDOW) || defined(XWIN_MULTIWINDOWEXTWM)
- g_ScreenInfo[g_iLastScreen].fMultiMonitorOverride = TRUE;
-#endif
- g_ScreenInfo[g_iLastScreen].fMultipleMonitors = TRUE;
- }
-
- /* Indicate that we have processed this argument */
- return 1;
- }
-
- /*
- * Look for the '-nomultiplemonitors' argument
- */
- if (IS_OPTION ("-nomultiplemonitors")
- || IS_OPTION ("-nomultimonitors"))
- {
- /* Is this parameter attached to a screen or is it global? */
- if (-1 == g_iLastScreen)
- {
- int j;
-
- /* Parameter is for all screens */
- for (j = 0; j < MAXSCREENS; j++)
- {
-#if defined(XWIN_MULTIWINDOW) || defined(XWIN_MULTIWINDOWEXTWM)
- g_ScreenInfo[j].fMultiMonitorOverride = TRUE;
-#endif
- g_ScreenInfo[j].fMultipleMonitors = FALSE;
- }
- }
- else
- {
- /* Parameter is for a single screen */
-#if defined(XWIN_MULTIWINDOW) || defined(XWIN_MULTIWINDOWEXTWM)
- g_ScreenInfo[g_iLastScreen].fMultiMonitorOverride = TRUE;
-#endif
- g_ScreenInfo[g_iLastScreen].fMultipleMonitors = FALSE;
- }
-
- /* Indicate that we have processed this argument */
- return 1;
- }
-
-
- /*
- * Look for the '-scrollbars' argument
- */
- if (IS_OPTION ("-scrollbars"))
- {
- /* Is this parameter attached to a screen or is it global? */
- if (-1 == g_iLastScreen)
- {
- int j;
-
- /* Parameter is for all screens */
- for (j = 0; j < MAXSCREENS; j++)
- {
- g_ScreenInfo[j].fScrollbars = TRUE;
- }
- }
- else
- {
- /* Parameter is for a single screen */
- g_ScreenInfo[g_iLastScreen].fScrollbars = TRUE;
- }
-
- /* Indicate that we have processed this argument */
- return 1;
- }
-
-
-#ifdef XWIN_CLIPBOARD
- /*
- * Look for the '-clipboard' argument
- */
- if (IS_OPTION ("-clipboard"))
- {
- /* Now the default, we still accept the arg for backwards compatibility */
- g_fClipboard = TRUE;
-
- /* Indicate that we have processed this argument */
- return 1;
- }
-
- /*
- * Look for the '-noclipboard' argument
- */
- if (IS_OPTION ("-noclipboard"))
- {
- g_fClipboard = FALSE;
-
- /* Indicate that we have processed this argument */
- return 1;
- }
-#endif
-
-
- /*
- * Look for the '-ignoreinput' argument
- */
- if (IS_OPTION ("-ignoreinput"))
- {
- /* Is this parameter attached to a screen or is it global? */
- if (-1 == g_iLastScreen)
- {
- int j;
-
- /* Parameter is for all screens */
- for (j = 0; j < MAXSCREENS; j++)
- {
- g_ScreenInfo[j].fIgnoreInput = TRUE;
- }
- }
- else
- {
- /* Parameter is for a single screen */
- g_ScreenInfo[g_iLastScreen].fIgnoreInput = TRUE;
- }
-
- /* Indicate that we have processed this argument */
- return 1;
- }
-
- /*
- * Look for the '-emulate3buttons' argument
- */
- if (IS_OPTION ("-emulate3buttons"))
- {
- int iArgsProcessed = 1;
- int iE3BTimeout = WIN_DEFAULT_E3B_TIME;
-
- /* Grab the optional timeout value */
- if (i + 1 < argc
- && 1 == sscanf (argv[i + 1], "%d",
- &iE3BTimeout))
- {
- /* Indicate that we have processed the next argument */
- iArgsProcessed++;
- }
- else
- {
- /*
- * sscanf () won't modify iE3BTimeout if it doesn't find
- * the specified format; however, I want to be explicit
- * about setting the default timeout in such cases to
- * prevent some programs (me) from getting confused.
- */
- iE3BTimeout = WIN_DEFAULT_E3B_TIME;
- }
-
- /* Is this parameter attached to a screen or is it global? */
- if (-1 == g_iLastScreen)
- {
- int j;
-
- /* Parameter is for all screens */
- for (j = 0; j < MAXSCREENS; j++)
- {
- g_ScreenInfo[j].iE3BTimeout = iE3BTimeout;
- }
- }
- else
- {
- /* Parameter is for a single screen */
- g_ScreenInfo[g_iLastScreen].iE3BTimeout = iE3BTimeout;
- }
-
- /* Indicate that we have processed this argument */
- return iArgsProcessed;
- }
-
- /*
- * Look for the '-depth n' argument
- */
- if (IS_OPTION ("-depth"))
- {
- DWORD dwBPP = 0;
-
- /* Display the usage message if the argument is malformed */
- if (++i >= argc)
- {
- UseMsg ();
- return 0;
- }
-
- /* Grab the argument */
- dwBPP = atoi (argv[i]);
-
- /* Is this parameter attached to a screen or global? */
- if (-1 == g_iLastScreen)
- {
- int j;
-
- /* Parameter is for all screens */
- for (j = 0; j < MAXSCREENS; j++)
- {
- g_ScreenInfo[j].dwBPP = dwBPP;
- }
- }
- else
- {
- /* Parameter is for a single screen */
- g_ScreenInfo[g_iLastScreen].dwBPP = dwBPP;
- }
-
- /* Indicate that we have processed the argument */
- return 2;
- }
-
- /*
- * Look for the '-refresh n' argument
- */
- if (IS_OPTION ("-refresh"))
- {
- DWORD dwRefreshRate = 0;
-
- /* Display the usage message if the argument is malformed */
- if (++i >= argc)
- {
- UseMsg ();
- return 0;
- }
-
- /* Grab the argument */
- dwRefreshRate = atoi (argv[i]);
-
- /* Is this parameter attached to a screen or global? */
- if (-1 == g_iLastScreen)
- {
- int j;
-
- /* Parameter is for all screens */
- for (j = 0; j < MAXSCREENS; j++)
- {
- g_ScreenInfo[j].dwRefreshRate = dwRefreshRate;
- }
- }
- else
- {
- /* Parameter is for a single screen */
- g_ScreenInfo[g_iLastScreen].dwRefreshRate = dwRefreshRate;
- }
-
- /* Indicate that we have processed the argument */
- return 2;
- }
-
- /*
- * Look for the '-clipupdates num_boxes' argument
- */
- if (IS_OPTION ("-clipupdates"))
- {
- DWORD dwNumBoxes = 0;
-
- /* Display the usage message if the argument is malformed */
- if (++i >= argc)
- {
- UseMsg ();
- return 0;
- }
-
- /* Grab the argument */
- dwNumBoxes = atoi (argv[i]);
-
- /* Is this parameter attached to a screen or global? */
- if (-1 == g_iLastScreen)
- {
- int j;
-
- /* Parameter is for all screens */
- for (j = 0; j < MAXSCREENS; j++)
- {
- g_ScreenInfo[j].dwClipUpdatesNBoxes = dwNumBoxes;
- }
- }
- else
- {
- /* Parameter is for a single screen */
- g_ScreenInfo[g_iLastScreen].dwClipUpdatesNBoxes = dwNumBoxes;
- }
-
- /* Indicate that we have processed the argument */
- return 2;
- }
-
-#ifdef XWIN_EMULATEPSEUDO
- /*
- * Look for the '-emulatepseudo' argument
- */
- if (IS_OPTION ("-emulatepseudo"))
- {
- /* Is this parameter attached to a screen or is it global? */
- if (-1 == g_iLastScreen)
- {
- int j;
-
- /* Parameter is for all screens */
- for (j = 0; j < MAXSCREENS; j++)
- {
- g_ScreenInfo[j].fEmulatePseudo = TRUE;
- }
- }
- else
- {
- /* Parameter is for a single screen */
- g_ScreenInfo[g_iLastScreen].fEmulatePseudo = TRUE;
- }
-
- /* Indicate that we have processed this argument */
- return 1;
- }
-#endif
-
- /*
- * Look for the '-nowinkill' argument
- */
- if (IS_OPTION ("-nowinkill"))
- {
- /* Is this parameter attached to a screen or is it global? */
- if (-1 == g_iLastScreen)
- {
- int j;
-
- /* Parameter is for all screens */
- for (j = 0; j < MAXSCREENS; j++)
- {
- g_ScreenInfo[j].fUseWinKillKey = FALSE;
- }
- }
- else
- {
- /* Parameter is for a single screen */
- g_ScreenInfo[g_iLastScreen].fUseWinKillKey = FALSE;
- }
-
- /* Indicate that we have processed this argument */
- return 1;
- }
-
- /*
- * Look for the '-winkill' argument
- */
- if (IS_OPTION ("-winkill"))
- {
- /* Is this parameter attached to a screen or is it global? */
- if (-1 == g_iLastScreen)
- {
- int j;
-
- /* Parameter is for all screens */
- for (j = 0; j < MAXSCREENS; j++)
- {
- g_ScreenInfo[j].fUseWinKillKey = TRUE;
- }
- }
- else
- {
- /* Parameter is for a single screen */
- g_ScreenInfo[g_iLastScreen].fUseWinKillKey = TRUE;
- }
-
- /* Indicate that we have processed this argument */
- return 1;
- }
-
- /*
- * Look for the '-nounixkill' argument
- */
- if (IS_OPTION ("-nounixkill"))
- {
- /* Is this parameter attached to a screen or is it global? */
- if (-1 == g_iLastScreen)
- {
- int j;
-
- /* Parameter is for all screens */
- for (j = 0; j < MAXSCREENS; j++)
- {
- g_ScreenInfo[j].fUseUnixKillKey = FALSE;
- }
- }
- else
- {
- /* Parameter is for a single screen */
- g_ScreenInfo[g_iLastScreen].fUseUnixKillKey = FALSE;
- }
-
- /* Indicate that we have processed this argument */
- return 1;
- }
-
- /*
- * Look for the '-unixkill' argument
- */
- if (IS_OPTION ("-unixkill"))
- {
- /* Is this parameter attached to a screen or is it global? */
- if (-1 == g_iLastScreen)
- {
- int j;
-
- /* Parameter is for all screens */
- for (j = 0; j < MAXSCREENS; j++)
- {
- g_ScreenInfo[j].fUseUnixKillKey = TRUE;
- }
- }
- else
- {
- /* Parameter is for a single screen */
- g_ScreenInfo[g_iLastScreen].fUseUnixKillKey = TRUE;
- }
-
- /* Indicate that we have processed this argument */
- return 1;
- }
-
- /*
- * Look for the '-notrayicon' argument
- */
- if (IS_OPTION ("-notrayicon"))
- {
- /* Is this parameter attached to a screen or is it global? */
- if (-1 == g_iLastScreen)
- {
- int j;
-
- /* Parameter is for all screens */
- for (j = 0; j < MAXSCREENS; j++)
- {
- g_ScreenInfo[j].fNoTrayIcon = TRUE;
- }
- }
- else
- {
- /* Parameter is for a single screen */
- g_ScreenInfo[g_iLastScreen].fNoTrayIcon = TRUE;
- }
-
- /* Indicate that we have processed this argument */
- return 1;
- }
-
- /*
- * Look for the '-trayicon' argument
- */
- if (IS_OPTION ("-trayicon"))
- {
- /* Is this parameter attached to a screen or is it global? */
- if (-1 == g_iLastScreen)
- {
- int j;
-
- /* Parameter is for all screens */
- for (j = 0; j < MAXSCREENS; j++)
- {
- g_ScreenInfo[j].fNoTrayIcon = FALSE;
- }
- }
- else
- {
- /* Parameter is for a single screen */
- g_ScreenInfo[g_iLastScreen].fNoTrayIcon = FALSE;
- }
-
- /* Indicate that we have processed this argument */
- return 1;
- }
-
- /*
- * Look for the '-fp' argument
- */
- if (IS_OPTION ("-fp"))
- {
- CHECK_ARGS (1);
- g_cmdline.fontPath = argv[++i];
- return 0; /* Let DIX parse this again */
- }
-
- /*
- * Look for the '-query' argument
- */
- if (IS_OPTION ("-query"))
- {
- CHECK_ARGS (1);
- g_fXdmcpEnabled = TRUE;
- g_pszQueryHost = argv[++i];
- return 0; /* Let DIX parse this again */
- }
-
- /*
- * Look for the '-auth' argument
- */
- if (IS_OPTION ("-auth"))
- {
- g_fAuthEnabled = TRUE;
- return 0; /* Let DIX parse this again */
- }
-
- /*
- * Look for the '-indirect' or '-broadcast' arguments
- */
- if (IS_OPTION ("-indirect")
- || IS_OPTION ("-broadcast"))
- {
- g_fXdmcpEnabled = TRUE;
- return 0; /* Let DIX parse this again */
- }
-
- /*
- * Look for the '-config' argument
- */
- if (IS_OPTION ("-config")
- || IS_OPTION ("-xf86config"))
- {
- CHECK_ARGS (1);
-#ifdef XWIN_XF86CONFIG
- g_cmdline.configFile = argv[++i];
-#else
- winMessageBoxF ("The %s option is not supported in this "
- "release.\n"
- "Ignoring this option and continuing.\n",
- MB_ICONINFORMATION,
- argv[i]);
-#endif
- return 2;
- }
-
- /*
- * Look for the '-configdir' argument
- */
- if (IS_OPTION ("-configdir"))
- {
- CHECK_ARGS (1);
-#ifdef XWIN_XF86CONFIG
- g_cmdline.configDir = argv[++i];
-#else
- winMessageBoxF ("The %s option is not supported in this "
- "release.\n"
- "Ignoring this option and continuing.\n",
- MB_ICONINFORMATION,
- argv[i]);
-#endif
- return 2;
- }
-
- /*
- * Look for the '-keyboard' argument
- */
- if (IS_OPTION ("-keyboard"))
- {
-#ifdef XWIN_XF86CONFIG
- CHECK_ARGS (1);
- g_cmdline.keyboard = argv[++i];
-#else
- winMessageBoxF ("The -keyboard option is not supported in this "
- "release.\n"
- "Ignoring this option and continuing.\n",
- MB_ICONINFORMATION);
-#endif
- return 2;
- }
-
- /*
- * Look for the '-logfile' argument
- */
- if (IS_OPTION ("-logfile"))
- {
- CHECK_ARGS (1);
- g_pszLogFile = argv[++i];
-#ifdef RELOCATE_PROJECTROOT
- g_fLogFileChanged = TRUE;
-#endif
- return 2;
- }
-
- /*
- * Look for the '-logverbose' argument
- */
- if (IS_OPTION ("-logverbose"))
- {
- CHECK_ARGS (1);
- g_iLogVerbose = atoi(argv[++i]);
- return 2;
- }
-
-#ifdef XWIN_CLIPBOARD
- /*
- * Look for the '-nounicodeclipboard' argument
- */
- if (IS_OPTION ("-nounicodeclipboard"))
- {
- g_fUnicodeClipboard = FALSE;
- /* Indicate that we have processed the argument */
- return 1;
- }
-#endif
-
- if (IS_OPTION ("-xkbrules"))
- {
- CHECK_ARGS (1);
- g_cmdline.xkbRules = argv[++i];
- return 2;
- }
- if (IS_OPTION ("-xkbmodel"))
- {
- CHECK_ARGS (1);
- g_cmdline.xkbModel = argv[++i];
- return 2;
- }
- if (IS_OPTION ("-xkblayout"))
- {
- CHECK_ARGS (1);
- g_cmdline.xkbLayout = argv[++i];
- return 2;
- }
- if (IS_OPTION ("-xkbvariant"))
- {
- CHECK_ARGS (1);
- g_cmdline.xkbVariant = argv[++i];
- return 2;
- }
- if (IS_OPTION ("-xkboptions"))
- {
- CHECK_ARGS (1);
- g_cmdline.xkbOptions = argv[++i];
- return 2;
- }
-
- if (IS_OPTION ("-keyhook"))
- {
- g_fKeyboardHookLL = TRUE;
- return 1;
- }
-
- if (IS_OPTION ("-nokeyhook"))
- {
- g_fKeyboardHookLL = FALSE;
- return 1;
- }
-
- if (IS_OPTION ("-swcursor"))
- {
- g_fSoftwareCursor = TRUE;
- return 1;
- }
-
- if (IS_OPTION ("-silent-dup-error"))
- {
- g_fSilentDupError = TRUE;
- return 1;
- }
-
- if (IS_OPTION("-wgl"))
- {
- g_fNativeGl = TRUE;
- return 1;
- }
-
- if (IS_OPTION("-nowgl"))
- {
- g_fNativeGl = FALSE;
- return 1;
- }
-
- return 0;
-}
-
-
-/*
- * winLogCommandLine - Write entire command line to the log file
- */
-
-void
-winLogCommandLine (int argc, char *argv[])
-{
- int i;
- int iSize = 0;
- int iCurrLen = 0;
-
-#define CHARS_PER_LINE 60
-
- /* Bail if command line has already been logged */
- if (g_pszCommandLine)
- return;
-
- /* Count how much memory is needed for concatenated command line */
- for (i = 0, iCurrLen = 0; i < argc; ++i)
- if (argv[i])
- {
- /* Adds two characters for lines that overflow */
- if ((strlen (argv[i]) < CHARS_PER_LINE
- && iCurrLen + strlen (argv[i]) > CHARS_PER_LINE)
- || strlen (argv[i]) > CHARS_PER_LINE)
- {
- iCurrLen = 0;
- iSize += 2;
- }
-
- /* Add space for item and trailing space */
- iSize += strlen (argv[i]) + 1;
-
- /* Update current line length */
- iCurrLen += strlen (argv[i]);
- }
-
- /* Allocate memory for concatenated command line */
- g_pszCommandLine = malloc (iSize + 1);
- if (!g_pszCommandLine)
- FatalError ("winLogCommandLine - Could not allocate memory for "
- "command line string. Exiting.\n");
-
- /* Set first character to concatenated command line to null */
- g_pszCommandLine[0] = '\0';
-
- /* Loop through all args */
- for (i = 0, iCurrLen = 0; i < argc; ++i)
- {
- /* Add a character for lines that overflow */
- if ((strlen (argv[i]) < CHARS_PER_LINE
- && iCurrLen + strlen (argv[i]) > CHARS_PER_LINE)
- || strlen (argv[i]) > CHARS_PER_LINE)
- {
- iCurrLen = 0;
-
- /* Add line break if it fits */
- strncat (g_pszCommandLine, "\n ", iSize - strlen (g_pszCommandLine));
- }
-
- strncat (g_pszCommandLine, argv[i], iSize - strlen (g_pszCommandLine));
- strncat (g_pszCommandLine, " ", iSize - strlen (g_pszCommandLine));
-
- /* Save new line length */
- iCurrLen += strlen (argv[i]);
- }
-
- winDebug ("XWin was started with the following command line:\n\n"
- "%s\n\n", g_pszCommandLine);
-}
-
-
-/*
- * winLogVersionInfo - Log Cygwin/X version information
- */
-
-void
-winLogVersionInfo (void)
-{
-#ifdef WINDBG
- static Bool s_fBeenHere = FALSE;
-
- if (s_fBeenHere)
- return;
- s_fBeenHere = TRUE;
-
- winDebug ("Welcome to the VcXsrv X Server\n");
- winDebug ("Vendor: %s\n", VENDOR_STRING);
- winDebug ("Release: %d.%d.%d.%d (%d)\n\n", XORG_VERSION_MAJOR, XORG_VERSION_MINOR, XORG_VERSION_PATCH, XORG_VERSION_SNAP, XORG_VERSION_CURRENT);
- winDebug ("%s\n\n", BUILDERSTRING);
- winDebug ("Contact: %s\n\n", VENDOR_CONTACT);
-#endif
-}
-/*
- * getMonitorInfo - callback function used to return information from the enumeration of monitors attached
- */
-
-wBOOL CALLBACK getMonitorInfo(HMONITOR hMonitor, HDC hdc, LPRECT rect, LPARAM _data)
-{
- struct GetMonitorInfoData* data = (struct GetMonitorInfoData*)_data;
- // only get data for monitor number specified in <data>
- data->monitorNum++;
- if (data->monitorNum == data->requestedMonitor)
- {
- data->bMonitorSpecifiedExists = TRUE;
- data->monitorOffsetX = rect->left;
- data->monitorOffsetY = rect->top;
- data->monitorHeight = rect->bottom - rect->top;
- data->monitorWidth = rect->right - rect->left;
- return FALSE;
- }
- return TRUE;
-}
+/* + +Copyright 1993, 1998 The Open Group +Copyright (C) Colin Harrison 2005-2008 + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. + +*/ + +#ifdef HAVE_XWIN_CONFIG_H +#include <xwin-config.h> +#endif +#ifdef XVENDORNAME +#define VENDOR_STRING XVENDORNAME +#define VENDOR_CONTACT BUILDERADDR +#endif +#include <../xfree86/common/xorgVersion.h> +#include "win.h" +#include "winconfig.h" +#include "winprefs.h" +#include "winmsg.h" +#define COMPILE_MULTIMON_STUBS +#include <multimon.h> +/* + * References to external symbols + */ + +extern int g_iNumScreens; +extern winScreenInfo * g_ScreenInfo; +#ifdef XWIN_CLIPBOARD +extern Bool g_fUnicodeClipboard; +extern Bool g_fClipboard; +#endif +extern int g_iLogVerbose; +extern const char * g_pszLogFile; +#ifdef RELOCATE_PROJECTROOT +extern Bool g_fLogFileChanged; +#endif +extern Bool g_fXdmcpEnabled; +extern Bool g_fAuthEnabled; +extern char * g_pszCommandLine; +extern Bool g_fKeyboardHookLL; +extern Bool g_fNoHelpMessageBox; +extern Bool g_fSoftwareCursor; +extern Bool g_fSilentDupError; +extern Bool g_fNativeGl; + +/* globals required by callback function for monitor information */ +struct GetMonitorInfoData { + int requestedMonitor; + int monitorNum; + Bool bUserSpecifiedMonitor; + Bool bMonitorSpecifiedExists; + int monitorOffsetX; + int monitorOffsetY; + int monitorHeight; + int monitorWidth; +}; + +wBOOL CALLBACK getMonitorInfo(HMONITOR hMonitor, HDC hdc, LPRECT rect, LPARAM _data); + +static Bool QueryMonitor(int index, struct GetMonitorInfoData *data) +{ + /* prepare data */ + if (data == NULL) + return FALSE; + memset(data, 0, sizeof(*data)); + data->requestedMonitor = index; + + /* query information */ + xEnumDisplayMonitors(NULL, NULL, getMonitorInfo, (LPARAM) data); + + return TRUE; +} + +/* + * Function prototypes + */ + +void +winLogCommandLine (int argc, char *argv[]); + +void +winLogVersionInfo (void); + +#ifdef DDXOSVERRORF +void OsVendorVErrorF (const char *pszFormat, va_list va_args); +#endif + +/* + * Process arguments on the command line + */ + +static int iLastScreen = -1; +static winScreenInfo defaultScreenInfo; + +static void +winInitializeScreenDefaults(void) +{ + DWORD dwWidth, dwHeight; + static Bool fInitializedScreenDefaults = FALSE; + + /* Bail out early if default screen has already been initialized */ + if (fInitializedScreenDefaults) + return; + + /* Zero the memory used for storing the screen info */ + memset(&defaultScreenInfo, 0, sizeof(winScreenInfo)); + + /* Get default width and height */ + /* + * NOTE: These defaults will cause the window to cover only + * the primary monitor in the case that we have multiple monitors. + */ + dwWidth = GetSystemMetrics (SM_CXSCREEN); + dwHeight = GetSystemMetrics (SM_CYSCREEN); + + winDebug ("winInitializeScreenDefaults - w %d h %d\n", + (int) dwWidth, (int) dwHeight); + + /* Set a default DPI, if no parameter was passed */ + if (monitorResolution == 0) + monitorResolution = WIN_DEFAULT_DPI; + + defaultScreenInfo.dwWidth = dwWidth; + defaultScreenInfo.dwHeight = dwHeight; + defaultScreenInfo.dwUserWidth = dwWidth; + defaultScreenInfo.dwUserHeight = dwHeight; + defaultScreenInfo.fUserGaveHeightAndWidth = WIN_DEFAULT_USER_GAVE_HEIGHT_AND_WIDTH; + defaultScreenInfo.fUserGavePosition = FALSE; + defaultScreenInfo.dwBPP = WIN_DEFAULT_BPP; + defaultScreenInfo.dwClipUpdatesNBoxes = WIN_DEFAULT_CLIP_UPDATES_NBOXES; +#ifdef XWIN_EMULATEPSEUDO + defaultScreenInfo.fEmulatePseudo = WIN_DEFAULT_EMULATE_PSEUDO; +#endif + defaultScreenInfo.dwRefreshRate = WIN_DEFAULT_REFRESH; + defaultScreenInfo.pfb = NULL; + defaultScreenInfo.fFullScreen = FALSE; + defaultScreenInfo.fDecoration = TRUE; +#ifdef XWIN_MULTIWINDOWEXTWM + defaultScreenInfo.fMWExtWM = FALSE; + defaultScreenInfo.fInternalWM = FALSE; +#endif + defaultScreenInfo.fRootless = FALSE; +#ifdef XWIN_MULTIWINDOW + defaultScreenInfo.fMultiWindow = FALSE; +#endif +#if defined(XWIN_MULTIWINDOW) || defined(XWIN_MULTIWINDOWEXTWM) + defaultScreenInfo.fMultiMonitorOverride = FALSE; +#endif + defaultScreenInfo.fMultipleMonitors = FALSE; + defaultScreenInfo.fLessPointer = FALSE; + defaultScreenInfo.fScrollbars = FALSE; + defaultScreenInfo.fNoTrayIcon = FALSE; + defaultScreenInfo.iE3BTimeout = WIN_E3B_OFF; + defaultScreenInfo.dwWidth_mm = (dwWidth / WIN_DEFAULT_DPI) * 25.4; + defaultScreenInfo.dwHeight_mm = (dwHeight / WIN_DEFAULT_DPI) * 25.4; + defaultScreenInfo.fUseWinKillKey = WIN_DEFAULT_WIN_KILL; + defaultScreenInfo.fUseUnixKillKey = WIN_DEFAULT_UNIX_KILL; + defaultScreenInfo.fIgnoreInput = FALSE; + defaultScreenInfo.fExplicitScreen = FALSE; + + /* Note that the default screen has been initialized */ + fInitializedScreenDefaults = TRUE; +} + +static void +winInitializeScreen(int i) +{ + winDebug ("winInitializeScreen - %d\n",i); + + /* Initialize default screen values, if needed */ + winInitializeScreenDefaults(); + + /* Copy the default screen info */ + g_ScreenInfo[i] = defaultScreenInfo; + + /* Set the screen number */ + g_ScreenInfo[i].dwScreen = i; +} + +void +winInitializeScreens(int maxscreens) +{ + int i; + winDebug ("winInitializeScreens - %i\n", maxscreens); + + if (maxscreens > g_iNumScreens) + { + /* Reallocate the memory for DDX-specific screen info */ + g_ScreenInfo = realloc(g_ScreenInfo, maxscreens * sizeof (winScreenInfo)); + + /* Set default values for any new screens */ + for (i = g_iNumScreens; i < maxscreens ; i++) + winInitializeScreen(i); + + /* Keep a count of the number of screens */ + g_iNumScreens = maxscreens; + } +} + +/* See Porting Layer Definition - p. 57 */ +/* + * INPUT + * argv: pointer to an array of null-terminated strings, one for + * each token in the X Server command line; the first token + * is 'XWin.exe', or similar. + * argc: a count of the number of tokens stored in argv. + * i: a zero-based index into argv indicating the current token being + * processed. + * + * OUTPUT + * return: return the number of tokens processed correctly. + * + * NOTE + * When looking for n tokens, check that i + n is less than argc. Or, + * you may check if i is greater than or equal to argc, in which case + * you should display the UseMsg () and return 0. + */ + +/* Check if enough arguments are given for the option */ +#define CHECK_ARGS(count) if (i + count >= argc) { UseMsg (); return 0; } + +/* Compare the current option with the string. */ +#define IS_OPTION(name) (strcmp (argv[i], name) == 0) + +int +ddxProcessArgument (int argc, char *argv[], int i) +{ + static Bool s_fBeenHere = FALSE; + winScreenInfo *screenInfoPtr = NULL; + + /* Initialize once */ + if (!s_fBeenHere) + { +#ifdef DDXOSVERRORF + /* + * This initialises our hook into VErrorF () for catching log messages + * that are generated before OsInit () is called. + */ + OsVendorVErrorFProc = OsVendorVErrorF; +#endif + + s_fBeenHere = TRUE; + + /* Initialize only if option is not -help */ + if (!IS_OPTION("-help") && !IS_OPTION("-h") && !IS_OPTION("--help") && + !IS_OPTION("-version") && !IS_OPTION("--version")) + { + + /* Log the version information */ + winLogVersionInfo (); + + /* Log the command line */ + winLogCommandLine (argc, argv); + + /* + * Initialize default screen settings. We have to do this before + * OsVendorInit () gets called, otherwise we will overwrite + * settings changed by parameters such as -fullscreen, etc. + */ + winDebug ("ddxProcessArgument - Initializing default " + "screens\n"); + winInitializeScreenDefaults(); + } + } + + winDebug ("ddxProcessArgument - arg: %s\n", argv[i]); + + /* + * Look for the '-help' and similar options + */ + if (IS_OPTION ("-help") || IS_OPTION("-h") || IS_OPTION("--help")) + { + /* Reset logfile. We don't need that helpmessage in the logfile */ + g_pszLogFile = NULL; + g_fNoHelpMessageBox = TRUE; + UseMsg(); + exit (0); + return 1; + } + + if (IS_OPTION ("-version") || IS_OPTION("--version")) + { + /* Reset logfile. We don't need that versioninfo in the logfile */ + g_pszLogFile = NULL; + winLogVersionInfo (); + exit (0); + return 1; + } + + /* + * Look for the '-screen scr_num [width height]' argument + */ + if (IS_OPTION ("-screen")) + { + int iArgsProcessed = 1; + int nScreenNum; + int iWidth, iHeight, iX, iY; + int iMonitor; + + winDebug ("ddxProcessArgument - screen - argc: %d i: %d\n", + argc, i); + + /* Display the usage message if the argument is malformed */ + if (i + 1 >= argc) + { + return 0; + } + + /* Grab screen number */ + nScreenNum = atoi (argv[i + 1]); + + /* Validate the specified screen number */ + if (nScreenNum < 0) + { + ErrorF ("ddxProcessArgument - screen - Invalid screen number %d\n", + nScreenNum); + UseMsg (); + return 0; + } + + /* + Initialize default values for any new screens + + Note that default values can't change after a -screen option is + seen, so it's safe to do this for each screen as it is introduced + */ + winInitializeScreens(nScreenNum+1); + + /* look for @m where m is monitor number */ + if (i + 2 < argc + && 1 == sscanf(argv[i + 2], "@%d", (int *) &iMonitor)) + { + struct GetMonitorInfoData data; + if (!QueryMonitor(iMonitor, &data)) + { + ErrorF ("ddxProcessArgument - screen - " + "Querying monitors is not supported on NT4 and Win95\n"); + } else if (data.bMonitorSpecifiedExists == TRUE) + { + winDebug("ddxProcessArgument - screen - Found Valid ``@Monitor'' = %d arg\n", iMonitor); + iArgsProcessed = 3; + g_ScreenInfo[nScreenNum].fUserGaveHeightAndWidth = FALSE; + g_ScreenInfo[nScreenNum].fUserGavePosition = TRUE; + g_ScreenInfo[nScreenNum].dwWidth = data.monitorWidth; + g_ScreenInfo[nScreenNum].dwHeight = data.monitorHeight; + g_ScreenInfo[nScreenNum].dwUserWidth = data.monitorWidth; + g_ScreenInfo[nScreenNum].dwUserHeight = data.monitorHeight; + g_ScreenInfo[nScreenNum].dwInitialX = data.monitorOffsetX; + g_ScreenInfo[nScreenNum].dwInitialY = data.monitorOffsetY; + } + else + { + /* monitor does not exist, error out */ + ErrorF ("ddxProcessArgument - screen - Invalid monitor number %d\n", + iMonitor); + UseMsg (); + exit (0); + return 0; + } + } + + /* Look for 'WxD' or 'W D' */ + else if (i + 2 < argc + && 2 == sscanf (argv[i + 2], "%dx%d", + (int *) &iWidth, + (int *) &iHeight)) + { + winDebug ("ddxProcessArgument - screen - Found ``WxD'' arg\n"); + iArgsProcessed = 3; + g_ScreenInfo[nScreenNum].fUserGaveHeightAndWidth = TRUE; + g_ScreenInfo[nScreenNum].dwWidth = iWidth; + g_ScreenInfo[nScreenNum].dwHeight = iHeight; + g_ScreenInfo[nScreenNum].dwUserWidth = iWidth; + g_ScreenInfo[nScreenNum].dwUserHeight = iHeight; + /* Look for WxD+X+Y */ + if (2 == sscanf (argv[i + 2], "%*dx%*d+%d+%d", + (int *) &iX, + (int *) &iY)) + { + winDebug("ddxProcessArgument - screen - Found ``X+Y'' arg\n"); + g_ScreenInfo[nScreenNum].fUserGavePosition = TRUE; + g_ScreenInfo[nScreenNum].dwInitialX = iX; + g_ScreenInfo[nScreenNum].dwInitialY = iY; + + /* look for WxD+X+Y@m where m is monitor number. take X,Y to be offsets from monitor's root position */ + if (1 == sscanf (argv[i + 2], "%*dx%*d+%*d+%*d@%d", + (int *) &iMonitor)) + { + struct GetMonitorInfoData data; + if (!QueryMonitor(iMonitor, &data)) + { + ErrorF ("ddxProcessArgument - screen - " + "Querying monitors is not supported on NT4 and Win95\n"); + } else if (data.bMonitorSpecifiedExists == TRUE) + { + g_ScreenInfo[nScreenNum].dwInitialX += data.monitorOffsetX; + g_ScreenInfo[nScreenNum].dwInitialY += data.monitorOffsetY; + } + else + { + /* monitor does not exist, error out */ + ErrorF ("ddxProcessArgument - screen - Invalid monitor number %d\n", + iMonitor); + UseMsg (); + exit (0); + return 0; + } + + } + } + + /* look for WxD@m where m is monitor number */ + else if (1 == sscanf(argv[i + 2], "%*dx%*d@%d", + (int *) &iMonitor)) + { + struct GetMonitorInfoData data; + if (!QueryMonitor(iMonitor, &data)) + { + ErrorF ("ddxProcessArgument - screen - " + "Querying monitors is not supported on NT4 and Win95\n"); + } else if (data.bMonitorSpecifiedExists == TRUE) + { + winDebug ("ddxProcessArgument - screen - Found Valid ``@Monitor'' = %d arg\n", iMonitor); + g_ScreenInfo[nScreenNum].fUserGavePosition = TRUE; + g_ScreenInfo[nScreenNum].dwInitialX = data.monitorOffsetX; + g_ScreenInfo[nScreenNum].dwInitialY = data.monitorOffsetY; + } + else + { + /* monitor does not exist, error out */ + ErrorF ("ddxProcessArgument - screen - Invalid monitor number %d\n", + iMonitor); + UseMsg (); + exit (0); + return 0; + } + + } + } + else if (i + 3 < argc + && 1 == sscanf (argv[i + 2], "%d", + (int *) &iWidth) + && 1 == sscanf (argv[i + 3], "%d", + (int *) &iHeight)) + { + winDebug ("ddxProcessArgument - screen - Found ``W D'' arg\n"); + iArgsProcessed = 4; + g_ScreenInfo[nScreenNum].fUserGaveHeightAndWidth = TRUE; + g_ScreenInfo[nScreenNum].dwWidth = iWidth; + g_ScreenInfo[nScreenNum].dwHeight = iHeight; + g_ScreenInfo[nScreenNum].dwUserWidth = iWidth; + g_ScreenInfo[nScreenNum].dwUserHeight = iHeight; + if (i + 5 < argc + && 1 == sscanf (argv[i + 4], "%d", + (int *) &iX) + && 1 == sscanf (argv[i + 5], "%d", + (int *) &iY)) + { + winDebug ("ddxProcessArgument - screen - Found ``X Y'' arg\n"); + iArgsProcessed = 6; + g_ScreenInfo[nScreenNum].fUserGavePosition = TRUE; + g_ScreenInfo[nScreenNum].dwInitialX = iX; + g_ScreenInfo[nScreenNum].dwInitialY = iY; + } + } + else + { + ErrorF ("ddxProcessArgument - screen - Did not find size arg. " + "dwWidth: %d dwHeight: %d\n", + (int) g_ScreenInfo[nScreenNum].dwWidth, + (int) g_ScreenInfo[nScreenNum].dwHeight); + iArgsProcessed = 2; + g_ScreenInfo[nScreenNum].fUserGaveHeightAndWidth = FALSE; + } + + /* Calculate the screen width and height in millimeters */ + if (g_ScreenInfo[nScreenNum].fUserGaveHeightAndWidth) + { + g_ScreenInfo[nScreenNum].dwWidth_mm + = (g_ScreenInfo[nScreenNum].dwWidth + / monitorResolution) * 25.4; + g_ScreenInfo[nScreenNum].dwHeight_mm + = (g_ScreenInfo[nScreenNum].dwHeight + / monitorResolution) * 25.4; + } + + /* Flag that this screen was explicity specified by the user */ + g_ScreenInfo[nScreenNum].fExplicitScreen = TRUE; + + /* + * Keep track of the last screen number seen, as parameters seen + * before a screen number apply to all screens, whereas parameters + * seen after a screen number apply to that screen number only. + */ + iLastScreen = nScreenNum; + + return iArgsProcessed; + } + + + /* + * Is this parameter attached to a screen or global? + * + * If the parameter is for all screens (appears before + * any -screen option), store it in the default screen + * info + * + * If the parameter is for a single screen (appears + * after a -screen option), store it in the screen info + * for that screen + * + */ + if (iLastScreen == -1) + { + screenInfoPtr = &defaultScreenInfo; + } + else + { + screenInfoPtr = &(g_ScreenInfo[iLastScreen]); + } + + /* + * Look for the '-engine n' argument + */ + if (IS_OPTION ("-engine")) + { + DWORD dwEngine = 0; + CARD8 c8OnBits = 0; + + /* Display the usage message if the argument is malformed */ + if (++i >= argc) + { + UseMsg (); + return 0; + } + + /* Grab the argument */ + dwEngine = atoi (argv[i]); + + /* Count the one bits in the engine argument */ + c8OnBits = winCountBits (dwEngine); + + /* Argument should only have a single bit on */ + if (c8OnBits != 1) + { + UseMsg (); + return 0; + } + + screenInfoPtr->dwEnginePreferred = dwEngine; + + /* Indicate that we have processed the argument */ + return 2; + } + + /* + * Look for the '-fullscreen' argument + */ + if (IS_OPTION ("-fullscreen")) + { +#if defined(XWIN_MULTIWINDOW) || defined(XWIN_MULTIWINDOWEXTWM) + if (!screenInfoPtr->fMultiMonitorOverride) + screenInfoPtr->fMultipleMonitors = FALSE; +#endif + screenInfoPtr->fFullScreen = TRUE; + + /* Indicate that we have processed this argument */ + return 1; + } + + /* + * Look for the '-lesspointer' argument + */ + if (IS_OPTION ("-lesspointer")) + { + screenInfoPtr->fLessPointer = TRUE; + + /* Indicate that we have processed this argument */ + return 1; + } + + /* + * Look for the '-nodecoration' argument + */ + if (IS_OPTION ("-nodecoration")) + { +#if defined(XWIN_MULTIWINDOW) || defined(XWIN_MULTIWINDOWEXTWM) + if (!screenInfoPtr->fMultiMonitorOverride) + screenInfoPtr->fMultipleMonitors = FALSE; +#endif + screenInfoPtr->fDecoration = FALSE; + + /* Indicate that we have processed this argument */ + return 1; + } + +#ifdef XWIN_MULTIWINDOWEXTWM + /* + * Look for the '-mwextwm' argument + */ + if (IS_OPTION ("-mwextwm")) + { + if (!screenInfoPtr->fMultiMonitorOverride) + screenInfoPtr->fMultipleMonitors = TRUE; + screenInfoPtr->fMWExtWM = TRUE; + + /* Indicate that we have processed this argument */ + return 1; + } + /* + * Look for the '-internalwm' argument + */ + if (IS_OPTION ("-internalwm")) + { + if (!screenInfoPtr->fMultiMonitorOverride) + screenInfoPtr->fMultipleMonitors = TRUE; + screenInfoPtr->fMWExtWM = TRUE; + screenInfoPtr->fInternalWM = TRUE; + + /* Indicate that we have processed this argument */ + return 1; + } +#endif + + /* + * Look for the '-rootless' argument + */ + if (IS_OPTION ("-rootless")) + { +#if defined(XWIN_MULTIWINDOW) || defined(XWIN_MULTIWINDOWEXTWM) + if (!screenInfoPtr->fMultiMonitorOverride) + screenInfoPtr->fMultipleMonitors = FALSE; +#endif + screenInfoPtr->fRootless = TRUE; + + /* Indicate that we have processed this argument */ + return 1; + } + +#ifdef XWIN_MULTIWINDOW + /* + * Look for the '-multiwindow' argument + */ + if (IS_OPTION ("-multiwindow")) + { +#if defined(XWIN_MULTIWINDOW) || defined(XWIN_MULTIWINDOWEXTWM) + if (!screenInfoPtr->fMultiMonitorOverride) + screenInfoPtr->fMultipleMonitors = TRUE; +#endif + screenInfoPtr->fMultiWindow = TRUE; + + /* Indicate that we have processed this argument */ + return 1; + } +#endif + + /* + * Look for the '-multiplemonitors' argument + */ + if (IS_OPTION ("-multiplemonitors") + || IS_OPTION ("-multimonitors")) + { +#if defined(XWIN_MULTIWINDOW) || defined(XWIN_MULTIWINDOWEXTWM) + screenInfoPtr->fMultiMonitorOverride = TRUE; +#endif + screenInfoPtr->fMultipleMonitors = TRUE; + + /* Indicate that we have processed this argument */ + return 1; + } + + /* + * Look for the '-nomultiplemonitors' argument + */ + if (IS_OPTION ("-nomultiplemonitors") + || IS_OPTION ("-nomultimonitors")) + { +#if defined(XWIN_MULTIWINDOW) || defined(XWIN_MULTIWINDOWEXTWM) + screenInfoPtr->fMultiMonitorOverride = TRUE; +#endif + screenInfoPtr->fMultipleMonitors = FALSE; + + /* Indicate that we have processed this argument */ + return 1; + } + + + /* + * Look for the '-scrollbars' argument + */ + if (IS_OPTION ("-scrollbars")) + { + screenInfoPtr->fScrollbars = TRUE; + + /* Indicate that we have processed this argument */ + return 1; + } + + +#ifdef XWIN_CLIPBOARD + /* + * Look for the '-clipboard' argument + */ + if (IS_OPTION ("-clipboard")) + { + /* Now the default, we still accept the arg for backwards compatibility */ + g_fClipboard = TRUE; + + /* Indicate that we have processed this argument */ + return 1; + } + + /* + * Look for the '-noclipboard' argument + */ + if (IS_OPTION ("-noclipboard")) + { + g_fClipboard = FALSE; + + /* Indicate that we have processed this argument */ + return 1; + } +#endif + + + /* + * Look for the '-ignoreinput' argument + */ + if (IS_OPTION ("-ignoreinput")) + { + screenInfoPtr->fIgnoreInput = TRUE; + + /* Indicate that we have processed this argument */ + return 1; + } + + /* + * Look for the '-emulate3buttons' argument + */ + if (IS_OPTION ("-emulate3buttons")) + { + int iArgsProcessed = 1; + int iE3BTimeout = WIN_DEFAULT_E3B_TIME; + + /* Grab the optional timeout value */ + if (i + 1 < argc + && 1 == sscanf (argv[i + 1], "%d", + &iE3BTimeout)) + { + /* Indicate that we have processed the next argument */ + iArgsProcessed++; + } + else + { + /* + * sscanf () won't modify iE3BTimeout if it doesn't find + * the specified format; however, I want to be explicit + * about setting the default timeout in such cases to + * prevent some programs (me) from getting confused. + */ + iE3BTimeout = WIN_DEFAULT_E3B_TIME; + } + + screenInfoPtr->iE3BTimeout = iE3BTimeout; + + /* Indicate that we have processed this argument */ + return iArgsProcessed; + } + + /* + * Look for the '-depth n' argument + */ + if (IS_OPTION ("-depth")) + { + DWORD dwBPP = 0; + + /* Display the usage message if the argument is malformed */ + if (++i >= argc) + { + UseMsg (); + return 0; + } + + /* Grab the argument */ + dwBPP = atoi (argv[i]); + + screenInfoPtr->dwBPP = dwBPP; + + /* Indicate that we have processed the argument */ + return 2; + } + + /* + * Look for the '-refresh n' argument + */ + if (IS_OPTION ("-refresh")) + { + DWORD dwRefreshRate = 0; + + /* Display the usage message if the argument is malformed */ + if (++i >= argc) + { + UseMsg (); + return 0; + } + + /* Grab the argument */ + dwRefreshRate = atoi (argv[i]); + + screenInfoPtr->dwRefreshRate = dwRefreshRate; + + /* Indicate that we have processed the argument */ + return 2; + } + + /* + * Look for the '-clipupdates num_boxes' argument + */ + if (IS_OPTION ("-clipupdates")) + { + DWORD dwNumBoxes = 0; + + /* Display the usage message if the argument is malformed */ + if (++i >= argc) + { + UseMsg (); + return 0; + } + + /* Grab the argument */ + dwNumBoxes = atoi (argv[i]); + + screenInfoPtr->dwClipUpdatesNBoxes = dwNumBoxes; + + /* Indicate that we have processed the argument */ + return 2; + } + +#ifdef XWIN_EMULATEPSEUDO + /* + * Look for the '-emulatepseudo' argument + */ + if (IS_OPTION ("-emulatepseudo")) + { + screenInfoPtr->fEmulatePseudo = TRUE; + + /* Indicate that we have processed this argument */ + return 1; + } +#endif + + /* + * Look for the '-nowinkill' argument + */ + if (IS_OPTION ("-nowinkill")) + { + screenInfoPtr->fUseWinKillKey = FALSE; + + /* Indicate that we have processed this argument */ + return 1; + } + + /* + * Look for the '-winkill' argument + */ + if (IS_OPTION ("-winkill")) + { + screenInfoPtr->fUseWinKillKey = TRUE; + + /* Indicate that we have processed this argument */ + return 1; + } + + /* + * Look for the '-nounixkill' argument + */ + if (IS_OPTION ("-nounixkill")) + { + screenInfoPtr->fUseUnixKillKey = FALSE; + + /* Indicate that we have processed this argument */ + return 1; + } + + /* + * Look for the '-unixkill' argument + */ + if (IS_OPTION ("-unixkill")) + { + screenInfoPtr->fUseUnixKillKey = TRUE; + + /* Indicate that we have processed this argument */ + return 1; + } + + /* + * Look for the '-notrayicon' argument + */ + if (IS_OPTION ("-notrayicon")) + { + screenInfoPtr->fNoTrayIcon = TRUE; + + /* Indicate that we have processed this argument */ + return 1; + } + + /* + * Look for the '-trayicon' argument + */ + if (IS_OPTION ("-trayicon")) + { + screenInfoPtr->fNoTrayIcon = FALSE; + + /* Indicate that we have processed this argument */ + return 1; + } + + /* + * Look for the '-fp' argument + */ + if (IS_OPTION ("-fp")) + { + CHECK_ARGS (1); + g_cmdline.fontPath = argv[++i]; + return 0; /* Let DIX parse this again */ + } + + /* + * Look for the '-query' argument + */ + if (IS_OPTION ("-query")) + { + CHECK_ARGS (1); + g_fXdmcpEnabled = TRUE; + g_pszQueryHost = argv[++i]; + return 0; /* Let DIX parse this again */ + } + + /* + * Look for the '-auth' argument + */ + if (IS_OPTION ("-auth")) + { + g_fAuthEnabled = TRUE; + return 0; /* Let DIX parse this again */ + } + + /* + * Look for the '-indirect' or '-broadcast' arguments + */ + if (IS_OPTION ("-indirect") + || IS_OPTION ("-broadcast")) + { + g_fXdmcpEnabled = TRUE; + return 0; /* Let DIX parse this again */ + } + + /* + * Look for the '-config' argument + */ + if (IS_OPTION ("-config") + || IS_OPTION ("-xf86config")) + { + CHECK_ARGS (1); +#ifdef XWIN_XF86CONFIG + g_cmdline.configFile = argv[++i]; +#else + winMessageBoxF ("The %s option is not supported in this " + "release.\n" + "Ignoring this option and continuing.\n", + MB_ICONINFORMATION, + argv[i]); +#endif + return 2; + } + + /* + * Look for the '-configdir' argument + */ + if (IS_OPTION ("-configdir")) + { + CHECK_ARGS (1); +#ifdef XWIN_XF86CONFIG + g_cmdline.configDir = argv[++i]; +#else + winMessageBoxF ("The %s option is not supported in this " + "release.\n" + "Ignoring this option and continuing.\n", + MB_ICONINFORMATION, + argv[i]); +#endif + return 2; + } + + /* + * Look for the '-keyboard' argument + */ + if (IS_OPTION ("-keyboard")) + { +#ifdef XWIN_XF86CONFIG + CHECK_ARGS (1); + g_cmdline.keyboard = argv[++i]; +#else + winMessageBoxF ("The -keyboard option is not supported in this " + "release.\n" + "Ignoring this option and continuing.\n", + MB_ICONINFORMATION); +#endif + return 2; + } + + /* + * Look for the '-logfile' argument + */ + if (IS_OPTION ("-logfile")) + { + CHECK_ARGS (1); + g_pszLogFile = argv[++i]; +#ifdef RELOCATE_PROJECTROOT + g_fLogFileChanged = TRUE; +#endif + return 2; + } + + /* + * Look for the '-logverbose' argument + */ + if (IS_OPTION ("-logverbose")) + { + CHECK_ARGS (1); + g_iLogVerbose = atoi(argv[++i]); + return 2; + } + +#ifdef XWIN_CLIPBOARD + /* + * Look for the '-nounicodeclipboard' argument + */ + if (IS_OPTION ("-nounicodeclipboard")) + { + g_fUnicodeClipboard = FALSE; + /* Indicate that we have processed the argument */ + return 1; + } +#endif + + if (IS_OPTION ("-xkbrules")) + { + CHECK_ARGS (1); + g_cmdline.xkbRules = argv[++i]; + return 2; + } + if (IS_OPTION ("-xkbmodel")) + { + CHECK_ARGS (1); + g_cmdline.xkbModel = argv[++i]; + return 2; + } + if (IS_OPTION ("-xkblayout")) + { + CHECK_ARGS (1); + g_cmdline.xkbLayout = argv[++i]; + return 2; + } + if (IS_OPTION ("-xkbvariant")) + { + CHECK_ARGS (1); + g_cmdline.xkbVariant = argv[++i]; + return 2; + } + if (IS_OPTION ("-xkboptions")) + { + CHECK_ARGS (1); + g_cmdline.xkbOptions = argv[++i]; + return 2; + } + + if (IS_OPTION ("-keyhook")) + { + g_fKeyboardHookLL = TRUE; + return 1; + } + + if (IS_OPTION ("-nokeyhook")) + { + g_fKeyboardHookLL = FALSE; + return 1; + } + + if (IS_OPTION ("-swcursor")) + { + g_fSoftwareCursor = TRUE; + return 1; + } + + if (IS_OPTION ("-silent-dup-error")) + { + g_fSilentDupError = TRUE; + return 1; + } + + if (IS_OPTION("-wgl")) + { + g_fNativeGl = TRUE; + return 1; + } + + if (IS_OPTION("-nowgl")) + { + g_fNativeGl = FALSE; + return 1; + } + + return 0; +} + + +/* + * winLogCommandLine - Write entire command line to the log file + */ + +void +winLogCommandLine (int argc, char *argv[]) +{ + int i; + int iSize = 0; + int iCurrLen = 0; + +#define CHARS_PER_LINE 60 + + /* Bail if command line has already been logged */ + if (g_pszCommandLine) + return; + + /* Count how much memory is needed for concatenated command line */ + for (i = 0, iCurrLen = 0; i < argc; ++i) + if (argv[i]) + { + /* Adds two characters for lines that overflow */ + if ((strlen (argv[i]) < CHARS_PER_LINE + && iCurrLen + strlen (argv[i]) > CHARS_PER_LINE) + || strlen (argv[i]) > CHARS_PER_LINE) + { + iCurrLen = 0; + iSize += 2; + } + + /* Add space for item and trailing space */ + iSize += strlen (argv[i]) + 1; + + /* Update current line length */ + iCurrLen += strlen (argv[i]); + } + + /* Allocate memory for concatenated command line */ + g_pszCommandLine = malloc (iSize + 1); + if (!g_pszCommandLine) + FatalError ("winLogCommandLine - Could not allocate memory for " + "command line string. Exiting.\n"); + + /* Set first character to concatenated command line to null */ + g_pszCommandLine[0] = '\0'; + + /* Loop through all args */ + for (i = 0, iCurrLen = 0; i < argc; ++i) + { + /* Add a character for lines that overflow */ + if ((strlen (argv[i]) < CHARS_PER_LINE + && iCurrLen + strlen (argv[i]) > CHARS_PER_LINE) + || strlen (argv[i]) > CHARS_PER_LINE) + { + iCurrLen = 0; + + /* Add line break if it fits */ + strncat (g_pszCommandLine, "\n ", iSize - strlen (g_pszCommandLine)); + } + + strncat (g_pszCommandLine, argv[i], iSize - strlen (g_pszCommandLine)); + strncat (g_pszCommandLine, " ", iSize - strlen (g_pszCommandLine)); + + /* Save new line length */ + iCurrLen += strlen (argv[i]); + } + + winDebug ("XWin was started with the following command line:\n\n" + "%s\n\n", g_pszCommandLine); +} + + +/* + * winLogVersionInfo - Log Cygwin/X version information + */ + +void +winLogVersionInfo (void) +{ +#ifdef WINDBG + static Bool s_fBeenHere = FALSE; + + if (s_fBeenHere) + return; + s_fBeenHere = TRUE; + + winDebug ("Welcome to the VcXsrv X Server\n"); + winDebug ("Vendor: %s\n", VENDOR_STRING); + winDebug ("Release: %d.%d.%d.%d (%d)\n\n", XORG_VERSION_MAJOR, XORG_VERSION_MINOR, XORG_VERSION_PATCH, XORG_VERSION_SNAP, XORG_VERSION_CURRENT); + winDebug ("%s\n\n", BUILDERSTRING); + winDebug ("Contact: %s\n\n", VENDOR_CONTACT); +#endif +} +/* + * getMonitorInfo - callback function used to return information from the enumeration of monitors attached + */ + +wBOOL CALLBACK getMonitorInfo(HMONITOR hMonitor, HDC hdc, LPRECT rect, LPARAM _data) +{ + struct GetMonitorInfoData* data = (struct GetMonitorInfoData*)_data; + // only get data for monitor number specified in <data> + data->monitorNum++; + if (data->monitorNum == data->requestedMonitor) + { + data->bMonitorSpecifiedExists = TRUE; + data->monitorOffsetX = rect->left; + data->monitorOffsetY = rect->top; + data->monitorHeight = rect->bottom - rect->top; + data->monitorWidth = rect->right - rect->left; + return FALSE; + } + return TRUE; +} diff --git a/xorg-server/hw/xwin/winscrinit.c b/xorg-server/hw/xwin/winscrinit.c index 84341c8fb..501a999a4 100644 --- a/xorg-server/hw/xwin/winscrinit.c +++ b/xorg-server/hw/xwin/winscrinit.c @@ -194,7 +194,7 @@ winScreenInit (int index, /* * In this case, some of the defaults set in - * winInitializeDefaultScreens () are not correct ... + * winInitializeScreenDefaults() are not correct ... */ if (!pScreenInfo->fUserGaveHeightAndWidth) { diff --git a/xorg-server/hw/xwin/winvalargs.c b/xorg-server/hw/xwin/winvalargs.c index 1c9b17fde..6f8d1c994 100644 --- a/xorg-server/hw/xwin/winvalargs.c +++ b/xorg-server/hw/xwin/winvalargs.c @@ -40,17 +40,24 @@ */ extern int g_iNumScreens; -extern winScreenInfo g_ScreenInfo[]; +extern winScreenInfo * g_ScreenInfo; extern Bool g_fXdmcpEnabled; /* - * Prototypes + * Verify all screens have been explicitly specified */ +static BOOL +isEveryScreenExplicit(void) +{ + int i; -Bool -winValidateArgs (void); + for (i = 0; i < g_iNumScreens; i++) + if (!g_ScreenInfo[i].fExplicitScreen) + return FALSE; + return TRUE; +} /* * winValidateArgs - Look for invalid argument combinations @@ -62,6 +69,7 @@ winValidateArgs (void) int i; int iMaxConsecutiveScreen = 0; BOOL fHasNormalScreen0 = FALSE; + BOOL fImplicitScreenFound = FALSE; /* * Check for a malformed set of -screen parameters. @@ -70,23 +78,14 @@ winValidateArgs (void) * XWin -screen 0 -screen 2 * XWin -screen 1 -screen 2 */ - for (i = 0; i < MAXSCREENS; i++) - { - if (g_ScreenInfo[i].fExplicitScreen) - iMaxConsecutiveScreen = i + 1; - } - winDebug ("winValidateArgs - g_iNumScreens: %d " - "iMaxConsecutiveScreen: %d\n", - g_iNumScreens, iMaxConsecutiveScreen); - if (g_iNumScreens < iMaxConsecutiveScreen) + if (!isEveryScreenExplicit()) { ErrorF ("winValidateArgs - Malformed set of screen parameter(s). " "Screens must be specified consecutively starting with " "screen 0. That is, you cannot have only a screen 1, nor " "could you have screen 0 and screen 2. You instead must " - "have screen 0, or screen 0 and screen 1, respectively. Of " - "you can specify as many screens as you want from 0 up to " - "%d.\n", MAXSCREENS - 1); + "have screen 0, or screen 0 and screen 1, respectively. " + "You can specify as many screens as you want.\n"); return FALSE; } |