--- /dev/null
+Makefile
+Xquartz.1.html
+Xquartz._man
+XFree86.1.html
+XFree86._man
+XFree86.man
+appledri.h appledristr.h
+xf86drm.h
+build
--- /dev/null
+{
+ IBClasses = (
+ {CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; },
+ {
+ ACTIONS = {
+ "apps_table_cancel" = id;
+ "apps_table_delete" = id;
+ "apps_table_done" = id;
+ "apps_table_duplicate" = id;
+ "apps_table_new" = id;
+ "apps_table_show" = id;
+ "bring_to_front" = id;
+ "close_window" = id;
+ "enable_fullscreen_changed" = id;
+ "minimize_window" = id;
+ "next_window" = id;
+ "prefs_changed" = id;
+ "prefs_show" = id;
+ "previous_window" = id;
+ "toggle_fullscreen" = id;
+ "x11_help" = id;
+ "zoom_window" = id;
+ };
+ CLASS = X11Controller;
+ LANGUAGE = ObjC;
+ OUTLETS = {
+ "apps_separator" = id;
+ "apps_table" = id;
+ depth = id;
+ "dock_apps_menu" = id;
+ "dock_menu" = id;
+ "dock_window_separator" = id;
+ "enable_auth" = id;
+ "enable_fullscreen" = id;
+ "enable_keyequivs" = id;
+ "enable_tcp" = id;
+ "fake_buttons" = id;
+ "prefs_panel" = id;
+ "sync_keymap" = id;
+ "toggle_fullscreen_item" = id;
+ "use_sysbeep" = id;
+ "window_separator" = id;
+ "x11_about_item" = id;
+ };
+ SUPERCLASS = NSObject;
+ }
+ );
+ IBVersion = 1;
+}
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>IBDocumentLocation</key>
+ <string>61 48 372 379 0 0 1280 832 </string>
+ <key>IBEditorPositions</key>
+ <dict>
+ <key>29</key>
+ <string>530 771 319 44 0 0 1280 832 </string>
+ <key>423</key>
+ <string>525 668 148 61 0 0 1280 832 </string>
+ </dict>
+ <key>IBFramework Version</key>
+ <string>437.0</string>
+ <key>IBGroupedObjects</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <string>371</string>
+ <string>372</string>
+ </array>
+ <key>1</key>
+ <array>
+ <string>385</string>
+ <string>382</string>
+ <string>386</string>
+ </array>
+ <key>3</key>
+ <array>
+ <string>370</string>
+ <string>369</string>
+ </array>
+ <key>4</key>
+ <array>
+ <string>363</string>
+ <string>365</string>
+ </array>
+ <key>5</key>
+ <array>
+ <string>368</string>
+ <string>364</string>
+ </array>
+ <key>6</key>
+ <array>
+ <string>543</string>
+ <string>541</string>
+ </array>
+ <key>7</key>
+ <array>
+ <string>375</string>
+ <string>377</string>
+ </array>
+ <key>8</key>
+ <array>
+ <string>374</string>
+ <string>376</string>
+ </array>
+ </dict>
+ <key>IBLastGroupID</key>
+ <string>9</string>
+ <key>IBLockedObjects</key>
+ <array>
+ <integer>285</integer>
+ <integer>348</integer>
+ <integer>244</integer>
+ </array>
+ <key>IBOpenObjects</key>
+ <array>
+ <integer>423</integer>
+ <integer>29</integer>
+ </array>
+ <key>IBSystem Version</key>
+ <string>8C46</string>
+</dict>
+</plist>
--- /dev/null
+{
+ IBClasses = (
+ {CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; },
+ {
+ ACTIONS = {
+ "apps_table_cancel" = id;
+ "apps_table_delete" = id;
+ "apps_table_done" = id;
+ "apps_table_duplicate" = id;
+ "apps_table_new" = id;
+ "apps_table_show" = id;
+ "bring_to_front" = id;
+ "close_window" = id;
+ "enable_fullscreen_changed" = id;
+ "minimize_window" = id;
+ "next_window" = id;
+ "prefs_changed" = id;
+ "prefs_show" = id;
+ "previous_window" = id;
+ "toggle_fullscreen" = id;
+ "x11_help" = id;
+ "zoom_window" = id;
+ };
+ CLASS = X11Controller;
+ LANGUAGE = ObjC;
+ OUTLETS = {
+ "apps_separator" = id;
+ "apps_table" = id;
+ depth = id;
+ "dock_apps_menu" = id;
+ "dock_menu" = id;
+ "dock_window_separator" = id;
+ "enable_auth" = id;
+ "enable_fullscreen" = id;
+ "enable_keyequivs" = id;
+ "enable_tcp" = id;
+ "fake_buttons" = id;
+ "prefs_panel" = id;
+ "sync_keymap" = id;
+ "toggle_fullscreen_item" = id;
+ "use_sysbeep" = id;
+ "window_separator" = id;
+ "x11_about_item" = id;
+ };
+ SUPERCLASS = NSObject;
+ }
+ );
+ IBVersion = 1;
+}
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>IBDocumentLocation</key>
+ <string>61 48 372 379 0 0 1280 832 </string>
+ <key>IBEditorPositions</key>
+ <dict>
+ <key>29</key>
+ <string>530 771 301 44 0 0 1280 832 </string>
+ <key>423</key>
+ <string>525 668 142 61 0 0 1280 832 </string>
+ </dict>
+ <key>IBFramework Version</key>
+ <string>349.0</string>
+ <key>IBGroupedObjects</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <string>371</string>
+ <string>372</string>
+ </array>
+ <key>1</key>
+ <array>
+ <string>385</string>
+ <string>382</string>
+ <string>386</string>
+ </array>
+ <key>3</key>
+ <array>
+ <string>370</string>
+ <string>369</string>
+ </array>
+ <key>4</key>
+ <array>
+ <string>363</string>
+ <string>365</string>
+ </array>
+ <key>5</key>
+ <array>
+ <string>368</string>
+ <string>364</string>
+ </array>
+ <key>6</key>
+ <array>
+ <string>543</string>
+ <string>541</string>
+ </array>
+ <key>7</key>
+ <array>
+ <string>375</string>
+ <string>377</string>
+ </array>
+ <key>8</key>
+ <array>
+ <string>374</string>
+ <string>376</string>
+ </array>
+ </dict>
+ <key>IBLastGroupID</key>
+ <string>9</string>
+ <key>IBLockedObjects</key>
+ <array>
+ <integer>285</integer>
+ <integer>348</integer>
+ <integer>244</integer>
+ </array>
+ <key>IBOpenObjects</key>
+ <array>
+ <integer>423</integer>
+ <integer>29</integer>
+ <integer>285</integer>
+ <integer>244</integer>
+ </array>
+ <key>IBSystem Version</key>
+ <string>7R28</string>
+</dict>
+</plist>
--- /dev/null
+XCOMM $XFree86: xc/programs/Xserver/hw/darwin/Imakefile,v 1.14 2002/08/28 06:19:15 torrey Exp $
+
+#include <Server.tmpl>
+#define IHaveSubdirs
+
+LinkSourceFile(XFree86.man,../xfree86)
+LinkSourceFile(appledri.h,$(LIBSRC)/GL/apple)
+LinkSourceFile(appledristr.h,$(LIBSRC)/GL/apple)
+
+SRCS = darwin.c \
+ darwin-input.c \
+ darwin-keyboard.c \
+ darwin-new-keymap.c \
+ darwin-old-keymap.c \
+ keysym2ucs.c \
+ quartz.c \
+ quartz-audio.c \
+ quartz-cursor.c \
+ quartz-server.c \
+ rootless-common.c \
+ rootless-gc.c \
+ rootless-picture.c \
+ rootless-screen.c \
+ rootless-val-tree.c \
+ rootless-window.c \
+ pseudoramiX.c \
+ appledri.c \
+ applewm-impl.c \
+ dri-surface.c \
+ x-list.c \
+ x-hash.c \
+ x-hook.c \
+ X11Application.m \
+ X11Controller.m
+
+OBJS = darwin.o \
+ darwin-input.o \
+ darwin-keyboard.o \
+ darwin-new-keymap.o \
+ darwin-old-keymap.o \
+ keysym2ucs.o \
+ quartz.o \
+ quartz-audio.o \
+ quartz-cursor.o \
+ quartz-server.o \
+ rootless-common.o \
+ rootless-gc.o \
+ rootless-picture.o \
+ rootless-screen.o \
+ rootless-val-tree.o \
+ rootless-window.o \
+ pseudoramiX.o \
+ appledri.o \
+ applewm-impl.o \
+ dri-surface.o \
+ x-list.o \
+ x-hash.o \
+ x-hook.o \
+ X11Application.o \
+ X11Controller.o
+
+AS := /System/Library/Frameworks/ApplicationServices.framework
+
+INCLUDES = -I. -I$(SERVERSRC)/mi -I$(SERVERSRC)/fb -I$(EXTINCSRC) \
+ -I$(SERVERSRC)/render -I$(SERVERSRC)/include -I$(XINCLUDESRC) \
+ -I$(SERVERSRC)/os -I$(SERVERSRC)/Xext -I$(SERVERSRC)/GL/apple \
+ -I$(INCLUDESRC) -I$(FONTINCSRC) -F$(AS)/Frameworks \
+ $(XPLUGIN_INCLUDE)
+
+OSNAME = OSName
+OSVENDOR = OSVendor
+OSNAMEDEF = -DOSNAME='" $(OSNAME)"' -DOSVENDOR='" $(OSVENDOR)"'
+
+#if defined(XFree86CustomVersion)
+CUSTOMVERSION = XFree86CustomVersion
+CUSTOMVERDEF = -DXF86_CUSTOM_VERSION='$(CUSTOMVERSION)'
+#endif
+
+#if defined(BuilderString)
+BUILDERSTRING = BuilderString
+BUILDERMSG = -DBUILDERSTRING='$(BUILDERSTRING)'
+#endif
+
+SUBDIRS = utils
+
+DEFINES = $(CUSTOMVERDEF) -DXBINDIR=$(BINDIR) -DXINITDIR=$(XINITDIR) \
+ $(QUARTZDEFINES) $(DEBUGDEFINES)
+
+#if XFree86Devel
+DEBUGDEFINES = -DROOTLESSDEBUG
+#endif
+
+EXTRAMANDEFS = -D__logdir__=$(LOGDIRECTORY)
+
+SpecialCObjectRule(darwin,$(ICONFIGFILES),$(OSNAMEDEF) $(BUILDERMSG) $(CUSTOMVERDEF))
+
+NormalLibraryObjectRule()
+NormalLibraryTarget(XQuartz,$(OBJS))
+
+InstallManPage(Xquartz,$(MANDIR))
+InstallManPage(XFree86,$(MANDIR))
+
+DependTarget()
+
+MakeSubdirs($(SUBDIRS))
+DependSubdirs($(SUBDIRS))
+
+#ifndef DarwinArchEnv
+#define DarwinArchEnv
+#endif
+
+PBXBUILD = DarwinArchEnv pbxbuild
+PBXBUILDSTYLE = Development
+PBXBUILDDIR= ./build
+
+DITTO = ditto
+
+#if NothingOutsideProjectRoot
+APPINSTALLDIR = $(BINDIR)/../Applications
+#else
+APPINSTALLDIR = /Applications/Utilities
+#endif
+
+all::
+ $(PBXBUILD) -buildstyle $(PBXBUILDSTYLE) build
+
+install::
+ $(PBXBUILD) -buildstyle $(PBXBUILDSTYLE) install
+ mkdir -p $(DESTDIR)$(APPINSTALLDIR)
+ $(DITTO) $(PBXBUILDDIR)/UninstalledProducts/X11.app $(DESTDIR)$(APPINSTALLDIR)/X11.app
+
+clean::
+ $(PBXBUILD) 'clean'
+
+%.o : %.m
+ $(CC) $(CFLAGS) -c -o $@ $<
--- /dev/null
+jsh.pbxuser
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>ActivePerspectiveName</key>
+ <string>Project</string>
+ <key>AllowedModules</key>
+ <array>
+ <dict>
+ <key>BundleLoadPath</key>
+ <string></string>
+ <key>MaxInstances</key>
+ <string>n</string>
+ <key>Module</key>
+ <string>PBXSmartGroupTreeModule</string>
+ <key>Name</key>
+ <string>Groups and Files Outline View</string>
+ </dict>
+ <dict>
+ <key>BundleLoadPath</key>
+ <string></string>
+ <key>MaxInstances</key>
+ <string>n</string>
+ <key>Module</key>
+ <string>PBXNavigatorGroup</string>
+ <key>Name</key>
+ <string>Editor</string>
+ </dict>
+ <dict>
+ <key>BundleLoadPath</key>
+ <string></string>
+ <key>MaxInstances</key>
+ <string>n</string>
+ <key>Module</key>
+ <string>XCTaskListModule</string>
+ <key>Name</key>
+ <string>Task List</string>
+ </dict>
+ <dict>
+ <key>BundleLoadPath</key>
+ <string></string>
+ <key>MaxInstances</key>
+ <string>n</string>
+ <key>Module</key>
+ <string>XCDetailModule</string>
+ <key>Name</key>
+ <string>File and Smart Group Detail Viewer</string>
+ </dict>
+ <dict>
+ <key>BundleLoadPath</key>
+ <string></string>
+ <key>MaxInstances</key>
+ <string>1</string>
+ <key>Module</key>
+ <string>PBXBuildResultsModule</string>
+ <key>Name</key>
+ <string>Detailed Build Results Viewer</string>
+ </dict>
+ <dict>
+ <key>BundleLoadPath</key>
+ <string></string>
+ <key>MaxInstances</key>
+ <string>1</string>
+ <key>Module</key>
+ <string>PBXProjectFindModule</string>
+ <key>Name</key>
+ <string>Project Batch Find Tool</string>
+ </dict>
+ <dict>
+ <key>BundleLoadPath</key>
+ <string></string>
+ <key>MaxInstances</key>
+ <string>n</string>
+ <key>Module</key>
+ <string>PBXRunSessionModule</string>
+ <key>Name</key>
+ <string>Run Log</string>
+ </dict>
+ <dict>
+ <key>BundleLoadPath</key>
+ <string></string>
+ <key>MaxInstances</key>
+ <string>n</string>
+ <key>Module</key>
+ <string>PBXBookmarksModule</string>
+ <key>Name</key>
+ <string>Bookmarks Tool</string>
+ </dict>
+ <dict>
+ <key>BundleLoadPath</key>
+ <string></string>
+ <key>MaxInstances</key>
+ <string>n</string>
+ <key>Module</key>
+ <string>PBXClassBrowserModule</string>
+ <key>Name</key>
+ <string>Class Browser</string>
+ </dict>
+ <dict>
+ <key>BundleLoadPath</key>
+ <string></string>
+ <key>MaxInstances</key>
+ <string>n</string>
+ <key>Module</key>
+ <string>PBXCVSModule</string>
+ <key>Name</key>
+ <string>Source Code Control Tool</string>
+ </dict>
+ <dict>
+ <key>BundleLoadPath</key>
+ <string></string>
+ <key>MaxInstances</key>
+ <string>n</string>
+ <key>Module</key>
+ <string>PBXDebugBreakpointsModule</string>
+ <key>Name</key>
+ <string>Debug Breakpoints Tool</string>
+ </dict>
+ <dict>
+ <key>BundleLoadPath</key>
+ <string></string>
+ <key>MaxInstances</key>
+ <string>n</string>
+ <key>Module</key>
+ <string>XCDockableInspector</string>
+ <key>Name</key>
+ <string>Inspector</string>
+ </dict>
+ <dict>
+ <key>BundleLoadPath</key>
+ <string></string>
+ <key>MaxInstances</key>
+ <string>n</string>
+ <key>Module</key>
+ <string>PBXOpenQuicklyModule</string>
+ <key>Name</key>
+ <string>Open Quickly Tool</string>
+ </dict>
+ <dict>
+ <key>BundleLoadPath</key>
+ <string></string>
+ <key>MaxInstances</key>
+ <string>1</string>
+ <key>Module</key>
+ <string>PBXDebugSessionModule</string>
+ <key>Name</key>
+ <string>Debugger</string>
+ </dict>
+ <dict>
+ <key>BundleLoadPath</key>
+ <string></string>
+ <key>MaxInstances</key>
+ <string>1</string>
+ <key>Module</key>
+ <string>PBXDebugCLIModule</string>
+ <key>Name</key>
+ <string>Debug Console</string>
+ </dict>
+ </array>
+ <key>Description</key>
+ <string>DefaultDescriptionKey</string>
+ <key>DockingSystemVisible</key>
+ <false/>
+ <key>Extension</key>
+ <string>mode1</string>
+ <key>FavBarConfig</key>
+ <dict>
+ <key>PBXProjectModuleGUID</key>
+ <string>A66420E408E74B62005A12D3</string>
+ <key>XCBarModuleItemNames</key>
+ <dict/>
+ <key>XCBarModuleItems</key>
+ <array/>
+ </dict>
+ <key>FirstTimeWindowDisplayed</key>
+ <false/>
+ <key>Identifier</key>
+ <string>com.apple.perspectives.project.mode1</string>
+ <key>MajorVersion</key>
+ <integer>31</integer>
+ <key>MinorVersion</key>
+ <integer>1</integer>
+ <key>Name</key>
+ <string>Default</string>
+ <key>Notifications</key>
+ <array/>
+ <key>OpenEditors</key>
+ <array>
+ <dict>
+ <key>Content</key>
+ <dict>
+ <key>PBXProjectModuleGUID</key>
+ <string>A664210208E74CC8005A12D3</string>
+ <key>PBXProjectModuleLabel</key>
+ <string>Target: SynfigStudio</string>
+ <key>PBXSplitModuleInNavigatorKey</key>
+ <dict>
+ <key>Split0</key>
+ <dict>
+ <key>PBXProjectModuleGUID</key>
+ <string>A664210308E74CC8005A12D3</string>
+ <key>PBXProjectModuleLabel</key>
+ <string>Target: SynfigStudio</string>
+ <key>_historyCapacity</key>
+ <integer>0</integer>
+ <key>bookmark</key>
+ <string>A664210908E77262005A12D3</string>
+ <key>history</key>
+ <array>
+ <string>A664210408E74CC8005A12D3</string>
+ </array>
+ </dict>
+ <key>SplitCount</key>
+ <string>1</string>
+ </dict>
+ <key>StatusBarVisibility</key>
+ <true/>
+ </dict>
+ <key>Geometry</key>
+ <dict>
+ <key>Frame</key>
+ <string>{{0, 20}, {784, 658}}</string>
+ <key>PBXModuleWindowStatusBarHidden2</key>
+ <false/>
+ <key>RubberWindowFrame</key>
+ <string>42 107 784 699 0 0 1280 832 </string>
+ </dict>
+ </dict>
+ </array>
+ <key>PerspectiveWidths</key>
+ <array>
+ <integer>-1</integer>
+ <integer>-1</integer>
+ </array>
+ <key>Perspectives</key>
+ <array>
+ <dict>
+ <key>ChosenToolbarItems</key>
+ <array>
+ <string>active-target-popup</string>
+ <string>active-buildstyle-popup</string>
+ <string>action</string>
+ <string>NSToolbarFlexibleSpaceItem</string>
+ <string>build-and-debug</string>
+ <string>buildOrClean</string>
+ <string>get-info</string>
+ <string>toggle-editor</string>
+ <string>servicesModuleCVS</string>
+ <string>NSToolbarFlexibleSpaceItem</string>
+ <string>com.apple.pbx.toolbar.searchfield</string>
+ </array>
+ <key>ControllerClassBaseName</key>
+ <string></string>
+ <key>IconName</key>
+ <string>WindowOfProjectWithEditor</string>
+ <key>Identifier</key>
+ <string>perspective.project</string>
+ <key>IsVertical</key>
+ <false/>
+ <key>Layout</key>
+ <array>
+ <dict>
+ <key>BecomeActive</key>
+ <true/>
+ <key>ContentConfiguration</key>
+ <dict>
+ <key>PBXBottomSmartGroupGIDs</key>
+ <array>
+ <string>1C37FBAC04509CD000000102</string>
+ <string>1C37FAAC04509CD000000102</string>
+ <string>1C08E77C0454961000C914BD</string>
+ <string>1C37FABC05509CD000000102</string>
+ <string>1C37FABC05539CD112110102</string>
+ <string>E2644B35053B69B200211256</string>
+ <string>1C37FABC04509CD000100104</string>
+ <string>1CC0EA4004350EF90044410B</string>
+ <string>1CC0EA4004350EF90041110B</string>
+ </array>
+ <key>PBXProjectModuleGUID</key>
+ <string>1CE0B1FE06471DED0097A5F4</string>
+ <key>PBXProjectModuleLabel</key>
+ <string>Files</string>
+ <key>PBXProjectStructureProvided</key>
+ <string>yes</string>
+ <key>PBXSmartGroupTreeModuleColumnData</key>
+ <dict>
+ <key>PBXSmartGroupTreeModuleColumnWidthsKey</key>
+ <array>
+ <real>186</real>
+ </array>
+ <key>PBXSmartGroupTreeModuleColumnsKey_v4</key>
+ <array>
+ <string>MainColumn</string>
+ </array>
+ </dict>
+ <key>PBXSmartGroupTreeModuleOutlineStateKey_v7</key>
+ <dict>
+ <key>PBXSmartGroupTreeModuleOutlineStateExpansionKey</key>
+ <array>
+ <string>20286C29FDCF999611CA2CEA</string>
+ <string>20286C2CFDCF999611CA2CEA</string>
+ <string>02345980000FD03B11CA0E72</string>
+ <string>1C37FBAC04509CD000000102</string>
+ <string>1C08E77C0454961000C914BD</string>
+ <string>1C37FABC05509CD000000102</string>
+ </array>
+ <key>PBXSmartGroupTreeModuleOutlineStateSelectionKey</key>
+ <array>
+ <array>
+ <integer>7</integer>
+ <integer>2</integer>
+ <integer>0</integer>
+ </array>
+ </array>
+ <key>PBXSmartGroupTreeModuleOutlineStateVisibleRectKey</key>
+ <string>{{0, 0}, {186, 617}}</string>
+ </dict>
+ <key>PBXTopSmartGroupGIDs</key>
+ <array/>
+ <key>XCIncludePerspectivesSwitch</key>
+ <true/>
+ <key>XCSharingToken</key>
+ <string>com.apple.Xcode.GFSharingToken</string>
+ </dict>
+ <key>GeometryConfiguration</key>
+ <dict>
+ <key>Frame</key>
+ <string>{{0, 0}, {203, 635}}</string>
+ <key>GroupTreeTableConfiguration</key>
+ <array>
+ <string>MainColumn</string>
+ <real>186</real>
+ </array>
+ <key>RubberWindowFrame</key>
+ <string>297 92 845 676 0 0 1280 832 </string>
+ </dict>
+ <key>Module</key>
+ <string>PBXSmartGroupTreeModule</string>
+ <key>Proportion</key>
+ <string>203pt</string>
+ </dict>
+ <dict>
+ <key>Dock</key>
+ <array>
+ <dict>
+ <key>ContentConfiguration</key>
+ <dict>
+ <key>PBXProjectModuleGUID</key>
+ <string>1CE0B20306471E060097A5F4</string>
+ <key>PBXProjectModuleLabel</key>
+ <string>bundle-main.c</string>
+ <key>PBXSplitModuleInNavigatorKey</key>
+ <dict>
+ <key>Split0</key>
+ <dict>
+ <key>PBXProjectModuleGUID</key>
+ <string>1CE0B20406471E060097A5F4</string>
+ <key>PBXProjectModuleLabel</key>
+ <string>bundle-main.c</string>
+ <key>_historyCapacity</key>
+ <integer>0</integer>
+ <key>bookmark</key>
+ <string>A664210808E77262005A12D3</string>
+ <key>history</key>
+ <array>
+ <string>A66420F808E74CC8005A12D3</string>
+ <string>A66420F908E74CC8005A12D3</string>
+ <string>A66420FA08E74CC8005A12D3</string>
+ <string>A66420FB08E74CC8005A12D3</string>
+ </array>
+ <key>prevStack</key>
+ <array>
+ <string>A66420FC08E74CC8005A12D3</string>
+ <string>A66420FD08E74CC8005A12D3</string>
+ <string>A66420FE08E74CC8005A12D3</string>
+ <string>A66420FF08E74CC8005A12D3</string>
+ <string>A664210008E74CC8005A12D3</string>
+ </array>
+ </dict>
+ <key>SplitCount</key>
+ <string>1</string>
+ </dict>
+ <key>StatusBarVisibility</key>
+ <true/>
+ </dict>
+ <key>GeometryConfiguration</key>
+ <dict>
+ <key>Frame</key>
+ <string>{{0, 0}, {637, 384}}</string>
+ <key>RubberWindowFrame</key>
+ <string>297 92 845 676 0 0 1280 832 </string>
+ </dict>
+ <key>Module</key>
+ <string>PBXNavigatorGroup</string>
+ <key>Proportion</key>
+ <string>384pt</string>
+ </dict>
+ <dict>
+ <key>ContentConfiguration</key>
+ <dict>
+ <key>PBXProjectModuleGUID</key>
+ <string>1CE0B20506471E060097A5F4</string>
+ <key>PBXProjectModuleLabel</key>
+ <string>Detail</string>
+ </dict>
+ <key>GeometryConfiguration</key>
+ <dict>
+ <key>Frame</key>
+ <string>{{0, 389}, {637, 246}}</string>
+ <key>RubberWindowFrame</key>
+ <string>297 92 845 676 0 0 1280 832 </string>
+ </dict>
+ <key>Module</key>
+ <string>XCDetailModule</string>
+ <key>Proportion</key>
+ <string>246pt</string>
+ </dict>
+ </array>
+ <key>Proportion</key>
+ <string>637pt</string>
+ </dict>
+ </array>
+ <key>Name</key>
+ <string>Project</string>
+ <key>ServiceClasses</key>
+ <array>
+ <string>XCModuleDock</string>
+ <string>PBXSmartGroupTreeModule</string>
+ <string>XCModuleDock</string>
+ <string>PBXNavigatorGroup</string>
+ <string>XCDetailModule</string>
+ </array>
+ <key>TableOfContents</key>
+ <array>
+ <string>A66420E208E74B62005A12D3</string>
+ <string>1CE0B1FE06471DED0097A5F4</string>
+ <string>A66420E308E74B62005A12D3</string>
+ <string>1CE0B20306471E060097A5F4</string>
+ <string>1CE0B20506471E060097A5F4</string>
+ </array>
+ <key>ToolbarConfiguration</key>
+ <string>xcode.toolbar.config.default</string>
+ </dict>
+ <dict>
+ <key>ControllerClassBaseName</key>
+ <string></string>
+ <key>IconName</key>
+ <string>WindowOfProject</string>
+ <key>Identifier</key>
+ <string>perspective.morph</string>
+ <key>IsVertical</key>
+ <integer>0</integer>
+ <key>Layout</key>
+ <array>
+ <dict>
+ <key>BecomeActive</key>
+ <integer>1</integer>
+ <key>ContentConfiguration</key>
+ <dict>
+ <key>PBXBottomSmartGroupGIDs</key>
+ <array>
+ <string>1C37FBAC04509CD000000102</string>
+ <string>1C37FAAC04509CD000000102</string>
+ <string>1C08E77C0454961000C914BD</string>
+ <string>1C37FABC05509CD000000102</string>
+ <string>1C37FABC05539CD112110102</string>
+ <string>E2644B35053B69B200211256</string>
+ <string>1C37FABC04509CD000100104</string>
+ <string>1CC0EA4004350EF90044410B</string>
+ <string>1CC0EA4004350EF90041110B</string>
+ </array>
+ <key>PBXProjectModuleGUID</key>
+ <string>11E0B1FE06471DED0097A5F4</string>
+ <key>PBXProjectModuleLabel</key>
+ <string>Files</string>
+ <key>PBXProjectStructureProvided</key>
+ <string>yes</string>
+ <key>PBXSmartGroupTreeModuleColumnData</key>
+ <dict>
+ <key>PBXSmartGroupTreeModuleColumnWidthsKey</key>
+ <array>
+ <real>186</real>
+ </array>
+ <key>PBXSmartGroupTreeModuleColumnsKey_v4</key>
+ <array>
+ <string>MainColumn</string>
+ </array>
+ </dict>
+ <key>PBXSmartGroupTreeModuleOutlineStateKey_v7</key>
+ <dict>
+ <key>PBXSmartGroupTreeModuleOutlineStateExpansionKey</key>
+ <array>
+ <string>29B97314FDCFA39411CA2CEA</string>
+ <string>1C37FABC05509CD000000102</string>
+ </array>
+ <key>PBXSmartGroupTreeModuleOutlineStateSelectionKey</key>
+ <array>
+ <array>
+ <integer>0</integer>
+ </array>
+ </array>
+ <key>PBXSmartGroupTreeModuleOutlineStateVisibleRectKey</key>
+ <string>{{0, 0}, {186, 337}}</string>
+ </dict>
+ <key>PBXTopSmartGroupGIDs</key>
+ <array/>
+ <key>XCIncludePerspectivesSwitch</key>
+ <integer>1</integer>
+ <key>XCSharingToken</key>
+ <string>com.apple.Xcode.GFSharingToken</string>
+ </dict>
+ <key>GeometryConfiguration</key>
+ <dict>
+ <key>Frame</key>
+ <string>{{0, 0}, {203, 355}}</string>
+ <key>GroupTreeTableConfiguration</key>
+ <array>
+ <string>MainColumn</string>
+ <real>186</real>
+ </array>
+ <key>RubberWindowFrame</key>
+ <string>373 269 690 397 0 0 1440 878 </string>
+ </dict>
+ <key>Module</key>
+ <string>PBXSmartGroupTreeModule</string>
+ <key>Proportion</key>
+ <string>100%</string>
+ </dict>
+ </array>
+ <key>Name</key>
+ <string>Morph</string>
+ <key>PreferredWidth</key>
+ <integer>300</integer>
+ <key>ServiceClasses</key>
+ <array>
+ <string>XCModuleDock</string>
+ <string>PBXSmartGroupTreeModule</string>
+ </array>
+ <key>TableOfContents</key>
+ <array>
+ <string>11E0B1FE06471DED0097A5F4</string>
+ </array>
+ <key>ToolbarConfiguration</key>
+ <string>xcode.toolbar.config.default.short</string>
+ </dict>
+ </array>
+ <key>PerspectivesBarVisible</key>
+ <false/>
+ <key>ShelfIsVisible</key>
+ <false/>
+ <key>SourceDescription</key>
+ <string>file at '/System/Library/PrivateFrameworks/DevToolsInterface.framework/Versions/A/Resources/XCPerspectivesSpecificationMode1.xcperspec'</string>
+ <key>StatusbarIsVisible</key>
+ <true/>
+ <key>TimeStamp</key>
+ <real>0.0</real>
+ <key>ToolbarDisplayMode</key>
+ <integer>2</integer>
+ <key>ToolbarIsVisible</key>
+ <true/>
+ <key>ToolbarSizeMode</key>
+ <integer>2</integer>
+ <key>Type</key>
+ <string>Perspectives</string>
+ <key>UpdateMessage</key>
+ <string>The Default Workspace in this version of Xcode now includes support to hide and show the detail view (what has been referred to as the "Metro-Morph" feature). You must discard your current Default Workspace settings and update to the latest Default Workspace in order to gain this feature. Do you wish to update to the latest Workspace defaults for project '%@'?</string>
+ <key>WindowJustification</key>
+ <integer>5</integer>
+ <key>WindowOrderList</key>
+ <array>
+ <string>A66420EE08E74B62005A12D3</string>
+ <string>A66420EF08E74B62005A12D3</string>
+ <string>A66420EC08E74B62005A12D3</string>
+ <string>A66420EB08E74B62005A12D3</string>
+ <string>1CD10A99069EF8BA00B06720</string>
+ <string>/Users/darco/Projects/X11App/Synfig Studio.pbproj</string>
+ <string>A664210208E74CC8005A12D3</string>
+ </array>
+ <key>WindowString</key>
+ <string>297 92 845 676 0 0 1280 832 </string>
+ <key>WindowTools</key>
+ <array>
+ <dict>
+ <key>Identifier</key>
+ <string>windowTool.build</string>
+ <key>Layout</key>
+ <array>
+ <dict>
+ <key>Dock</key>
+ <array>
+ <dict>
+ <key>ContentConfiguration</key>
+ <dict>
+ <key>PBXProjectModuleGUID</key>
+ <string>1CD0528F0623707200166675</string>
+ <key>PBXProjectModuleLabel</key>
+ <string><No Editor></string>
+ <key>PBXSplitModuleInNavigatorKey</key>
+ <dict>
+ <key>Split0</key>
+ <dict>
+ <key>PBXProjectModuleGUID</key>
+ <string>1CD052900623707200166675</string>
+ </dict>
+ <key>SplitCount</key>
+ <string>1</string>
+ </dict>
+ <key>StatusBarVisibility</key>
+ <integer>1</integer>
+ </dict>
+ <key>GeometryConfiguration</key>
+ <dict>
+ <key>Frame</key>
+ <string>{{0, 0}, {500, 215}}</string>
+ <key>RubberWindowFrame</key>
+ <string>192 257 500 500 0 0 1280 1002 </string>
+ </dict>
+ <key>Module</key>
+ <string>PBXNavigatorGroup</string>
+ <key>Proportion</key>
+ <string>218pt</string>
+ </dict>
+ <dict>
+ <key>BecomeActive</key>
+ <integer>1</integer>
+ <key>ContentConfiguration</key>
+ <dict>
+ <key>PBXProjectModuleGUID</key>
+ <string>XCMainBuildResultsModuleGUID</string>
+ <key>PBXProjectModuleLabel</key>
+ <string>Build</string>
+ </dict>
+ <key>GeometryConfiguration</key>
+ <dict>
+ <key>Frame</key>
+ <string>{{0, 222}, {500, 236}}</string>
+ <key>RubberWindowFrame</key>
+ <string>192 257 500 500 0 0 1280 1002 </string>
+ </dict>
+ <key>Module</key>
+ <string>PBXBuildResultsModule</string>
+ <key>Proportion</key>
+ <string>236pt</string>
+ </dict>
+ </array>
+ <key>Proportion</key>
+ <string>458pt</string>
+ </dict>
+ </array>
+ <key>Name</key>
+ <string>Build Results</string>
+ <key>ServiceClasses</key>
+ <array>
+ <string>PBXBuildResultsModule</string>
+ </array>
+ <key>StatusbarIsVisible</key>
+ <integer>1</integer>
+ <key>TableOfContents</key>
+ <array>
+ <string>1C78EAA5065D492600B07095</string>
+ <string>1C78EAA6065D492600B07095</string>
+ <string>1CD0528F0623707200166675</string>
+ <string>XCMainBuildResultsModuleGUID</string>
+ </array>
+ <key>ToolbarConfiguration</key>
+ <string>xcode.toolbar.config.build</string>
+ <key>WindowString</key>
+ <string>192 257 500 500 0 0 1280 1002 </string>
+ </dict>
+ <dict>
+ <key>FirstTimeWindowDisplayed</key>
+ <false/>
+ <key>Identifier</key>
+ <string>windowTool.debugger</string>
+ <key>IsVertical</key>
+ <true/>
+ <key>Layout</key>
+ <array>
+ <dict>
+ <key>Dock</key>
+ <array>
+ <dict>
+ <key>ContentConfiguration</key>
+ <dict>
+ <key>Debugger</key>
+ <dict>
+ <key>HorizontalSplitView</key>
+ <dict>
+ <key>_collapsingFrameDimension</key>
+ <real>0.0</real>
+ <key>_indexOfCollapsedView</key>
+ <integer>0</integer>
+ <key>_percentageOfCollapsedView</key>
+ <real>0.0</real>
+ <key>isCollapsed</key>
+ <string>yes</string>
+ <key>sizes</key>
+ <array>
+ <string>{{0, 0}, {305, 162}}</string>
+ <string>{{305, 0}, {389, 162}}</string>
+ </array>
+ </dict>
+ <key>VerticalSplitView</key>
+ <dict>
+ <key>_collapsingFrameDimension</key>
+ <real>0.0</real>
+ <key>_indexOfCollapsedView</key>
+ <integer>0</integer>
+ <key>_percentageOfCollapsedView</key>
+ <real>0.0</real>
+ <key>isCollapsed</key>
+ <string>yes</string>
+ <key>sizes</key>
+ <array>
+ <string>{{0, 0}, {694, 162}}</string>
+ <string>{{0, 162}, {694, 219}}</string>
+ </array>
+ </dict>
+ </dict>
+ <key>LauncherConfigVersion</key>
+ <string>8</string>
+ <key>PBXProjectModuleGUID</key>
+ <string>1C162984064C10D400B95A72</string>
+ <key>PBXProjectModuleLabel</key>
+ <string>Debug - GLUTExamples (Underwater)</string>
+ </dict>
+ <key>GeometryConfiguration</key>
+ <dict>
+ <key>DebugConsoleDrawerSize</key>
+ <string>{100, 120}</string>
+ <key>DebugConsoleVisible</key>
+ <string>None</string>
+ <key>DebugConsoleWindowFrame</key>
+ <string>{{200, 200}, {500, 300}}</string>
+ <key>DebugSTDIOWindowFrame</key>
+ <string>{{200, 200}, {500, 300}}</string>
+ <key>Frame</key>
+ <string>{{0, 0}, {694, 381}}</string>
+ <key>RubberWindowFrame</key>
+ <string>318 323 694 422 0 0 1280 832 </string>
+ </dict>
+ <key>Module</key>
+ <string>PBXDebugSessionModule</string>
+ <key>Proportion</key>
+ <string>381pt</string>
+ </dict>
+ </array>
+ <key>Proportion</key>
+ <string>381pt</string>
+ </dict>
+ </array>
+ <key>Name</key>
+ <string>Debugger</string>
+ <key>ServiceClasses</key>
+ <array>
+ <string>PBXDebugSessionModule</string>
+ </array>
+ <key>StatusbarIsVisible</key>
+ <true/>
+ <key>TableOfContents</key>
+ <array>
+ <string>1CD10A99069EF8BA00B06720</string>
+ <string>A66420E508E74B62005A12D3</string>
+ <string>1C162984064C10D400B95A72</string>
+ <string>A66420E608E74B62005A12D3</string>
+ <string>A66420E708E74B62005A12D3</string>
+ <string>A66420E808E74B62005A12D3</string>
+ <string>A66420E908E74B62005A12D3</string>
+ <string>A66420EA08E74B62005A12D3</string>
+ <string>A66420EB08E74B62005A12D3</string>
+ </array>
+ <key>ToolbarConfiguration</key>
+ <string>xcode.toolbar.config.debug</string>
+ <key>WindowString</key>
+ <string>318 323 694 422 0 0 1280 832 </string>
+ <key>WindowToolGUID</key>
+ <string>1CD10A99069EF8BA00B06720</string>
+ <key>WindowToolIsVisible</key>
+ <true/>
+ </dict>
+ <dict>
+ <key>Identifier</key>
+ <string>windowTool.find</string>
+ <key>Layout</key>
+ <array>
+ <dict>
+ <key>Dock</key>
+ <array>
+ <dict>
+ <key>Dock</key>
+ <array>
+ <dict>
+ <key>ContentConfiguration</key>
+ <dict>
+ <key>PBXProjectModuleGUID</key>
+ <string>1CDD528C0622207200134675</string>
+ <key>PBXProjectModuleLabel</key>
+ <string><No Editor></string>
+ <key>PBXSplitModuleInNavigatorKey</key>
+ <dict>
+ <key>Split0</key>
+ <dict>
+ <key>PBXProjectModuleGUID</key>
+ <string>1CD0528D0623707200166675</string>
+ </dict>
+ <key>SplitCount</key>
+ <string>1</string>
+ </dict>
+ <key>StatusBarVisibility</key>
+ <integer>1</integer>
+ </dict>
+ <key>GeometryConfiguration</key>
+ <dict>
+ <key>Frame</key>
+ <string>{{0, 0}, {781, 167}}</string>
+ <key>RubberWindowFrame</key>
+ <string>62 385 781 470 0 0 1440 878 </string>
+ </dict>
+ <key>Module</key>
+ <string>PBXNavigatorGroup</string>
+ <key>Proportion</key>
+ <string>781pt</string>
+ </dict>
+ </array>
+ <key>Proportion</key>
+ <string>50%</string>
+ </dict>
+ <dict>
+ <key>BecomeActive</key>
+ <integer>1</integer>
+ <key>ContentConfiguration</key>
+ <dict>
+ <key>PBXProjectModuleGUID</key>
+ <string>1CD0528E0623707200166675</string>
+ <key>PBXProjectModuleLabel</key>
+ <string>Project Find</string>
+ </dict>
+ <key>GeometryConfiguration</key>
+ <dict>
+ <key>Frame</key>
+ <string>{{8, 0}, {773, 254}}</string>
+ <key>RubberWindowFrame</key>
+ <string>62 385 781 470 0 0 1440 878 </string>
+ </dict>
+ <key>Module</key>
+ <string>PBXProjectFindModule</string>
+ <key>Proportion</key>
+ <string>50%</string>
+ </dict>
+ </array>
+ <key>Proportion</key>
+ <string>428pt</string>
+ </dict>
+ </array>
+ <key>Name</key>
+ <string>Project Find</string>
+ <key>ServiceClasses</key>
+ <array>
+ <string>PBXProjectFindModule</string>
+ </array>
+ <key>StatusbarIsVisible</key>
+ <integer>1</integer>
+ <key>TableOfContents</key>
+ <array>
+ <string>1C530D57069F1CE1000CFCEE</string>
+ <string>1C530D58069F1CE1000CFCEE</string>
+ <string>1C530D59069F1CE1000CFCEE</string>
+ <string>1CDD528C0622207200134675</string>
+ <string>1C530D5A069F1CE1000CFCEE</string>
+ <string>1CE0B1FE06471DED0097A5F4</string>
+ <string>1CD0528E0623707200166675</string>
+ </array>
+ <key>WindowString</key>
+ <string>62 385 781 470 0 0 1440 878 </string>
+ <key>WindowToolGUID</key>
+ <string>1C530D57069F1CE1000CFCEE</string>
+ <key>WindowToolIsVisible</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>Identifier</key>
+ <string>MENUSEPARATOR</string>
+ </dict>
+ <dict>
+ <key>FirstTimeWindowDisplayed</key>
+ <false/>
+ <key>Identifier</key>
+ <string>windowTool.debuggerConsole</string>
+ <key>IsVertical</key>
+ <true/>
+ <key>Layout</key>
+ <array>
+ <dict>
+ <key>Dock</key>
+ <array>
+ <dict>
+ <key>ContentConfiguration</key>
+ <dict>
+ <key>PBXProjectModuleGUID</key>
+ <string>1C78EAAC065D492600B07095</string>
+ <key>PBXProjectModuleLabel</key>
+ <string>Debugger Console</string>
+ </dict>
+ <key>GeometryConfiguration</key>
+ <dict>
+ <key>Frame</key>
+ <string>{{0, 0}, {440, 358}}</string>
+ <key>RubberWindowFrame</key>
+ <string>339 322 440 400 0 0 1280 832 </string>
+ </dict>
+ <key>Module</key>
+ <string>PBXDebugCLIModule</string>
+ <key>Proportion</key>
+ <string>358pt</string>
+ </dict>
+ </array>
+ <key>Proportion</key>
+ <string>359pt</string>
+ </dict>
+ </array>
+ <key>Name</key>
+ <string>Debugger Console</string>
+ <key>ServiceClasses</key>
+ <array>
+ <string>PBXDebugCLIModule</string>
+ </array>
+ <key>StatusbarIsVisible</key>
+ <true/>
+ <key>TableOfContents</key>
+ <array>
+ <string>A66420EC08E74B62005A12D3</string>
+ <string>A66420ED08E74B62005A12D3</string>
+ <string>1C78EAAC065D492600B07095</string>
+ </array>
+ <key>WindowString</key>
+ <string>339 322 440 400 0 0 1280 832 </string>
+ <key>WindowToolGUID</key>
+ <string>A66420EC08E74B62005A12D3</string>
+ <key>WindowToolIsVisible</key>
+ <false/>
+ </dict>
+ <dict>
+ <key>Identifier</key>
+ <string>windowTool.run</string>
+ <key>Layout</key>
+ <array>
+ <dict>
+ <key>Dock</key>
+ <array>
+ <dict>
+ <key>ContentConfiguration</key>
+ <dict>
+ <key>LauncherConfigVersion</key>
+ <string>3</string>
+ <key>PBXProjectModuleGUID</key>
+ <string>1CD0528B0623707200166675</string>
+ <key>PBXProjectModuleLabel</key>
+ <string>Run</string>
+ <key>Runner</key>
+ <dict>
+ <key>HorizontalSplitView</key>
+ <dict>
+ <key>_collapsingFrameDimension</key>
+ <real>0.0</real>
+ <key>_indexOfCollapsedView</key>
+ <integer>0</integer>
+ <key>_percentageOfCollapsedView</key>
+ <real>0.0</real>
+ <key>isCollapsed</key>
+ <string>yes</string>
+ <key>sizes</key>
+ <array>
+ <string>{{0, 0}, {493, 167}}</string>
+ <string>{{0, 176}, {493, 267}}</string>
+ </array>
+ </dict>
+ <key>VerticalSplitView</key>
+ <dict>
+ <key>_collapsingFrameDimension</key>
+ <real>0.0</real>
+ <key>_indexOfCollapsedView</key>
+ <integer>0</integer>
+ <key>_percentageOfCollapsedView</key>
+ <real>0.0</real>
+ <key>isCollapsed</key>
+ <string>yes</string>
+ <key>sizes</key>
+ <array>
+ <string>{{0, 0}, {405, 443}}</string>
+ <string>{{414, 0}, {514, 443}}</string>
+ </array>
+ </dict>
+ </dict>
+ </dict>
+ <key>GeometryConfiguration</key>
+ <dict>
+ <key>Frame</key>
+ <string>{{0, 0}, {460, 159}}</string>
+ <key>RubberWindowFrame</key>
+ <string>316 696 459 200 0 0 1280 1002 </string>
+ </dict>
+ <key>Module</key>
+ <string>PBXRunSessionModule</string>
+ <key>Proportion</key>
+ <string>159pt</string>
+ </dict>
+ </array>
+ <key>Proportion</key>
+ <string>159pt</string>
+ </dict>
+ </array>
+ <key>Name</key>
+ <string>Run Log</string>
+ <key>ServiceClasses</key>
+ <array>
+ <string>PBXRunSessionModule</string>
+ </array>
+ <key>StatusbarIsVisible</key>
+ <integer>1</integer>
+ <key>TableOfContents</key>
+ <array>
+ <string>1C0AD2B3069F1EA900FABCE6</string>
+ <string>1C0AD2B4069F1EA900FABCE6</string>
+ <string>1CD0528B0623707200166675</string>
+ <string>1C0AD2B5069F1EA900FABCE6</string>
+ </array>
+ <key>ToolbarConfiguration</key>
+ <string>xcode.toolbar.config.run</string>
+ <key>WindowString</key>
+ <string>316 696 459 200 0 0 1280 1002 </string>
+ <key>WindowToolGUID</key>
+ <string>1C0AD2B3069F1EA900FABCE6</string>
+ <key>WindowToolIsVisible</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>Identifier</key>
+ <string>windowTool.scm</string>
+ <key>Layout</key>
+ <array>
+ <dict>
+ <key>Dock</key>
+ <array>
+ <dict>
+ <key>ContentConfiguration</key>
+ <dict>
+ <key>PBXProjectModuleGUID</key>
+ <string>1C78EAB2065D492600B07095</string>
+ <key>PBXProjectModuleLabel</key>
+ <string><No Editor></string>
+ <key>PBXSplitModuleInNavigatorKey</key>
+ <dict>
+ <key>Split0</key>
+ <dict>
+ <key>PBXProjectModuleGUID</key>
+ <string>1C78EAB3065D492600B07095</string>
+ </dict>
+ <key>SplitCount</key>
+ <string>1</string>
+ </dict>
+ <key>StatusBarVisibility</key>
+ <integer>1</integer>
+ </dict>
+ <key>GeometryConfiguration</key>
+ <dict>
+ <key>Frame</key>
+ <string>{{0, 0}, {452, 0}}</string>
+ <key>RubberWindowFrame</key>
+ <string>743 379 452 308 0 0 1280 1002 </string>
+ </dict>
+ <key>Module</key>
+ <string>PBXNavigatorGroup</string>
+ <key>Proportion</key>
+ <string>0pt</string>
+ </dict>
+ <dict>
+ <key>BecomeActive</key>
+ <integer>1</integer>
+ <key>ContentConfiguration</key>
+ <dict>
+ <key>PBXProjectModuleGUID</key>
+ <string>1CD052920623707200166675</string>
+ <key>PBXProjectModuleLabel</key>
+ <string>SCM</string>
+ </dict>
+ <key>GeometryConfiguration</key>
+ <dict>
+ <key>ConsoleFrame</key>
+ <string>{{0, 259}, {452, 0}}</string>
+ <key>Frame</key>
+ <string>{{0, 7}, {452, 259}}</string>
+ <key>RubberWindowFrame</key>
+ <string>743 379 452 308 0 0 1280 1002 </string>
+ <key>TableConfiguration</key>
+ <array>
+ <string>Status</string>
+ <real>30</real>
+ <string>FileName</string>
+ <real>199</real>
+ <string>Path</string>
+ <real>197.09500122070312</real>
+ </array>
+ <key>TableFrame</key>
+ <string>{{0, 0}, {452, 250}}</string>
+ </dict>
+ <key>Module</key>
+ <string>PBXCVSModule</string>
+ <key>Proportion</key>
+ <string>262pt</string>
+ </dict>
+ </array>
+ <key>Proportion</key>
+ <string>266pt</string>
+ </dict>
+ </array>
+ <key>Name</key>
+ <string>SCM</string>
+ <key>ServiceClasses</key>
+ <array>
+ <string>PBXCVSModule</string>
+ </array>
+ <key>StatusbarIsVisible</key>
+ <integer>1</integer>
+ <key>TableOfContents</key>
+ <array>
+ <string>1C78EAB4065D492600B07095</string>
+ <string>1C78EAB5065D492600B07095</string>
+ <string>1C78EAB2065D492600B07095</string>
+ <string>1CD052920623707200166675</string>
+ </array>
+ <key>ToolbarConfiguration</key>
+ <string>xcode.toolbar.config.scm</string>
+ <key>WindowString</key>
+ <string>743 379 452 308 0 0 1280 1002 </string>
+ </dict>
+ <dict>
+ <key>Identifier</key>
+ <string>windowTool.breakpoints</string>
+ <key>Layout</key>
+ <array>
+ <dict>
+ <key>Dock</key>
+ <array>
+ <dict>
+ <key>BecomeActive</key>
+ <integer>1</integer>
+ <key>ContentConfiguration</key>
+ <dict>
+ <key>PBXProjectModuleGUID</key>
+ <string>1CD052930623707200166675</string>
+ <key>PBXProjectModuleLabel</key>
+ <string>Breakpoints</string>
+ </dict>
+ <key>GeometryConfiguration</key>
+ <dict>
+ <key>BreakpointsTreeTableConfiguration</key>
+ <array>
+ <string>enabledColumn</string>
+ <real>16</real>
+ <string>breakpointColumn</string>
+ <real>201.5830078125</real>
+ </array>
+ <key>Frame</key>
+ <string>{{0, 0}, {240, 195}}</string>
+ <key>RubberWindowFrame</key>
+ <string>342 421 240 216 0 0 1440 878 </string>
+ </dict>
+ <key>Module</key>
+ <string>PBXDebugBreakpointsModule</string>
+ <key>Proportion</key>
+ <string>195pt</string>
+ </dict>
+ </array>
+ <key>Proportion</key>
+ <string>195pt</string>
+ </dict>
+ </array>
+ <key>Name</key>
+ <string>Breakpoints</string>
+ <key>ServiceClasses</key>
+ <array>
+ <string>PBXDebugBreakpointsModule</string>
+ </array>
+ <key>StatusbarIsVisible</key>
+ <integer>0</integer>
+ <key>TableOfContents</key>
+ <array>
+ <string>1C0AD2AD069F1E9B00FABCE6</string>
+ <string>1C0AD2AE069F1E9B00FABCE6</string>
+ <string>1CD052930623707200166675</string>
+ </array>
+ <key>WindowString</key>
+ <string>342 421 240 216 0 0 1440 878 </string>
+ <key>WindowToolGUID</key>
+ <string>1C0AD2AD069F1E9B00FABCE6</string>
+ <key>WindowToolIsVisible</key>
+ <integer>0</integer>
+ </dict>
+ <dict>
+ <key>Identifier</key>
+ <string>windowTool.bookmarks</string>
+ <key>Layout</key>
+ <array>
+ <dict>
+ <key>Dock</key>
+ <array>
+ <dict>
+ <key>Module</key>
+ <string>PBXBookmarksModule</string>
+ <key>Proportion</key>
+ <string>100%</string>
+ </dict>
+ </array>
+ <key>Proportion</key>
+ <string>100%</string>
+ </dict>
+ </array>
+ <key>Name</key>
+ <string>Bookmarks</string>
+ <key>ServiceClasses</key>
+ <array>
+ <string>PBXBookmarksModule</string>
+ </array>
+ <key>StatusbarIsVisible</key>
+ <integer>0</integer>
+ <key>WindowString</key>
+ <string>538 42 401 187 0 0 1280 1002 </string>
+ </dict>
+ <dict>
+ <key>Identifier</key>
+ <string>windowTool.classBrowser</string>
+ <key>Layout</key>
+ <array>
+ <dict>
+ <key>Dock</key>
+ <array>
+ <dict>
+ <key>BecomeActive</key>
+ <integer>1</integer>
+ <key>ContentConfiguration</key>
+ <dict>
+ <key>OptionsSetName</key>
+ <string>Hierarchy, all classes</string>
+ <key>PBXProjectModuleGUID</key>
+ <string>1CA6456E063B45B4001379D8</string>
+ <key>PBXProjectModuleLabel</key>
+ <string>Class Browser - NSObject</string>
+ </dict>
+ <key>GeometryConfiguration</key>
+ <dict>
+ <key>ClassesFrame</key>
+ <string>{{0, 0}, {374, 96}}</string>
+ <key>ClassesTreeTableConfiguration</key>
+ <array>
+ <string>PBXClassNameColumnIdentifier</string>
+ <real>208</real>
+ <string>PBXClassBookColumnIdentifier</string>
+ <real>22</real>
+ </array>
+ <key>Frame</key>
+ <string>{{0, 0}, {630, 331}}</string>
+ <key>MembersFrame</key>
+ <string>{{0, 105}, {374, 395}}</string>
+ <key>MembersTreeTableConfiguration</key>
+ <array>
+ <string>PBXMemberTypeIconColumnIdentifier</string>
+ <real>22</real>
+ <string>PBXMemberNameColumnIdentifier</string>
+ <real>216</real>
+ <string>PBXMemberTypeColumnIdentifier</string>
+ <real>97</real>
+ <string>PBXMemberBookColumnIdentifier</string>
+ <real>22</real>
+ </array>
+ <key>PBXModuleWindowStatusBarHidden2</key>
+ <integer>1</integer>
+ <key>RubberWindowFrame</key>
+ <string>385 179 630 352 0 0 1440 878 </string>
+ </dict>
+ <key>Module</key>
+ <string>PBXClassBrowserModule</string>
+ <key>Proportion</key>
+ <string>332pt</string>
+ </dict>
+ </array>
+ <key>Proportion</key>
+ <string>332pt</string>
+ </dict>
+ </array>
+ <key>Name</key>
+ <string>Class Browser</string>
+ <key>ServiceClasses</key>
+ <array>
+ <string>PBXClassBrowserModule</string>
+ </array>
+ <key>StatusbarIsVisible</key>
+ <integer>0</integer>
+ <key>TableOfContents</key>
+ <array>
+ <string>1C0AD2AF069F1E9B00FABCE6</string>
+ <string>1C0AD2B0069F1E9B00FABCE6</string>
+ <string>1CA6456E063B45B4001379D8</string>
+ </array>
+ <key>ToolbarConfiguration</key>
+ <string>xcode.toolbar.config.classbrowser</string>
+ <key>WindowString</key>
+ <string>385 179 630 352 0 0 1440 878 </string>
+ <key>WindowToolGUID</key>
+ <string>1C0AD2AF069F1E9B00FABCE6</string>
+ <key>WindowToolIsVisible</key>
+ <integer>0</integer>
+ </dict>
+ </array>
+</dict>
+</plist>
--- /dev/null
+// !$*UTF8*$!
+{
+ 20286C28FDCF999611CA2CEA = {
+ activeBuildStyle = 4A9504C5FFE6A39111CA0CBA;
+ activeExecutable = A65E397F07515B8200A66E82;
+ activeTarget = 20286C34FDCF999611CA2CEA;
+ addToTargets = (
+ 20286C34FDCF999611CA2CEA,
+ );
+ codeSenseManager = A66420E108E74B3D005A12D3;
+ executables = (
+ A65E397F07515B8200A66E82,
+ );
+ perUserDictionary = {
+ PBXConfiguration.PBXFileTableDataSource3.PBXErrorsWarningsDataSource = {
+ PBXFileTableDataSourceColumnSortingDirectionKey = "-1";
+ PBXFileTableDataSourceColumnSortingKey = PBXErrorsWarningsDataSource_MessageID;
+ PBXFileTableDataSourceColumnWidthsKey = (
+ 20,
+ 300,
+ 200,
+ );
+ PBXFileTableDataSourceColumnsKey = (
+ PBXErrorsWarningsDataSource_TypeID,
+ PBXErrorsWarningsDataSource_MessageID,
+ PBXErrorsWarningsDataSource_LocationID,
+ );
+ };
+ PBXConfiguration.PBXFileTableDataSource3.PBXFileTableDataSource = {
+ PBXFileTableDataSourceColumnSortingDirectionKey = "-1";
+ PBXFileTableDataSourceColumnSortingKey = PBXFileDataSource_Filename_ColumnID;
+ PBXFileTableDataSourceColumnWidthsKey = (
+ 20,
+ 398,
+ 20,
+ 48,
+ 43,
+ 43,
+ 20,
+ );
+ PBXFileTableDataSourceColumnsKey = (
+ PBXFileDataSource_FiletypeID,
+ PBXFileDataSource_Filename_ColumnID,
+ PBXFileDataSource_Built_ColumnID,
+ PBXFileDataSource_ObjectSize_ColumnID,
+ PBXFileDataSource_Errors_ColumnID,
+ PBXFileDataSource_Warnings_ColumnID,
+ PBXFileDataSource_Target_ColumnID,
+ );
+ };
+ PBXConfiguration.PBXTargetDataSource.PBXTargetDataSource = {
+ PBXFileTableDataSourceColumnSortingDirectionKey = "-1";
+ PBXFileTableDataSourceColumnSortingKey = PBXFileDataSource_Filename_ColumnID;
+ PBXFileTableDataSourceColumnWidthsKey = (
+ 20,
+ 200,
+ 218,
+ 20,
+ 48.1626,
+ 43,
+ 43,
+ );
+ PBXFileTableDataSourceColumnsKey = (
+ PBXFileDataSource_FiletypeID,
+ PBXFileDataSource_Filename_ColumnID,
+ PBXTargetDataSource_PrimaryAttribute,
+ PBXFileDataSource_Built_ColumnID,
+ PBXFileDataSource_ObjectSize_ColumnID,
+ PBXFileDataSource_Errors_ColumnID,
+ PBXFileDataSource_Warnings_ColumnID,
+ );
+ };
+ PBXPerProjectTemplateStateSaveDate = 149375796;
+ "PBXTemplateGeometry-F5CA7ECB015C094F0DCA290F" = {
+ ContentSize = "{668, 621}";
+ LeftSlideOut = {
+ Collapsed = NO;
+ Frame = "{{0, 0}, {668, 621}}";
+ Split0 = {
+ Collapsed = NO;
+ Frame = "{{0, 0}, {668, 621}}";
+ Split0 = {
+ Frame = "{{0, 0}, {668, 621}}";
+ };
+ SplitCount = 1;
+ Tab0 = {
+ Frame = "{{0, 0}, {484, 208}}";
+ };
+ Tab1 = {
+ Debugger = {
+ Collapsed = NO;
+ Frame = "{{0, 0}, {664, 208}}";
+ Split0 = {
+ Frame = "{{0, 24}, {664, 184}}";
+ Split0 = {
+ Frame = "{{0, 0}, {325, 184}}";
+ };
+ Split1 = {
+ DebugVariablesTableConfiguration = (
+ Name,
+ 123,
+ Value,
+ 85,
+ Summary,
+ 96.123,
+ );
+ Frame = "{{334, 0}, {330, 184}}";
+ };
+ SplitCount = 2;
+ };
+ SplitCount = 1;
+ Tab0 = {
+ Frame = "{{0, 0}, {100, 50}}";
+ };
+ Tab1 = {
+ Frame = "{{0, 0}, {100, 50}}";
+ };
+ TabCount = 2;
+ TabsVisible = YES;
+ };
+ Frame = "{{0, 0}, {664, 208}}";
+ LauncherConfigVersion = 7;
+ };
+ Tab2 = {
+ Frame = "{{0, 0}, {664, 50}}";
+ LauncherConfigVersion = 3;
+ Runner = {
+ Frame = "{{0, 0}, {664, 50}}";
+ };
+ };
+ Tab3 = {
+ BuildMessageFrame = "{{0, 0}, {614, 203}}";
+ BuildTranscriptFrame = "{{0, 212}, {614, 85}}";
+ BuildTranscriptFrameExpanded = YES;
+ Frame = "{{0, 0}, {612, 295}}";
+ };
+ Tab4 = {
+ Frame = "{{0, 0}, {612, 295}}";
+ };
+ TabCount = 5;
+ TabsVisible = NO;
+ };
+ SplitCount = 1;
+ Tab0 = {
+ Frame = "{{0, 0}, {313, 531}}";
+ GroupTreeTableConfiguration = (
+ TargetStatusColumn,
+ 18,
+ MainColumn,
+ 280,
+ );
+ };
+ Tab1 = {
+ ClassesFrame = "{{0, 0}, {280, 398}}";
+ ClassesTreeTableConfiguration = (
+ PBXBookColumnIdentifier,
+ 20,
+ PBXClassColumnIdentifier,
+ 237,
+ );
+ Frame = "{{0, 0}, {278, 659}}";
+ MembersFrame = "{{0, 407}, {280, 252}}";
+ MembersTreeTableConfiguration = (
+ PBXBookColumnIdentifier,
+ 20,
+ PBXMethodColumnIdentifier,
+ 236,
+ );
+ };
+ Tab2 = {
+ Frame = "{{0, 0}, {200, 100}}";
+ };
+ Tab3 = {
+ Frame = "{{0, 0}, {200, 557}}";
+ TargetTableConfiguration = (
+ ActiveObject,
+ 16,
+ ObjectNames,
+ 202.296,
+ );
+ };
+ Tab4 = {
+ BreakpointsTreeTableConfiguration = (
+ breakpointColumn,
+ 197,
+ enabledColumn,
+ 31,
+ );
+ Frame = "{{0, 0}, {250, 100}}";
+ };
+ TabCount = 5;
+ TabsVisible = NO;
+ };
+ NavBarShownByDefault = YES;
+ StatusViewVisible = NO;
+ Template = F5CA7ECB015C094F0DCA290F;
+ ToolbarVisible = NO;
+ WindowLocation = "{425, 95}";
+ };
+ PBXWorkspaceContents = (
+ {
+ LeftSlideOut = {
+ Split0 = {
+ Split0 = {
+ NavContent0 = {
+ bookmark = A65E48C007518C4E00A66E82;
+ history = (
+ A65E3D3907515FE000A66E82,
+ A65E488907518C4E00A66E82,
+ A65E488A07518C4E00A66E82,
+ A65E488B07518C4E00A66E82,
+ A65E488C07518C4E00A66E82,
+ A65E488D07518C4E00A66E82,
+ A65E488E07518C4E00A66E82,
+ A65E488F07518C4E00A66E82,
+ A65E489007518C4E00A66E82,
+ A65E489107518C4E00A66E82,
+ A65E489207518C4E00A66E82,
+ A65E489307518C4E00A66E82,
+ A65E489407518C4E00A66E82,
+ A65E489507518C4E00A66E82,
+ A65E489607518C4E00A66E82,
+ A65E489707518C4E00A66E82,
+ A65E489807518C4E00A66E82,
+ A65E489907518C4E00A66E82,
+ );
+ prevStack = (
+ A65E3D3B07515FE000A66E82,
+ A65E3D3C07515FE000A66E82,
+ A65E3D3D07515FE000A66E82,
+ A65E3D3E07515FE000A66E82,
+ A65E3D3F07515FE000A66E82,
+ A65E3D4007515FE000A66E82,
+ A65E3D4107515FE000A66E82,
+ A65E489A07518C4E00A66E82,
+ A65E489B07518C4E00A66E82,
+ A65E489C07518C4E00A66E82,
+ A65E489D07518C4E00A66E82,
+ A65E489E07518C4E00A66E82,
+ A65E489F07518C4E00A66E82,
+ A65E48A007518C4E00A66E82,
+ A65E48A107518C4E00A66E82,
+ A65E48A207518C4E00A66E82,
+ A65E48A307518C4E00A66E82,
+ A65E48A407518C4E00A66E82,
+ A65E48A507518C4E00A66E82,
+ A65E48A607518C4E00A66E82,
+ A65E48A707518C4E00A66E82,
+ A65E48A807518C4E00A66E82,
+ A65E48A907518C4E00A66E82,
+ A65E48AA07518C4E00A66E82,
+ A65E48AB07518C4E00A66E82,
+ A65E48AC07518C4E00A66E82,
+ A65E48AD07518C4E00A66E82,
+ A65E48AE07518C4E00A66E82,
+ A65E48AF07518C4E00A66E82,
+ A65E48B007518C4E00A66E82,
+ A65E48B107518C4E00A66E82,
+ A65E48B207518C4E00A66E82,
+ A65E48B307518C4E00A66E82,
+ A65E48B407518C4E00A66E82,
+ A65E48B507518C4E00A66E82,
+ A65E48B607518C4E00A66E82,
+ A65E48B707518C4E00A66E82,
+ A65E48B807518C4E00A66E82,
+ A65E48B907518C4E00A66E82,
+ A65E48BA07518C4E00A66E82,
+ A65E48BB07518C4E00A66E82,
+ A65E48BC07518C4E00A66E82,
+ A65E48BD07518C4E00A66E82,
+ A65E48BE07518C4E00A66E82,
+ A65E48BF07518C4E00A66E82,
+ );
+ };
+ NavCount = 1;
+ NavGeometry0 = {
+ Frame = "{{0, 0}, {819, 439}}";
+ NavBarVisible = YES;
+ };
+ NavSplitVertical = NO;
+ };
+ SplitCount = 1;
+ Tab1 = {
+ Debugger = {
+ Split0 = {
+ SplitCount = 2;
+ };
+ SplitCount = 1;
+ TabCount = 2;
+ };
+ LauncherConfigVersion = 7;
+ };
+ Tab2 = {
+ LauncherConfigVersion = 3;
+ Runner = {
+ };
+ };
+ TabCount = 5;
+ };
+ SplitCount = 1;
+ Tab1 = {
+ OptionsSetName = "Hierarchy, all classes";
+ };
+ TabCount = 5;
+ };
+ },
+ {
+ LeftSlideOut = {
+ Split0 = {
+ Split0 = {
+ NavContent0 = {
+ bookmark = A65E48C207518C4E00A66E82;
+ history = (
+ A65E48C107518C4E00A66E82,
+ );
+ };
+ NavCount = 1;
+ NavGeometry0 = {
+ Frame = "{{0, 0}, {668, 621}}";
+ NavBarVisible = YES;
+ };
+ NavSplitVertical = NO;
+ };
+ SplitCount = 1;
+ Tab1 = {
+ Debugger = {
+ Split0 = {
+ SplitCount = 2;
+ };
+ SplitCount = 1;
+ TabCount = 2;
+ };
+ LauncherConfigVersion = 7;
+ };
+ Tab2 = {
+ LauncherConfigVersion = 3;
+ Runner = {
+ };
+ };
+ TabCount = 5;
+ };
+ SplitCount = 1;
+ Tab1 = {
+ OptionsSetName = "Hierarchy, all classes";
+ };
+ TabCount = 5;
+ };
+ },
+ {
+ LeftSlideOut = {
+ Split0 = {
+ Split0 = {
+ NavContent0 = {
+ bookmark = A65E48C407518C4E00A66E82;
+ history = (
+ A65E48C307518C4E00A66E82,
+ );
+ };
+ NavCount = 1;
+ NavGeometry0 = {
+ Frame = "{{0, 0}, {668, 621}}";
+ NavBarVisible = YES;
+ };
+ NavSplitVertical = NO;
+ };
+ SplitCount = 1;
+ Tab1 = {
+ Debugger = {
+ Split0 = {
+ SplitCount = 2;
+ };
+ SplitCount = 1;
+ TabCount = 2;
+ };
+ LauncherConfigVersion = 7;
+ };
+ Tab2 = {
+ LauncherConfigVersion = 3;
+ Runner = {
+ };
+ };
+ TabCount = 5;
+ };
+ SplitCount = 1;
+ Tab1 = {
+ OptionsSetName = "Hierarchy, all classes";
+ };
+ TabCount = 5;
+ };
+ },
+ {
+ LeftSlideOut = {
+ Split0 = {
+ Split0 = {
+ NavContent0 = {
+ bookmark = A65E48C607518C4E00A66E82;
+ history = (
+ A65E48C507518C4E00A66E82,
+ );
+ };
+ NavCount = 1;
+ NavGeometry0 = {
+ Frame = "{{0, 0}, {668, 621}}";
+ NavBarVisible = YES;
+ };
+ NavSplitVertical = NO;
+ };
+ SplitCount = 1;
+ Tab1 = {
+ Debugger = {
+ Split0 = {
+ SplitCount = 2;
+ };
+ SplitCount = 1;
+ TabCount = 2;
+ };
+ LauncherConfigVersion = 7;
+ };
+ Tab2 = {
+ LauncherConfigVersion = 3;
+ Runner = {
+ };
+ };
+ TabCount = 5;
+ };
+ SplitCount = 1;
+ Tab1 = {
+ OptionsSetName = "Hierarchy, all classes";
+ };
+ TabCount = 5;
+ };
+ },
+ );
+ PBXWorkspaceGeometries = (
+ {
+ ContentSize = "{1103, 612}";
+ LeftSlideOut = {
+ ActiveTab = 0;
+ ActiveTabName = PBXGroupTreeModule;
+ Collapsed = NO;
+ Frame = "{{0, 23}, {1103, 589}}";
+ Split0 = {
+ ActiveTab = 1;
+ ActiveTabName = PBXRunSessionModule;
+ Collapsed = NO;
+ Frame = "{{284, 0}, {819, 589}}";
+ Split0 = {
+ Frame = "{{0, 150}, {819, 439}}";
+ };
+ SplitCount = 1;
+ Tab0 = {
+ Frame = "{{0, 0}, {572, 214}}";
+ };
+ Tab1 = {
+ Debugger = {
+ Collapsed = NO;
+ Frame = "{{0, 0}, {572, 150}}";
+ Split0 = {
+ Frame = "{{0, 24}, {572, 126}}";
+ Split0 = {
+ Frame = "{{0, 0}, {279, 126}}";
+ };
+ Split1 = {
+ DebugVariablesTableConfiguration = (
+ Name,
+ 123,
+ Value,
+ 85,
+ Summary,
+ 62.123,
+ );
+ Frame = "{{288, 0}, {284, 126}}";
+ };
+ SplitCount = 2;
+ };
+ SplitCount = 1;
+ Tab0 = {
+ Frame = "{{0, 0}, {100, 50}}";
+ };
+ Tab1 = {
+ Frame = "{{0, 0}, {100, 50}}";
+ };
+ TabCount = 2;
+ TabsVisible = YES;
+ };
+ Frame = "{{0, 0}, {572, 125}}";
+ LauncherConfigVersion = 7;
+ };
+ Tab2 = {
+ Frame = "{{0, 0}, {819, 126}}";
+ LauncherConfigVersion = 3;
+ Runner = {
+ Frame = "{{0, 0}, {819, 126}}";
+ };
+ };
+ Tab3 = {
+ BuildMessageFrame = "{{0, 0}, {821, 165}}";
+ BuildTranscriptFrame = "{{0, 174}, {821, 69}}";
+ BuildTranscriptFrameExpanded = YES;
+ Frame = "{{0, 0}, {819, 265}}";
+ };
+ Tab4 = {
+ Frame = "{{0, 0}, {819, 295}}";
+ };
+ TabCount = 5;
+ TabsVisible = YES;
+ };
+ SplitCount = 1;
+ Tab0 = {
+ Frame = "{{0, 0}, {260, 589}}";
+ GroupTreeTableConfiguration = (
+ TargetStatusColumn,
+ 18,
+ MainColumn,
+ 227,
+ );
+ };
+ Tab1 = {
+ ClassesFrame = "{{0, 0}, {247, 330}}";
+ ClassesTreeTableConfiguration = (
+ PBXBookColumnIdentifier,
+ 20,
+ PBXClassColumnIdentifier,
+ 204,
+ );
+ Frame = "{{0, 0}, {245, 549}}";
+ MembersFrame = "{{0, 339}, {247, 210}}";
+ MembersTreeTableConfiguration = (
+ PBXBookColumnIdentifier,
+ 20,
+ PBXMethodColumnIdentifier,
+ 203,
+ );
+ };
+ Tab2 = {
+ Frame = "{{0, 0}, {226, 549}}";
+ };
+ Tab3 = {
+ Frame = "{{0, 0}, {191, 589}}";
+ TargetTableConfiguration = (
+ ActiveObject,
+ 16,
+ ObjectNames,
+ 202.296,
+ );
+ };
+ Tab4 = {
+ BreakpointsTreeTableConfiguration = (
+ breakpointColumn,
+ 138,
+ enabledColumn,
+ 31,
+ );
+ Frame = "{{0, 0}, {191, 549}}";
+ };
+ TabCount = 5;
+ TabsVisible = YES;
+ };
+ NavBarShownByDefault = YES;
+ StatusViewVisible = YES;
+ Template = F5F68CF101725D4C0D7A8F4C;
+ ToolbarVisible = YES;
+ WindowLocation = "{123, 29}";
+ },
+ {
+ ContentSize = "{668, 621}";
+ LeftSlideOut = {
+ Collapsed = NO;
+ Frame = "{{0, 0}, {668, 621}}";
+ Split0 = {
+ Collapsed = NO;
+ Frame = "{{0, 0}, {668, 621}}";
+ Split0 = {
+ Frame = "{{0, 0}, {668, 621}}";
+ };
+ SplitCount = 1;
+ Tab0 = {
+ Frame = "{{0, 0}, {484, 208}}";
+ };
+ Tab1 = {
+ Debugger = {
+ Collapsed = NO;
+ Frame = "{{0, 0}, {664, 208}}";
+ Split0 = {
+ Frame = "{{0, 24}, {664, 184}}";
+ Split0 = {
+ Frame = "{{0, 0}, {325, 184}}";
+ };
+ Split1 = {
+ DebugVariablesTableConfiguration = (
+ Name,
+ 123,
+ Value,
+ 85,
+ Summary,
+ 96.123,
+ );
+ Frame = "{{334, 0}, {330, 184}}";
+ };
+ SplitCount = 2;
+ };
+ SplitCount = 1;
+ Tab0 = {
+ Frame = "{{0, 0}, {100, 50}}";
+ };
+ Tab1 = {
+ Frame = "{{0, 0}, {100, 50}}";
+ };
+ TabCount = 2;
+ TabsVisible = YES;
+ };
+ Frame = "{{0, 0}, {664, 208}}";
+ LauncherConfigVersion = 7;
+ };
+ Tab2 = {
+ Frame = "{{0, 0}, {664, 50}}";
+ LauncherConfigVersion = 3;
+ Runner = {
+ Frame = "{{0, 0}, {664, 50}}";
+ };
+ };
+ Tab3 = {
+ BuildMessageFrame = "{{0, 0}, {614, 203}}";
+ BuildTranscriptFrame = "{{0, 212}, {614, 85}}";
+ BuildTranscriptFrameExpanded = YES;
+ Frame = "{{0, 0}, {612, 295}}";
+ };
+ Tab4 = {
+ Frame = "{{0, 0}, {612, 295}}";
+ };
+ TabCount = 5;
+ TabsVisible = NO;
+ };
+ SplitCount = 1;
+ Tab0 = {
+ Frame = "{{0, 0}, {313, 531}}";
+ GroupTreeTableConfiguration = (
+ TargetStatusColumn,
+ 18,
+ MainColumn,
+ 280,
+ );
+ };
+ Tab1 = {
+ ClassesFrame = "{{0, 0}, {280, 398}}";
+ ClassesTreeTableConfiguration = (
+ PBXBookColumnIdentifier,
+ 20,
+ PBXClassColumnIdentifier,
+ 237,
+ );
+ Frame = "{{0, 0}, {278, 659}}";
+ MembersFrame = "{{0, 407}, {280, 252}}";
+ MembersTreeTableConfiguration = (
+ PBXBookColumnIdentifier,
+ 20,
+ PBXMethodColumnIdentifier,
+ 236,
+ );
+ };
+ Tab2 = {
+ Frame = "{{0, 0}, {200, 100}}";
+ };
+ Tab3 = {
+ Frame = "{{0, 0}, {200, 557}}";
+ TargetTableConfiguration = (
+ ActiveObject,
+ 16,
+ ObjectNames,
+ 202.296,
+ );
+ };
+ Tab4 = {
+ BreakpointsTreeTableConfiguration = (
+ breakpointColumn,
+ 197,
+ enabledColumn,
+ 31,
+ );
+ Frame = "{{0, 0}, {250, 100}}";
+ };
+ TabCount = 5;
+ TabsVisible = NO;
+ };
+ NavBarShownByDefault = YES;
+ StatusViewVisible = NO;
+ Template = F5CA7ECB015C094F0DCA290F;
+ ToolbarVisible = NO;
+ WindowLocation = "{357, 158}";
+ },
+ {
+ ContentSize = "{668, 621}";
+ LeftSlideOut = {
+ Collapsed = NO;
+ Frame = "{{0, 0}, {668, 621}}";
+ Split0 = {
+ Collapsed = NO;
+ Frame = "{{0, 0}, {668, 621}}";
+ Split0 = {
+ Frame = "{{0, 0}, {668, 621}}";
+ };
+ SplitCount = 1;
+ Tab0 = {
+ Frame = "{{0, 0}, {484, 208}}";
+ };
+ Tab1 = {
+ Debugger = {
+ Collapsed = NO;
+ Frame = "{{0, 0}, {664, 208}}";
+ Split0 = {
+ Frame = "{{0, 24}, {664, 184}}";
+ Split0 = {
+ Frame = "{{0, 0}, {325, 184}}";
+ };
+ Split1 = {
+ DebugVariablesTableConfiguration = (
+ Name,
+ 123,
+ Value,
+ 85,
+ Summary,
+ 96.123,
+ );
+ Frame = "{{334, 0}, {330, 184}}";
+ };
+ SplitCount = 2;
+ };
+ SplitCount = 1;
+ Tab0 = {
+ Frame = "{{0, 0}, {100, 50}}";
+ };
+ Tab1 = {
+ Frame = "{{0, 0}, {100, 50}}";
+ };
+ TabCount = 2;
+ TabsVisible = YES;
+ };
+ Frame = "{{0, 0}, {664, 208}}";
+ LauncherConfigVersion = 7;
+ };
+ Tab2 = {
+ Frame = "{{0, 0}, {664, 50}}";
+ LauncherConfigVersion = 3;
+ Runner = {
+ Frame = "{{0, 0}, {664, 50}}";
+ };
+ };
+ Tab3 = {
+ BuildMessageFrame = "{{0, 0}, {614, 203}}";
+ BuildTranscriptFrame = "{{0, 212}, {614, 85}}";
+ BuildTranscriptFrameExpanded = YES;
+ Frame = "{{0, 0}, {612, 295}}";
+ };
+ Tab4 = {
+ Frame = "{{0, 0}, {612, 295}}";
+ };
+ TabCount = 5;
+ TabsVisible = NO;
+ };
+ SplitCount = 1;
+ Tab0 = {
+ Frame = "{{0, 0}, {313, 531}}";
+ GroupTreeTableConfiguration = (
+ TargetStatusColumn,
+ 18,
+ MainColumn,
+ 280,
+ );
+ };
+ Tab1 = {
+ ClassesFrame = "{{0, 0}, {280, 398}}";
+ ClassesTreeTableConfiguration = (
+ PBXBookColumnIdentifier,
+ 20,
+ PBXClassColumnIdentifier,
+ 237,
+ );
+ Frame = "{{0, 0}, {278, 659}}";
+ MembersFrame = "{{0, 407}, {280, 252}}";
+ MembersTreeTableConfiguration = (
+ PBXBookColumnIdentifier,
+ 20,
+ PBXMethodColumnIdentifier,
+ 236,
+ );
+ };
+ Tab2 = {
+ Frame = "{{0, 0}, {200, 100}}";
+ };
+ Tab3 = {
+ Frame = "{{0, 0}, {200, 557}}";
+ TargetTableConfiguration = (
+ ActiveObject,
+ 16,
+ ObjectNames,
+ 202.296,
+ );
+ };
+ Tab4 = {
+ BreakpointsTreeTableConfiguration = (
+ breakpointColumn,
+ 197,
+ enabledColumn,
+ 31,
+ );
+ Frame = "{{0, 0}, {250, 100}}";
+ };
+ TabCount = 5;
+ TabsVisible = NO;
+ };
+ NavBarShownByDefault = YES;
+ StatusViewVisible = NO;
+ Template = F5CA7ECB015C094F0DCA290F;
+ ToolbarVisible = NO;
+ WindowLocation = "{380, 137}";
+ },
+ {
+ ContentSize = "{668, 621}";
+ LeftSlideOut = {
+ Collapsed = NO;
+ Frame = "{{0, 0}, {668, 621}}";
+ Split0 = {
+ Collapsed = NO;
+ Frame = "{{0, 0}, {668, 621}}";
+ Split0 = {
+ Frame = "{{0, 0}, {668, 621}}";
+ };
+ SplitCount = 1;
+ Tab0 = {
+ Frame = "{{0, 0}, {484, 208}}";
+ };
+ Tab1 = {
+ Debugger = {
+ Collapsed = NO;
+ Frame = "{{0, 0}, {664, 208}}";
+ Split0 = {
+ Frame = "{{0, 24}, {664, 184}}";
+ Split0 = {
+ Frame = "{{0, 0}, {325, 184}}";
+ };
+ Split1 = {
+ DebugVariablesTableConfiguration = (
+ Name,
+ 123,
+ Value,
+ 85,
+ Summary,
+ 96.123,
+ );
+ Frame = "{{334, 0}, {330, 184}}";
+ };
+ SplitCount = 2;
+ };
+ SplitCount = 1;
+ Tab0 = {
+ Frame = "{{0, 0}, {100, 50}}";
+ };
+ Tab1 = {
+ Frame = "{{0, 0}, {100, 50}}";
+ };
+ TabCount = 2;
+ TabsVisible = YES;
+ };
+ Frame = "{{0, 0}, {664, 208}}";
+ LauncherConfigVersion = 7;
+ };
+ Tab2 = {
+ Frame = "{{0, 0}, {664, 50}}";
+ LauncherConfigVersion = 3;
+ Runner = {
+ Frame = "{{0, 0}, {664, 50}}";
+ };
+ };
+ Tab3 = {
+ BuildMessageFrame = "{{0, 0}, {614, 203}}";
+ BuildTranscriptFrame = "{{0, 212}, {614, 85}}";
+ BuildTranscriptFrameExpanded = YES;
+ Frame = "{{0, 0}, {612, 295}}";
+ };
+ Tab4 = {
+ Frame = "{{0, 0}, {612, 295}}";
+ };
+ TabCount = 5;
+ TabsVisible = NO;
+ };
+ SplitCount = 1;
+ Tab0 = {
+ Frame = "{{0, 0}, {313, 531}}";
+ GroupTreeTableConfiguration = (
+ TargetStatusColumn,
+ 18,
+ MainColumn,
+ 280,
+ );
+ };
+ Tab1 = {
+ ClassesFrame = "{{0, 0}, {280, 398}}";
+ ClassesTreeTableConfiguration = (
+ PBXBookColumnIdentifier,
+ 20,
+ PBXClassColumnIdentifier,
+ 237,
+ );
+ Frame = "{{0, 0}, {278, 659}}";
+ MembersFrame = "{{0, 407}, {280, 252}}";
+ MembersTreeTableConfiguration = (
+ PBXBookColumnIdentifier,
+ 20,
+ PBXMethodColumnIdentifier,
+ 236,
+ );
+ };
+ Tab2 = {
+ Frame = "{{0, 0}, {200, 100}}";
+ };
+ Tab3 = {
+ Frame = "{{0, 0}, {200, 557}}";
+ TargetTableConfiguration = (
+ ActiveObject,
+ 16,
+ ObjectNames,
+ 202.296,
+ );
+ };
+ Tab4 = {
+ BreakpointsTreeTableConfiguration = (
+ breakpointColumn,
+ 197,
+ enabledColumn,
+ 31,
+ );
+ Frame = "{{0, 0}, {250, 100}}";
+ };
+ TabCount = 5;
+ TabsVisible = NO;
+ };
+ NavBarShownByDefault = YES;
+ StatusViewVisible = NO;
+ Template = F5CA7ECB015C094F0DCA290F;
+ ToolbarVisible = NO;
+ WindowLocation = "{403, 116}";
+ },
+ );
+ PBXWorkspaceStateSaveDate = 149375796;
+ };
+ perUserProjectItems = {
+ A66420F808E74CC8005A12D3 = A66420F808E74CC8005A12D3;
+ A66420F908E74CC8005A12D3 = A66420F908E74CC8005A12D3;
+ A66420FA08E74CC8005A12D3 = A66420FA08E74CC8005A12D3;
+ A66420FB08E74CC8005A12D3 = A66420FB08E74CC8005A12D3;
+ A66420FC08E74CC8005A12D3 = A66420FC08E74CC8005A12D3;
+ A66420FD08E74CC8005A12D3 = A66420FD08E74CC8005A12D3;
+ A66420FE08E74CC8005A12D3 = A66420FE08E74CC8005A12D3;
+ A66420FF08E74CC8005A12D3 = A66420FF08E74CC8005A12D3;
+ A664210008E74CC8005A12D3 = A664210008E74CC8005A12D3;
+ A664210408E74CC8005A12D3 = A664210408E74CC8005A12D3;
+ A664210808E77262005A12D3 = A664210808E77262005A12D3;
+ A664210908E77262005A12D3 = A664210908E77262005A12D3;
+ };
+ sourceControlManager = A66420E008E74B3D005A12D3;
+ userBuildSettings = {
+ };
+ };
+ 20286C34FDCF999611CA2CEA = {
+ activeExec = 0;
+ executables = (
+ A65E397F07515B8200A66E82,
+ );
+ };
+ 50EE2AB703849F0B0ECA21EC = {
+ uiCtxt = {
+ sepNavIntBoundsRect = "{{0, 0}, {596, 12726}}";
+ sepNavSelRange = "{19522, 64}";
+ sepNavVisRect = "{{0, 12081}, {596, 352}}";
+ sepNavWindowFrame = "{{19, 72}, {784, 755}}";
+ };
+ };
+ A65E397F07515B8200A66E82 = {
+ activeArgIndex = 2147483647;
+ activeArgIndices = (
+ );
+ argumentStrings = (
+ );
+ configStateDict = {
+ "PBXLSLaunchAction-0" = {
+ PBXLSLaunchAction = 0;
+ PBXLSLaunchStartAction = 1;
+ PBXLSLaunchStdioStyle = 1;
+ PBXLSLaunchStyle = 0;
+ class = PBXLSRunLaunchConfig;
+ identifier = com.apple.ProjectBuilder.launch.runConfig;
+ remoteHostInfo = "";
+ startActionInfo = "";
+ };
+ };
+ cppStopOnCatchEnabled = 0;
+ cppStopOnThrowEnabled = 0;
+ customDataFormattersEnabled = 1;
+ debuggerPlugin = GDBDebugging;
+ disassemblyDisplayState = 0;
+ dylibVariantSuffix = "";
+ enableDebugStr = 1;
+ environmentEntries = (
+ );
+ executableSystemSymbolLevel = 0;
+ executableUserSymbolLevel = 0;
+ isa = PBXExecutable;
+ libgmallocEnabled = 0;
+ name = SynfigStudio;
+ savedGlobals = {
+ };
+ shlibInfoDictList = (
+ );
+ shlibInfoDictList_v2 = (
+ {
+ level = 0;
+ path = /usr/lib/system/libmathCommon.A.dylib;
+ whenToLoad = 0;
+ },
+ {
+ level = 0;
+ path = /usr/lib/libSystem.B.dylib;
+ whenToLoad = 0;
+ },
+ {
+ level = 0;
+ path = /usr/X11R6/lib/libX11.6.2.dylib;
+ whenToLoad = 0;
+ },
+ {
+ level = 0;
+ path = /usr/lib/libicucore.A.dylib;
+ whenToLoad = 0;
+ },
+ {
+ level = 0;
+ path = /usr/lib/libauto.dylib;
+ whenToLoad = 0;
+ },
+ {
+ level = 0;
+ path = /usr/lib/libobjc.A.dylib;
+ whenToLoad = 0;
+ },
+ {
+ level = 0;
+ path = /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation;
+ whenToLoad = 0;
+ },
+ {
+ level = 0;
+ path = /System/Library/Frameworks/SystemConfiguration.framework/Versions/A/SystemConfiguration;
+ whenToLoad = 0;
+ },
+ {
+ level = 0;
+ path = /usr/lib/libz.1.2.3.dylib;
+ whenToLoad = 0;
+ },
+ {
+ level = 0;
+ path = /System/Library/Frameworks/IOKit.framework/Versions/A/IOKit;
+ whenToLoad = 0;
+ },
+ {
+ level = 0;
+ path = /System/Library/Frameworks/Security.framework/Versions/A/Security;
+ whenToLoad = 0;
+ },
+ {
+ level = 0;
+ path = /System/Library/Frameworks/DiskArbitration.framework/Versions/A/DiskArbitration;
+ whenToLoad = 0;
+ },
+ {
+ level = 0;
+ path = /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/CarbonCore.framework/Versions/A/CarbonCore;
+ whenToLoad = 0;
+ },
+ {
+ level = 0;
+ path = /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/OSServices.framework/Versions/A/OSServices;
+ whenToLoad = 0;
+ },
+ {
+ level = 0;
+ path = /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/CFNetwork.framework/Versions/A/CFNetwork;
+ whenToLoad = 0;
+ },
+ {
+ level = 0;
+ path = /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/WebServicesCore.framework/Versions/A/WebServicesCore;
+ whenToLoad = 0;
+ },
+ {
+ level = 0;
+ path = /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/SearchKit.framework/Versions/A/SearchKit;
+ whenToLoad = 0;
+ },
+ {
+ level = 0;
+ path = /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/Metadata.framework/Versions/A/Metadata;
+ whenToLoad = 0;
+ },
+ {
+ level = 0;
+ path = /System/Library/Frameworks/CoreServices.framework/Versions/A/CoreServices;
+ whenToLoad = 0;
+ },
+ {
+ level = 0;
+ path = /System/Library/Frameworks/CoreAudio.framework/Versions/A/CoreAudio;
+ whenToLoad = 0;
+ },
+ {
+ level = 0;
+ path = /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/CarbonSound.framework/Versions/A/CarbonSound;
+ whenToLoad = 0;
+ },
+ {
+ level = 0;
+ path = /usr/lib/libbsm.dylib;
+ whenToLoad = 0;
+ },
+ {
+ level = 0;
+ path = /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/CoreGraphics.framework/Versions/A/CoreGraphics;
+ whenToLoad = 0;
+ },
+ {
+ level = 0;
+ path = /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/AE.framework/Versions/A/AE;
+ whenToLoad = 0;
+ },
+ {
+ level = 0;
+ path = /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ATS.framework/Versions/A/ATS;
+ whenToLoad = 0;
+ },
+ {
+ level = 0;
+ path = /usr/lib/libcrypto.0.9.7.dylib;
+ whenToLoad = 0;
+ },
+ {
+ level = 0;
+ path = /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/LaunchServices.framework/Versions/A/LaunchServices;
+ whenToLoad = 0;
+ },
+ {
+ level = 0;
+ path = /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ColorSync.framework/Versions/A/ColorSync;
+ whenToLoad = 0;
+ },
+ {
+ level = 0;
+ path = /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/CoreText.framework/Versions/A/CoreText;
+ whenToLoad = 0;
+ },
+ {
+ level = 0;
+ path = /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/QD.framework/Versions/A/QD;
+ whenToLoad = 0;
+ },
+ {
+ level = 0;
+ path = /usr/lib/libcups.2.dylib;
+ whenToLoad = 0;
+ },
+ {
+ level = 0;
+ path = /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/PrintCore.framework/Versions/A/PrintCore;
+ whenToLoad = 0;
+ },
+ {
+ level = 0;
+ path = /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/HIServices.framework/Versions/A/HIServices;
+ whenToLoad = 0;
+ },
+ {
+ level = 0;
+ path = /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/LangAnalysis.framework/Versions/A/LangAnalysis;
+ whenToLoad = 0;
+ },
+ {
+ level = 0;
+ path = /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/FindByContent.framework/Versions/A/FindByContent;
+ whenToLoad = 0;
+ },
+ {
+ level = 0;
+ path = /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/SpeechSynthesis.framework/Versions/A/SpeechSynthesis;
+ whenToLoad = 0;
+ },
+ {
+ level = 0;
+ path = /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ImageIO.framework/Versions/A/Resources/libJPEG.dylib;
+ whenToLoad = 0;
+ },
+ {
+ level = 0;
+ path = /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ImageIO.framework/Versions/A/Resources/libJP2.dylib;
+ whenToLoad = 0;
+ },
+ {
+ level = 0;
+ path = /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ImageIO.framework/Versions/A/Resources/libGIF.dylib;
+ whenToLoad = 0;
+ },
+ {
+ level = 0;
+ path = /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ImageIO.framework/Versions/A/Resources/libRaw.dylib;
+ whenToLoad = 0;
+ },
+ {
+ level = 0;
+ path = /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ImageIO.framework/Versions/A/Resources/libTIFF.dylib;
+ whenToLoad = 0;
+ },
+ {
+ level = 0;
+ path = /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ImageIO.framework/Versions/A/Resources/libPng.dylib;
+ whenToLoad = 0;
+ },
+ {
+ level = 0;
+ path = /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ImageIO.framework/Versions/A/Resources/libRadiance.dylib;
+ whenToLoad = 0;
+ },
+ {
+ level = 0;
+ path = /usr/lib/libmx.A.dylib;
+ whenToLoad = 0;
+ },
+ {
+ level = 0;
+ path = /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vImage.framework/Versions/A/vImage;
+ whenToLoad = 0;
+ },
+ {
+ level = 0;
+ path = /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libvMisc.dylib;
+ whenToLoad = 0;
+ },
+ {
+ level = 0;
+ path = /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libvDSP.dylib;
+ whenToLoad = 0;
+ },
+ {
+ level = 0;
+ path = /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libBLAS.dylib;
+ whenToLoad = 0;
+ },
+ {
+ level = 0;
+ path = /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libLAPACK.dylib;
+ whenToLoad = 0;
+ },
+ {
+ level = 0;
+ path = /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/vecLib;
+ whenToLoad = 0;
+ },
+ {
+ level = 0;
+ path = /System/Library/Frameworks/Accelerate.framework/Versions/A/Accelerate;
+ whenToLoad = 0;
+ },
+ {
+ level = 0;
+ path = /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ImageIO.framework/Versions/A/ImageIO;
+ whenToLoad = 0;
+ },
+ {
+ level = 0;
+ path = /System/Library/Frameworks/ApplicationServices.framework/Versions/A/ApplicationServices;
+ whenToLoad = 0;
+ },
+ {
+ level = 0;
+ path = /usr/lib/libiconv.2.dylib;
+ whenToLoad = 0;
+ },
+ {
+ level = 0;
+ path = /usr/lib/libxml2.2.dylib;
+ whenToLoad = 0;
+ },
+ {
+ level = 0;
+ path = /System/Library/Frameworks/Foundation.framework/Versions/C/Foundation;
+ whenToLoad = 0;
+ },
+ {
+ level = 0;
+ path = /System/Library/PrivateFrameworks/DesktopServicesPriv.framework/Versions/A/DesktopServicesPriv;
+ whenToLoad = 0;
+ },
+ {
+ level = 0;
+ path = /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/HIToolbox.framework/Versions/A/HIToolbox;
+ whenToLoad = 0;
+ },
+ {
+ level = 0;
+ path = /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/ImageCapture.framework/Versions/A/ImageCapture;
+ whenToLoad = 0;
+ },
+ {
+ level = 0;
+ path = /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/SpeechRecognition.framework/Versions/A/SpeechRecognition;
+ whenToLoad = 0;
+ },
+ {
+ level = 0;
+ path = /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/SecurityHI.framework/Versions/A/SecurityHI;
+ whenToLoad = 0;
+ },
+ {
+ level = 0;
+ path = /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/Ink.framework/Versions/A/Ink;
+ whenToLoad = 0;
+ },
+ {
+ level = 0;
+ path = /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/Help.framework/Versions/A/Help;
+ whenToLoad = 0;
+ },
+ {
+ level = 0;
+ path = /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/OpenScripting.framework/Versions/A/OpenScripting;
+ whenToLoad = 0;
+ },
+ {
+ level = 0;
+ path = /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/Print.framework/Versions/A/Print;
+ whenToLoad = 0;
+ },
+ {
+ level = 0;
+ path = /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/HTMLRendering.framework/Versions/A/HTMLRendering;
+ whenToLoad = 0;
+ },
+ {
+ level = 0;
+ path = /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/NavigationServices.framework/Versions/A/NavigationServices;
+ whenToLoad = 0;
+ },
+ {
+ level = 0;
+ path = /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/CommonPanels.framework/Versions/A/CommonPanels;
+ whenToLoad = 0;
+ },
+ {
+ level = 0;
+ path = /System/Library/Frameworks/Carbon.framework/Versions/A/Carbon;
+ whenToLoad = 0;
+ },
+ {
+ level = 0;
+ path = /System/Library/Frameworks/AudioUnit.framework/Versions/A/AudioUnit;
+ whenToLoad = 0;
+ },
+ {
+ level = 0;
+ path = /System/Library/Frameworks/AudioToolbox.framework/Versions/A/AudioToolbox;
+ whenToLoad = 0;
+ },
+ {
+ level = 0;
+ path = /usr/lib/libsqlite3.0.dylib;
+ whenToLoad = 0;
+ },
+ {
+ level = 0;
+ path = /System/Library/Frameworks/CoreData.framework/Versions/A/CoreData;
+ whenToLoad = 0;
+ },
+ {
+ level = 0;
+ path = /System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGL.dylib;
+ whenToLoad = 0;
+ },
+ {
+ level = 0;
+ path = /System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGLU.dylib;
+ whenToLoad = 0;
+ },
+ {
+ level = 0;
+ path = /System/Library/Frameworks/OpenGL.framework/Versions/A/OpenGL;
+ whenToLoad = 0;
+ },
+ {
+ level = 0;
+ path = /System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGLImage.dylib;
+ whenToLoad = 0;
+ },
+ {
+ level = 0;
+ path = /System/Library/Frameworks/QuartzCore.framework/Versions/A/QuartzCore;
+ whenToLoad = 0;
+ },
+ {
+ level = 0;
+ path = /System/Library/Frameworks/AppKit.framework/Versions/C/AppKit;
+ whenToLoad = 0;
+ },
+ {
+ level = 0;
+ path = /System/Library/Frameworks/Cocoa.framework/Versions/A/Cocoa;
+ whenToLoad = 0;
+ },
+ {
+ level = 0;
+ path = /System/Library/Frameworks/WebKit.framework/Versions/A/Frameworks/JavaScriptCore.framework/Versions/A/JavaScriptCore;
+ whenToLoad = 0;
+ },
+ {
+ level = 0;
+ path = /usr/lib/libxslt.1.dylib;
+ whenToLoad = 0;
+ },
+ {
+ level = 0;
+ path = /System/Library/Frameworks/WebKit.framework/Versions/A/Frameworks/WebCore.framework/Versions/A/WebCore;
+ whenToLoad = 0;
+ },
+ {
+ level = 0;
+ path = /System/Library/Frameworks/WebKit.framework/Versions/A/WebKit;
+ whenToLoad = 0;
+ },
+ {
+ level = 0;
+ path = /System/Library/Frameworks/OSAKit.framework/Versions/A/OSAKit;
+ whenToLoad = 0;
+ },
+ {
+ level = 0;
+ path = /System/Library/Frameworks/AppleScriptKit.framework/Versions/A/AppleScriptKit;
+ whenToLoad = 0;
+ },
+ {
+ level = 0;
+ path = "/Users/darco/Projects/X11App/build/Synfig Studio.app/Contents/MacOS/Synfig Studio";
+ whenToLoad = 0;
+ },
+ );
+ sourceDirectories = (
+ );
+ };
+ A65E4880075176F200A66E82 = {
+ uiCtxt = {
+ sepNavIntBoundsRect = "{{0, 0}, {512, 271}}";
+ sepNavSelRange = "{0, 0}";
+ sepNavVisRect = "{{0, 0}, {512, 271}}";
+ };
+ };
+ A65E4881075176F200A66E82 = {
+ uiCtxt = {
+ sepNavIntBoundsRect = "{{0, 0}, {512, 271}}";
+ sepNavSelRange = "{0, 0}";
+ sepNavVisRect = "{{0, 0}, {512, 271}}";
+ };
+ };
+ A65E48D507518C4E00A66E82 = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.objc;
+ name = X11Controller.m;
+ path = /Users/darco/Projects/X11App/X11Controller.m;
+ refType = 0;
+ sourceTree = "<absolute>";
+ uiCtxt = {
+ sepNavIntBoundsRect = "{{0, 0}, {662, 9674}}";
+ sepNavSelRange = "{0, 0}";
+ sepNavVisRect = "{{0, 409}, {596, 352}}";
+ };
+ };
+ A66420E008E74B3D005A12D3 = {
+ fallbackIsa = XCSourceControlManager;
+ isSCMEnabled = 0;
+ isa = PBXSourceControlManager;
+ scmConfiguration = {
+ };
+ scmType = "";
+ };
+ A66420E108E74B3D005A12D3 = {
+ indexTemplatePath = "";
+ isa = PBXCodeSenseManager;
+ };
+ A66420F508E74C31005A12D3 = {
+ isa = PBXFileReference;
+ name = "bundle-main.c";
+ path = "/Users/darco/Projects/X11App/bundle-main.c";
+ refType = 0;
+ sourceTree = "<absolute>";
+ uiCtxt = {
+ sepNavIntBoundsRect = "{{0, 0}, {596, 12726}}";
+ sepNavSelRange = "{19522, 64}";
+ sepNavVisRect = "{{0, 12081}, {596, 352}}";
+ };
+ };
+ A66420F808E74CC8005A12D3 = {
+ fRef = A65E4881075176F200A66E82;
+ isa = PBXTextBookmark;
+ name = "SynfigApplication.m: 1";
+ rLen = 0;
+ rLoc = 0;
+ rType = 0;
+ vrLen = 241;
+ vrLoc = 0;
+ };
+ A66420F908E74CC8005A12D3 = {
+ fRef = A65E4880075176F200A66E82;
+ isa = PBXTextBookmark;
+ name = "SynfigApplication.h: 1";
+ rLen = 0;
+ rLoc = 0;
+ rType = 0;
+ vrLen = 288;
+ vrLoc = 0;
+ };
+ A66420FA08E74CC8005A12D3 = {
+ fRef = A65E48D507518C4E00A66E82;
+ isa = PBXTextBookmark;
+ name = "X11Controller.m: 1";
+ rLen = 0;
+ rLoc = 0;
+ rType = 0;
+ vrLen = 463;
+ vrLoc = 1513;
+ };
+ A66420FB08E74CC8005A12D3 = {
+ fRef = A66420F508E74C31005A12D3;
+ isa = PBXTextBookmark;
+ rLen = 1;
+ rLoc = 875;
+ rType = 1;
+ };
+ A66420FC08E74CC8005A12D3 = {
+ fRef = A65E4881075176F200A66E82;
+ isa = PBXTextBookmark;
+ name = "SynfigApplication.m: 1";
+ rLen = 0;
+ rLoc = 0;
+ rType = 0;
+ vrLen = 241;
+ vrLoc = 0;
+ };
+ A66420FD08E74CC8005A12D3 = {
+ fRef = 50EE2AB703849F0B0ECA21EC;
+ isa = PBXTextBookmark;
+ name = "bundle-main.c: 535";
+ rLen = 0;
+ rLoc = 12130;
+ rType = 0;
+ vrLen = 531;
+ vrLoc = 11734;
+ };
+ A66420FE08E74CC8005A12D3 = {
+ fRef = A65E4881075176F200A66E82;
+ isa = PBXTextBookmark;
+ name = "SynfigApplication.m: 1";
+ rLen = 0;
+ rLoc = 0;
+ rType = 0;
+ vrLen = 241;
+ vrLoc = 0;
+ };
+ A66420FF08E74CC8005A12D3 = {
+ fRef = A65E4880075176F200A66E82;
+ isa = PBXTextBookmark;
+ name = "SynfigApplication.h: 1";
+ rLen = 0;
+ rLoc = 0;
+ rType = 0;
+ vrLen = 288;
+ vrLoc = 0;
+ };
+ A664210008E74CC8005A12D3 = {
+ fRef = A65E48D507518C4E00A66E82;
+ isa = PBXTextBookmark;
+ name = "X11Controller.m: 1";
+ rLen = 0;
+ rLoc = 0;
+ rType = 0;
+ vrLen = 463;
+ vrLoc = 1513;
+ };
+ A664210408E74CC8005A12D3 = {
+ isa = PBXTargetBookmark;
+ trg = 20286C34FDCF999611CA2CEA;
+ };
+ A664210808E77262005A12D3 = {
+ fRef = 50EE2AB703849F0B0ECA21EC;
+ isa = PBXTextBookmark;
+ name = "void (*initializeASKFunc)(void) = NSAddressOfSymbol(symbol);";
+ rLen = 64;
+ rLoc = 19522;
+ rType = 0;
+ vrLen = 488;
+ vrLoc = 19274;
+ };
+ A664210908E77262005A12D3 = {
+ isa = PBXTargetBookmark;
+ trg = 20286C34FDCF999611CA2CEA;
+ uiCtxt = {
+ TOCViewDetailVisibleRect = "{{0, 0}, {534, 609}}";
+ TOCViewExpandedItems = (
+ "com.apple.target-editor-pane.settings",
+ "com.apple.target-editor-pane.settings.simple",
+ "com.apple.target-editor-pane.info-plist",
+ "com.apple.target-editor-pane.info-plist.simple",
+ "com.apple.target-editor-pane.buildphases",
+ );
+ TOCViewMasterVisibleRect = "{{0, 0}, {211, 609}}";
+ TOCViewSelectedItems = (
+ "com.apple.target-editor-pane.info-plist",
+ );
+ };
+ };
+}
--- /dev/null
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 39;
+ objects = {
+ 02345980000FD03B11CA0E72 = {
+ children = (
+ 1870340FFE93FCAF11CA0CD7,
+ );
+ isa = PBXVariantGroup;
+ name = main.nib;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 02345981000FD03B11CA0E72 = {
+ fileRef = 02345980000FD03B11CA0E72;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 0249A667FF388E1711CA2CEA = {
+ explicitFileType = wrapper.application;
+ isa = PBXFileReference;
+ path = "Synfig Studio.app";
+ refType = 3;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+//020
+//021
+//022
+//023
+//024
+//040
+//041
+//042
+//043
+//044
+ 04313892FE3035C9C02AAC07 = {
+ buildActionMask = 2147483647;
+ files = (
+ );
+ isa = PBXRezBuildPhase;
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+//040
+//041
+//042
+//043
+//044
+//080
+//081
+//082
+//083
+//084
+ 0867D6AAFE840B52C02AAC07 = {
+ children = (
+ 0867D6ABFE840B52C02AAC07,
+ );
+ isa = PBXVariantGroup;
+ name = InfoPlist.strings;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 0867D6ABFE840B52C02AAC07 = {
+ fileEncoding = 10;
+ isa = PBXFileReference;
+ lastKnownFileType = text.plist.strings;
+ name = English;
+ path = English.lproj/InfoPlist.strings;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 0867D6ACFE840B52C02AAC07 = {
+ fileRef = 0867D6AAFE840B52C02AAC07;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+//080
+//081
+//082
+//083
+//084
+//180
+//181
+//182
+//183
+//184
+ 1870340FFE93FCAF11CA0CD7 = {
+ isa = PBXFileReference;
+ lastKnownFileType = wrapper.nib;
+ name = English;
+ path = English.lproj/main.nib;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+//180
+//181
+//182
+//183
+//184
+//190
+//191
+//192
+//193
+//194
+ 195DF8CFFE9D517E11CA2CBB = {
+ children = (
+ 0249A667FF388E1711CA2CEA,
+ );
+ isa = PBXGroup;
+ name = Products;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+//190
+//191
+//192
+//193
+//194
+//200
+//201
+//202
+//203
+//204
+ 20286C28FDCF999611CA2CEA = {
+ buildSettings = {
+ };
+ buildStyles = (
+ 4A9504C5FFE6A39111CA0CBA,
+ 4A9504C6FFE6A39111CA0CBA,
+ );
+ hasScannedForEncodings = 1;
+ isa = PBXProject;
+ mainGroup = 20286C29FDCF999611CA2CEA;
+ projectDirPath = "";
+ targets = (
+ 20286C34FDCF999611CA2CEA,
+ );
+ };
+ 20286C29FDCF999611CA2CEA = {
+ children = (
+ 20286C2AFDCF999611CA2CEA,
+ 20286C2CFDCF999611CA2CEA,
+ 20286C32FDCF999611CA2CEA,
+ 195DF8CFFE9D517E11CA2CBB,
+ );
+ isa = PBXGroup;
+ name = X11;
+ path = "";
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 20286C2AFDCF999611CA2CEA = {
+ children = (
+ 50EE2AB703849F0B0ECA21EC,
+ A65E488407517A2600A66E82,
+ A65E44C807516A5C00A66E82,
+ A65E44C907516A5C00A66E82,
+ A65E4880075176F200A66E82,
+ A65E4881075176F200A66E82,
+ );
+ isa = PBXGroup;
+ name = Sources;
+ path = "";
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 20286C2CFDCF999611CA2CEA = {
+ children = (
+ A65E3D3307515F5900A66E82,
+ A65E3D3407515F5900A66E82,
+ 50459C5F038587C60ECA21EC,
+ 0867D6AAFE840B52C02AAC07,
+ 02345980000FD03B11CA0E72,
+ );
+ isa = PBXGroup;
+ name = Resources;
+ path = "";
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 20286C32FDCF999611CA2CEA = {
+ children = (
+ 50F4F0A7039D6ACA0E82C0CB,
+ A65E488607517A6900A66E82,
+ 570C5748047186C400ACF82F,
+ );
+ isa = PBXGroup;
+ name = "External Frameworks and Libraries";
+ path = "";
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 20286C34FDCF999611CA2CEA = {
+ buildPhases = (
+ 20286C35FDCF999611CA2CEA,
+ A65E44BC075161B900A66E82,
+ 20286C36FDCF999611CA2CEA,
+ 20286C38FDCF999611CA2CEA,
+ 20286C3BFDCF999611CA2CEA,
+ 04313892FE3035C9C02AAC07,
+ );
+ buildSettings = {
+ FRAMEWORK_SEARCH_PATHS = "";
+ HEADER_SEARCH_PATHS = "/Users/darco/Desktop/X11ForMacOSXSource-1.0/xc/programs/Xserver/include /usr/X11R6/include/X11 /usr/X11R6/include";
+ LIBRARY_SEARCH_PATHS = /usr/X11R6/lib;
+ OTHER_CFLAGS = "";
+ OTHER_LDFLAGS = "-lXau -lX11";
+ OTHER_REZFLAGS = "";
+ PRODUCT_NAME = "Synfig Studio";
+ SECTORDER_FLAGS = "";
+ WARNING_CFLAGS = "-Wmost -Wno-four-char-constants -Wno-unknown-pragmas";
+ WRAPPER_EXTENSION = app;
+ };
+ dependencies = (
+ );
+ isa = PBXApplicationTarget;
+ name = SynfigStudio;
+ productName = X11;
+ productReference = 0249A667FF388E1711CA2CEA;
+ productSettingsXML = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>
+<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">
+<plist version=\"1.0\">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>English</string>
+ <key>CFBundleDocumentTypes</key>
+ <array>
+ <dict>
+ <key>CFBundleTypeExtensions</key>
+ <array>
+ <string>sif</string>
+ </array>
+ <key>CFBundleTypeIconFile</key>
+ <string>sif_file.icns</string>
+ <key>CFBundleTypeMIMETypes</key>
+ <array>
+ <string>image/x-sif</string>
+ </array>
+ <key>CFBundleTypeName</key>
+ <string>Synfig Composition</string>
+ <key>CFBundleTypeOSTypes</key>
+ <array>
+ <string>****</string>
+ </array>
+ <key>CFBundleTypeRole</key>
+ <string>Editor</string>
+ <key>LSIsAppleDefaultForType</key>
+ <true/>
+ <key>NSDocumentClass</key>
+ <string>image</string>
+ </dict>
+ </array>
+ <key>CFBundleExecutable</key>
+ <string>Synfig Studio</string>
+ <key>CFBundleGetInfoString</key>
+ <string>Synfig</string>
+ <key>CFBundleIconFile</key>
+ <string>voria.icns</string>
+ <key>CFBundleIdentifier</key>
+ <string>com.voria.synfig</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundleName</key>
+ <string>Synfig Studio</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleShortVersionString</key>
+ <string>0.1</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleVersion</key>
+ <string>0.1</string>
+ <key>CSResourcesFileMapped</key>
+ <true/>
+ <key>NSHumanReadableCopyright</key>
+ <string>Copyright © 2003, Apple Computer, Inc.
+Copyright © 2003, XFree86 Project, Inc.</string>
+ <key>NSMainNibFile</key>
+ <string>main</string>
+ <key>NSPrincipalClass</key>
+ <string>SynfigApplication</string>
+</dict>
+</plist>
+";
+ };
+ 20286C35FDCF999611CA2CEA = {
+ buildActionMask = 2147483647;
+ files = (
+ );
+ isa = PBXHeadersBuildPhase;
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 20286C36FDCF999611CA2CEA = {
+ buildActionMask = 2147483647;
+ files = (
+ 0867D6ACFE840B52C02AAC07,
+ 02345981000FD03B11CA0E72,
+ A65E488807517AA400A66E82,
+ 50459C60038587C60ECA21EC,
+ A65E3D3507515F5900A66E82,
+ A65E3D3607515F5900A66E82,
+ );
+ isa = PBXResourcesBuildPhase;
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 20286C38FDCF999611CA2CEA = {
+ buildActionMask = 2147483647;
+ files = (
+ 50EE2AB803849F0B0ECA21EC,
+ );
+ isa = PBXSourcesBuildPhase;
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 20286C3BFDCF999611CA2CEA = {
+ buildActionMask = 2147483647;
+ files = (
+ 50F4F0E8039D6ACA0E82C0CB,
+ 570C5749047186C400ACF82F,
+ A65E488707517A6900A66E82,
+ );
+ isa = PBXFrameworksBuildPhase;
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+//200
+//201
+//202
+//203
+//204
+//4A0
+//4A1
+//4A2
+//4A3
+//4A4
+ 4A9504C5FFE6A39111CA0CBA = {
+ buildSettings = {
+ COPY_PHASE_STRIP = NO;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_ENABLE_FIX_AND_CONTINUE = YES;
+ GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ OPTIMIZATION_CFLAGS = "-O0";
+ ZERO_LINK = YES;
+ };
+ isa = PBXBuildStyle;
+ name = Development;
+ };
+ 4A9504C6FFE6A39111CA0CBA = {
+ buildSettings = {
+ COPY_PHASE_STRIP = YES;
+ GCC_ENABLE_FIX_AND_CONTINUE = NO;
+ ZERO_LINK = NO;
+ };
+ isa = PBXBuildStyle;
+ name = Deployment;
+ };
+//4A0
+//4A1
+//4A2
+//4A3
+//4A4
+//500
+//501
+//502
+//503
+//504
+ 50459C5F038587C60ECA21EC = {
+ isa = PBXFileReference;
+ lastKnownFileType = image.icns;
+ path = X11.icns;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 50459C60038587C60ECA21EC = {
+ fileRef = 50459C5F038587C60ECA21EC;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 50EE2AB703849F0B0ECA21EC = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = "bundle-main.c";
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 50EE2AB803849F0B0ECA21EC = {
+ fileRef = 50EE2AB703849F0B0ECA21EC;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 50F4F0A7039D6ACA0E82C0CB = {
+ isa = PBXFileReference;
+ lastKnownFileType = wrapper.framework;
+ name = CoreFoundation.framework;
+ path = /System/Library/Frameworks/CoreFoundation.framework;
+ refType = 0;
+ sourceTree = "<absolute>";
+ };
+ 50F4F0E8039D6ACA0E82C0CB = {
+ fileRef = 50F4F0A7039D6ACA0E82C0CB;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+//500
+//501
+//502
+//503
+//504
+//570
+//571
+//572
+//573
+//574
+ 570C5748047186C400ACF82F = {
+ isa = PBXFileReference;
+ lastKnownFileType = wrapper.framework;
+ name = SystemConfiguration.framework;
+ path = /System/Library/Frameworks/SystemConfiguration.framework;
+ refType = 0;
+ sourceTree = "<absolute>";
+ };
+ 570C5749047186C400ACF82F = {
+ fileRef = 570C5748047186C400ACF82F;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+//570
+//571
+//572
+//573
+//574
+//A60
+//A61
+//A62
+//A63
+//A64
+ A65E3D3307515F5900A66E82 = {
+ isa = PBXFileReference;
+ lastKnownFileType = image.icns;
+ path = sif_file.icns;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ A65E3D3407515F5900A66E82 = {
+ isa = PBXFileReference;
+ lastKnownFileType = image.icns;
+ path = voria.icns;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ A65E3D3507515F5900A66E82 = {
+ fileRef = A65E3D3307515F5900A66E82;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ A65E3D3607515F5900A66E82 = {
+ fileRef = A65E3D3407515F5900A66E82;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ A65E44BC075161B900A66E82 = {
+ buildActionMask = 2147483647;
+ contextName = "";
+ files = (
+ A65E488507517A2600A66E82,
+ );
+ isSharedContext = 0;
+ isa = PBXAppleScriptBuildPhase;
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ A65E44C807516A5C00A66E82 = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ path = X11Controller.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ A65E44C907516A5C00A66E82 = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.objc;
+ path = X11Controller.m;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ A65E4880075176F200A66E82 = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ path = SynfigApplication.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ A65E4881075176F200A66E82 = {
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.objc;
+ path = SynfigApplication.m;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ A65E488407517A2600A66E82 = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.applescript;
+ path = events.applescript;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ A65E488507517A2600A66E82 = {
+ fileRef = A65E488407517A2600A66E82;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ Debug,
+ );
+ };
+ };
+ A65E488607517A6900A66E82 = {
+ isa = PBXFileReference;
+ lastKnownFileType = wrapper.framework;
+ name = AppleScriptKit.framework;
+ path = /System/Library/Frameworks/AppleScriptKit.framework;
+ refType = 0;
+ sourceTree = "<absolute>";
+ };
+ A65E488707517A6900A66E82 = {
+ fileRef = A65E488607517A6900A66E82;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ A65E488807517AA400A66E82 = {
+ fileRef = A65E488407517A2600A66E82;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ };
+ rootObject = 20286C28FDCF999611CA2CEA;
+}
--- /dev/null
+//
+// SynfigApplication.h
+// Synfig Studio
+//
+// Created by Robert Quattlebaum on Sun Nov 21 2004.
+// Copyright (c) 2004 __MyCompanyName__. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+#import "X11Application.h"
+
+@interface SynfigApplication : X11Application {
+
+}
+
+@end
--- /dev/null
+//
+// SynfigApplication.m
+// Synfig Studio
+//
+// Created by Robert Quattlebaum on Sun Nov 21 2004.
+// Copyright (c) 2004 __MyCompanyName__. All rights reserved.
+//
+
+#import "SynfigApplication.h"
+
+
+@implementation SynfigApplication
+
+@end
--- /dev/null
+/* X11Application.h -- subclass of NSApplication to multiplex events
+ $Id: X11Application.h,v 1.26 2003/08/08 19:16:13 jharper Exp $
+
+ Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
+
+ Permission is hereby granted, free of charge, to any person
+ obtaining a copy of this software and associated documentation files
+ (the "Software"), to deal in the Software without restriction,
+ including without limitation the rights to use, copy, modify, merge,
+ publish, distribute, sublicense, and/or sell copies of the Software,
+ and to permit persons to whom the Software is furnished to do so,
+ subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT
+ HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ DEALINGS IN THE SOFTWARE.
+
+ Except as contained in this notice, the name(s) of the above
+ copyright holders shall not be used in advertising or otherwise to
+ promote the sale, use or other dealings in this Software without
+ prior written authorization. */
+
+#ifndef X11APPLICATION_H
+#define X11APPLICATION_H 1
+
+#if __OBJC__
+
+#import <Cocoa/Cocoa.h>
+#import "X11Controller.h"
+
+@interface X11Application : NSApplication {
+ X11Controller *_controller;
+
+ unsigned int _x_active :1;
+}
+
+- (void) set_controller:controller;
+- (void) set_window_menu:(NSArray *)list;
+
+- (int) prefs_get_integer:(NSString *)key default:(int)def;
+- (const char *) prefs_get_string:(NSString *)key default:(const char *)def;
+- (float) prefs_get_float:(NSString *)key default:(float)def;
+- (int) prefs_get_boolean:(NSString *)key default:(int)def;
+- (NSArray *) prefs_get_array:(NSString *)key;
+- (void) prefs_set_integer:(NSString *)key value:(int)value;
+- (void) prefs_set_float:(NSString *)key value:(float)value;
+- (void) prefs_set_boolean:(NSString *)key value:(int)value;
+- (void) prefs_set_array:(NSString *)key value:(NSArray *)value;
+- (void) prefs_set_string:(NSString *)key value:(NSString *)value;
+- (void) prefs_synchronize;
+
+- (BOOL) x_active;
+
+@end
+
+extern X11Application *X11App;
+
+#endif /* __OBJC__ */
+
+extern void X11ApplicationSetWindowMenu (int nitems, const char **items,
+ const char *shortcuts);
+extern void X11ApplicationSetWindowMenuCheck (int idx);
+extern void X11ApplicationSetFrontProcess (void);
+extern void X11ApplicationSetCanQuit (int state);
+extern void X11ApplicationServerReady (void);
+extern void X11ApplicationShowHideMenubar (int state);
+
+extern void X11ApplicationMain (int argc, const char *argv[],
+ void (*server_thread) (void *),
+ void *server_arg);
+
+extern int X11EnableKeyEquivalents;
+
+#define APP_PREFS "com.apple.x11"
+
+#define PREFS_APPSMENU "apps_menu"
+#define PREFS_FAKEBUTTONS "enable_fake_buttons"
+#define PREFS_SYSBEEP "enable_system_beep"
+#define PREFS_KEYEQUIVS "enable_key_equivalents"
+#define PREFS_KEYMAP_FILE "keymap_file"
+#define PREFS_SYNC_KEYMAP "sync_keymap"
+#define PREFS_DEPTH "depth"
+#define PREFS_NO_AUTH "no_auth"
+#define PREFS_NO_TCP "nolisten_tcp"
+#define PREFS_DONE_XINIT_CHECK "done_xinit_check"
+#define PREFS_NO_QUIT_ALERT "no_quit_alert"
+#define PREFS_FAKE_BUTTON2 "fake_button2"
+#define PREFS_FAKE_BUTTON3 "fake_button3"
+#define PREFS_ROOTLESS "rootless"
+#define PREFS_FULLSCREEN_HOTKEYS "fullscreen_hotkeys"
+#define PREFS_SWAP_ALT_META "swap_alt_meta"
+#define PREFS_XP_OPTIONS "xp_options"
+
+#endif /* X11APPLICATION_H */
--- /dev/null
+/* X11Application.m -- subclass of NSApplication to multiplex events
+ $Id: X11Application.m,v 1.53 2003/09/13 02:00:46 jharper Exp $
+
+ Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
+
+ Permission is hereby granted, free of charge, to any person
+ obtaining a copy of this software and associated documentation files
+ (the "Software"), to deal in the Software without restriction,
+ including without limitation the rights to use, copy, modify, merge,
+ publish, distribute, sublicense, and/or sell copies of the Software,
+ and to permit persons to whom the Software is furnished to do so,
+ subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT
+ HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ DEALINGS IN THE SOFTWARE.
+
+ Except as contained in this notice, the name(s) of the above
+ copyright holders shall not be used in advertising or otherwise to
+ promote the sale, use or other dealings in this Software without
+ prior written authorization. */
+
+#import "X11Application.h"
+#include <Carbon/Carbon.h>
+
+/* ouch! */
+#define BOOL X_BOOL
+# include "Xproto.h"
+#define WindowPtr X_WindowPtr
+#define Cursor X_Cursor
+# include "quartz.h"
+# define _APPLEWM_SERVER_
+# include "applewm.h"
+# include "X.h"
+#undef Cursor
+#undef WindowPtr
+#undef BOOL
+
+#include "xf86Version.h"
+
+#include <mach/mach.h>
+#include <unistd.h>
+#include <pthread.h>
+
+#define DEFAULTS_FILE "/etc/X11/xserver/Xquartz.plist"
+
+int X11EnableKeyEquivalents = TRUE;
+
+X11Application *X11App;
+
+#define ALL_KEY_MASKS (NSShiftKeyMask | NSControlKeyMask \
+ | NSAlternateKeyMask | NSCommandKeyMask)
+
+@implementation X11Application
+
+typedef struct message_struct message;
+struct message_struct {
+ mach_msg_header_t hdr;
+ SEL selector;
+ NSObject *arg;
+};
+
+static mach_port_t _port;
+
+static void send_nsevent (NSEventType type, NSEvent *e);
+
+/* avoid header conflict hell */
+extern int RootlessKnowsWindowNumber (int number);
+extern void DarwinEnqueueEvent (const xEvent *e);
+
+static void
+init_ports (void)
+{
+ kern_return_t r;
+ NSPort *p;
+
+ if (_port != MACH_PORT_NULL)
+ return;
+
+ r = mach_port_allocate (mach_task_self (), MACH_PORT_RIGHT_RECEIVE, &_port);
+ if (r != KERN_SUCCESS)
+ return;
+
+ p = [NSMachPort portWithMachPort:_port];
+ [p setDelegate:NSApp];
+ [p scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
+}
+
+static void
+message_kit_thread (SEL selector, NSObject *arg)
+{
+ message msg;
+ kern_return_t r;
+
+ msg.hdr.msgh_bits = MACH_MSGH_BITS (MACH_MSG_TYPE_MAKE_SEND, 0);
+ msg.hdr.msgh_size = sizeof (msg);
+ msg.hdr.msgh_remote_port = _port;
+ msg.hdr.msgh_local_port = MACH_PORT_NULL;
+ msg.hdr.msgh_reserved = 0;
+ msg.hdr.msgh_id = 0;
+
+ msg.selector = selector;
+ msg.arg = [arg retain];
+
+ r = mach_msg (&msg.hdr, MACH_SEND_MSG, msg.hdr.msgh_size,
+ 0, MACH_PORT_NULL, 0, MACH_PORT_NULL);
+ if (r != KERN_SUCCESS)
+ fprintf (stderr, "%s: mach_msg failed: %x\n", __FUNCTION__, r);
+}
+
+- (void) handleMachMessage:(void *)_msg
+{
+ message *msg = _msg;
+
+ [self performSelector:msg->selector withObject:msg->arg];
+ [msg->arg release];
+}
+
+- (void) set_controller:obj
+{
+ if (_controller == nil)
+ _controller = [obj retain];
+}
+
+- (void) dealloc
+{
+ if (_controller != nil)
+ [_controller release];
+
+ if (_port != MACH_PORT_NULL)
+ mach_port_deallocate (mach_task_self (), _port);
+
+ [super dealloc];
+}
+
+- (void) orderFrontStandardAboutPanel: (id) sender
+{
+ NSMutableDictionary *dict;
+ NSDictionary *infoDict;
+ NSString *tem;
+
+ dict = [NSMutableDictionary dictionaryWithCapacity:2];
+ infoDict = [[NSBundle mainBundle] infoDictionary];
+
+ [dict setObject: NSLocalizedString (@"The X Window System", @"About panel")
+ forKey:@"ApplicationName"];
+
+ tem = [infoDict objectForKey:@"CFBundleShortVersionString"];
+
+ [dict setObject:[NSString stringWithFormat:@"X11 %@ - XFree86 %d.%d.%d",
+ tem, XF86_VERSION_MAJOR, XF86_VERSION_MINOR,
+ XF86_VERSION_PATCH] forKey:@"ApplicationVersion"];
+
+ [self orderFrontStandardAboutPanelWithOptions: dict];
+}
+
+- (void) activateX:(BOOL)state
+{
+ /* Create a TSM document that supports full Unicode input, and
+ have it activated while X is active (unless using the old
+ keymapping files) */
+ static TSMDocumentID x11_document;
+
+ if (state)
+ {
+ QuartzMessageMainThread (kXquartzActivate, 0);
+
+ if (!_x_active)
+ {
+ if (x11_document == 0 && darwinKeymapFile == NULL)
+ {
+ OSType types[1];
+ types[0] = kUnicodeDocument;
+ NewTSMDocument (1, types, &x11_document, 0);
+ }
+
+ if (x11_document != 0)
+ ActivateTSMDocument (x11_document);
+ }
+ }
+ else
+ {
+ QuartzMessageMainThread (kXquartzDeactivate, 0);
+
+ if (_x_active)
+ {
+ if (x11_document != 0)
+ DeactivateTSMDocument (x11_document);
+ }
+ }
+
+ _x_active = state;
+}
+
+- (void) became_key:(NSWindow *)win
+{
+ [self activateX:NO];
+}
+
+- (void) sendEvent:(NSEvent *)e
+{
+ NSEventType type;
+ BOOL for_appkit, for_x;
+
+ type = [e type];
+
+ /* By default pass down the responder chain and to X. */
+ for_appkit = YES;
+ for_x = YES;
+
+ switch (type)
+ {
+ case NSLeftMouseDown: case NSRightMouseDown: case NSOtherMouseDown:
+ case NSLeftMouseUp: case NSRightMouseUp: case NSOtherMouseUp:
+ if ([e window] != nil)
+ {
+ /* Pointer event has a window. Probably something for the kit. */
+
+ for_x = NO;
+
+ if (_x_active)
+ [self activateX:NO];
+ }
+ else if ([self modalWindow] == nil)
+ {
+ /* Must be an X window. Tell appkit it doesn't have focus. */
+
+ for_appkit = NO;
+
+ if ([self isActive])
+ {
+ [self deactivate];
+
+ if (!_x_active && RootlessKnowsWindowNumber ([e windowNumber]))
+ [self activateX:YES];
+ }
+ }
+ break;
+
+ case NSKeyDown: case NSKeyUp:
+ if (_x_active)
+ {
+ static int swallow_up;
+
+ /* No kit window is focused, so send it to X. */
+
+ for_appkit = NO;
+
+ if (type == NSKeyDown)
+ {
+ /* Before that though, see if there are any global
+ shortcuts bound to it. */
+
+ if (X11EnableKeyEquivalents
+ && [[self mainMenu] performKeyEquivalent:e])
+ {
+ swallow_up = [e keyCode];
+ for_x = NO;
+ }
+ else if (!quartzEnableRootless
+ && ([e modifierFlags] & ALL_KEY_MASKS)
+ == (NSCommandKeyMask | NSAlternateKeyMask)
+ && ([e keyCode] == 0 /*a*/
+ || [e keyCode] == 53 /*Esc*/))
+ {
+ swallow_up = 0;
+ for_x = NO;
+ QuartzMessageMainThread (kXquartzToggleFullscreen, 0);
+ }
+ }
+ else
+ {
+ /* If we saw a key equivalent on the down, don't pass
+ the up through to X. */
+
+ if (swallow_up != 0 && [e keyCode] == swallow_up)
+ {
+ swallow_up = 0;
+ for_x = NO;
+ }
+ }
+ }
+ else
+ {
+ for_x = NO;
+ }
+ break;
+
+ case NSFlagsChanged:
+ /* For the l33t X users who remap modifier keys to normal keysyms. */
+ if (!_x_active)
+ for_x = NO;
+ break;
+
+ case NSAppKitDefined:
+ switch ([e subtype])
+ {
+ case NSApplicationActivatedEventType:
+ for_x = NO;
+ if ([self modalWindow] == nil)
+ {
+ for_appkit = NO;
+
+ /* FIXME: hack to avoid having to pass the event to appkit,
+ which would cause it to raise one of its windows. */
+ _appFlags._active = YES;
+
+ [self activateX:YES];
+ }
+ break;
+
+ case 18: /* ApplicationDidReactivate */
+ if (quartzHasRoot)
+ for_appkit = NO;
+ break;
+
+ case NSApplicationDeactivatedEventType:
+ for_x = NO;
+ [self activateX:NO];
+ break;
+ }
+ break;
+
+ default: break; /* for gcc */
+ }
+
+ if (for_appkit)
+ {
+ [super sendEvent:e];
+ }
+
+ if (for_x)
+ {
+ send_nsevent (type, e);
+ }
+}
+
+- (void) set_window_menu:(NSArray *)list
+{
+ [_controller set_window_menu:list];
+}
+
+- (void) set_window_menu_check:(NSNumber *)n
+{
+ [_controller set_window_menu_check:n];
+}
+
+- (void) set_apps_menu:(NSArray *)list
+{
+ [_controller set_apps_menu:list];
+}
+
+- (void) set_front_process:unused
+{
+ [NSApp activateIgnoringOtherApps:YES];
+
+ if ([self modalWindow] == nil)
+ [self activateX:YES];
+}
+
+- (void) set_can_quit:(NSNumber *)state
+{
+ [_controller set_can_quit:[state boolValue]];
+}
+
+- (void) server_ready:unused
+{
+ [_controller server_ready];
+}
+
+- (void) show_hide_menubar:(NSNumber *)state
+{
+ if ([state boolValue])
+ ShowMenuBar ();
+ else
+ HideMenuBar ();
+}
+
+\f
+/* user preferences */
+
+/* Note that these functions only work for arrays whose elements
+ can be toll-free-bridged between NS and CF worlds. */
+
+static const void *cfretain (CFAllocatorRef a, const void *b) {
+ return CFRetain (b);
+}
+static void cfrelease (CFAllocatorRef a, const void *b) {
+ CFRelease (b);
+}
+static CFMutableArrayRef
+nsarray_to_cfarray (NSArray *in)
+{
+ CFMutableArrayRef out;
+ CFArrayCallBacks cb;
+ NSObject *ns;
+ const CFTypeRef *cf;
+ int i, count;
+
+ memset (&cb, 0, sizeof (cb));
+ cb.version = 0;
+ cb.retain = cfretain;
+ cb.release = cfrelease;
+
+ count = [in count];
+ out = CFArrayCreateMutable (NULL, count, &cb);
+
+ for (i = 0; i < count; i++)
+ {
+ ns = [in objectAtIndex:i];
+
+ if ([ns isKindOfClass:[NSArray class]])
+ cf = (CFTypeRef) nsarray_to_cfarray ((NSArray *) ns);
+ else
+ cf = CFRetain ((CFTypeRef) ns);
+
+ CFArrayAppendValue (out, cf);
+ CFRelease (cf);
+ }
+
+ return out;
+}
+static NSMutableArray *
+cfarray_to_nsarray (CFArrayRef in)
+{
+ NSMutableArray *out;
+ const CFTypeRef *cf;
+ NSObject *ns;
+ int i, count;
+
+ count = CFArrayGetCount (in);
+ out = [[NSMutableArray alloc] initWithCapacity:count];
+
+ for (i = 0; i < count; i++)
+ {
+ cf = CFArrayGetValueAtIndex (in, i);
+
+ if (CFGetTypeID (cf) == CFArrayGetTypeID ())
+ ns = cfarray_to_nsarray ((CFArrayRef) cf);
+ else
+ ns = [(id)cf retain];
+
+ [out addObject:ns];
+ [ns release];
+ }
+
+ return out;
+}
+
+- (CFPropertyListRef) prefs_get:(NSString *)key
+{
+ CFPropertyListRef value;
+
+ value = CFPreferencesCopyAppValue ((CFStringRef) key, CFSTR (APP_PREFS));
+
+ if (value == NULL)
+ {
+ static CFDictionaryRef defaults;
+
+ if (defaults == NULL)
+ {
+ CFStringRef error = NULL;
+ CFDataRef data;
+ CFURLRef url;
+ SInt32 error_code;
+
+ url = (CFURLCreateFromFileSystemRepresentation
+ (NULL, DEFAULTS_FILE, strlen (DEFAULTS_FILE), false));
+ if (CFURLCreateDataAndPropertiesFromResource (NULL, url, &data,
+ NULL, NULL,
+ &error_code))
+ {
+ defaults = (CFPropertyListCreateFromXMLData
+ (NULL, data, kCFPropertyListImmutable, &error));
+ if (error != NULL)
+ CFRelease (error);
+ CFRelease (data);
+ }
+ CFRelease (url);
+ }
+
+ if (defaults != NULL)
+ value = CFDictionaryGetValue (defaults, key);
+
+ if (value != NULL)
+ CFRetain (value);
+ }
+
+ return value;
+}
+
+- (int) prefs_get_integer:(NSString *)key default:(int)def
+{
+ CFPropertyListRef value;
+ int ret;
+
+ value = [self prefs_get:key];
+
+ if (value != NULL && CFGetTypeID (value) == CFNumberGetTypeID ())
+ CFNumberGetValue (value, kCFNumberIntType, &ret);
+ else if (value != NULL && CFGetTypeID (value) == CFStringGetTypeID ())
+ ret = CFStringGetIntValue (value);
+ else
+ ret = def;
+
+ if (value != NULL)
+ CFRelease (value);
+
+ return ret;
+}
+
+- (const char *) prefs_get_string:(NSString *)key default:(const char *)def
+{
+ CFPropertyListRef value;
+ const char *ret = NULL;
+
+ value = [self prefs_get:key];
+
+ if (value != NULL && CFGetTypeID (value) == CFStringGetTypeID ())
+ {
+ NSString *s = (NSString *) value;
+
+ ret = [s UTF8String];
+ }
+
+ if (value != NULL)
+ CFRelease (value);
+
+ return ret != NULL ? ret : def;
+}
+
+- (float) prefs_get_float:(NSString *)key default:(float)def
+{
+ CFPropertyListRef value;
+ float ret = def;
+
+ value = [self prefs_get:key];
+
+ if (value != NULL
+ && CFGetTypeID (value) == CFNumberGetTypeID ()
+ && CFNumberIsFloatType (value))
+ {
+ CFNumberGetValue (value, kCFNumberFloatType, &ret);
+ }
+ else if (value != NULL && CFGetTypeID (value) == CFStringGetTypeID ())
+ {
+ ret = CFStringGetDoubleValue (value);
+ }
+
+ if (value != NULL)
+ CFRelease (value);
+
+ return ret;
+}
+
+- (int) prefs_get_boolean:(NSString *)key default:(int)def
+{
+ CFPropertyListRef value;
+ int ret = def;
+
+ value = [self prefs_get:key];
+
+ if (value != NULL)
+ {
+ if (CFGetTypeID (value) == CFNumberGetTypeID ())
+ CFNumberGetValue (value, kCFNumberIntType, &ret);
+ else if (CFGetTypeID (value) == CFBooleanGetTypeID ())
+ ret = CFBooleanGetValue (value);
+ else if (CFGetTypeID (value) == CFStringGetTypeID ())
+ {
+ const char *tem = [(NSString *) value lossyCString];
+ if (strcasecmp (tem, "true") == 0 || strcasecmp (tem, "yes") == 0)
+ ret = YES;
+ else
+ ret = NO;
+ }
+
+ CFRelease (value);
+ }
+
+ return ret;
+}
+
+- (NSArray *) prefs_get_array:(NSString *)key
+{
+ NSArray *ret = nil;
+ CFPropertyListRef value;
+
+ value = [self prefs_get:key];
+
+ if (value != NULL)
+ {
+ if (CFGetTypeID (value) == CFArrayGetTypeID ())
+ ret = [cfarray_to_nsarray (value) autorelease];
+
+ CFRelease (value);
+ }
+
+ return ret;
+}
+
+- (void) prefs_set_integer:(NSString *)key value:(int)value
+{
+ CFNumberRef x;
+
+ x = CFNumberCreate (NULL, kCFNumberIntType, &value);
+
+ CFPreferencesSetValue ((CFStringRef) key, (CFTypeRef) x, CFSTR (APP_PREFS),
+ kCFPreferencesCurrentUser, kCFPreferencesAnyHost);
+
+ CFRelease (x);
+}
+
+- (void) prefs_set_float:(NSString *)key value:(float)value
+{
+ CFNumberRef x;
+
+ x = CFNumberCreate (NULL, kCFNumberFloatType, &value);
+
+ CFPreferencesSetValue ((CFStringRef) key, (CFTypeRef) x, CFSTR (APP_PREFS),
+ kCFPreferencesCurrentUser, kCFPreferencesAnyHost);
+
+ CFRelease (x);
+}
+
+- (void) prefs_set_boolean:(NSString *)key value:(int)value
+{
+ CFPreferencesSetValue ((CFStringRef) key,
+ (CFTypeRef) value ? kCFBooleanTrue
+ : kCFBooleanFalse, CFSTR (APP_PREFS),
+ kCFPreferencesCurrentUser, kCFPreferencesAnyHost);
+
+}
+
+- (void) prefs_set_array:(NSString *)key value:(NSArray *)value
+{
+ CFArrayRef cfarray;
+
+ cfarray = nsarray_to_cfarray (value);
+ CFPreferencesSetValue ((CFStringRef) key,
+ (CFTypeRef) cfarray,
+ CFSTR (APP_PREFS),
+ kCFPreferencesCurrentUser, kCFPreferencesAnyHost);
+ CFRelease (cfarray);
+}
+
+- (void) prefs_set_string:(NSString *)key value:(NSString *)value
+{
+ CFPreferencesSetValue ((CFStringRef) key, (CFTypeRef) value,
+ CFSTR (APP_PREFS), kCFPreferencesCurrentUser,
+ kCFPreferencesAnyHost);
+}
+
+- (void) prefs_synchronize
+{
+ CFPreferencesAppSynchronize (kCFPreferencesCurrentApplication);
+}
+
+- (void) read_defaults
+{
+ extern int darwinFakeButtons;
+ const char *tem;
+
+ quartzUseSysBeep = [self prefs_get_boolean:@PREFS_SYSBEEP
+ default:quartzUseSysBeep];
+ quartzEnableRootless = [self prefs_get_boolean:@PREFS_ROOTLESS
+ default:quartzEnableRootless];
+ quartzFullscreenDisableHotkeys = ![self prefs_get_boolean:
+ @PREFS_FULLSCREEN_HOTKEYS default:
+ !quartzFullscreenDisableHotkeys];
+ quartzXpluginOptions = [self prefs_get_integer:@PREFS_XP_OPTIONS
+ default:quartzXpluginOptions];
+
+ darwinSwapAltMeta = [self prefs_get_boolean:@PREFS_SWAP_ALT_META
+ default:darwinSwapAltMeta];
+ darwinFakeButtons = [self prefs_get_boolean:@PREFS_FAKEBUTTONS
+ default:darwinFakeButtons];
+ if (darwinFakeButtons)
+ {
+ const char *fake2, *fake3;
+
+ fake2 = [self prefs_get_string:@PREFS_FAKE_BUTTON2 default:NULL];
+ fake3 = [self prefs_get_string:@PREFS_FAKE_BUTTON3 default:NULL];
+
+ DarwinSetFakeButtons (fake2, fake3);
+ }
+
+ X11EnableKeyEquivalents = [self prefs_get_boolean:@PREFS_KEYEQUIVS
+ default:X11EnableKeyEquivalents];
+
+ darwinSyncKeymap = [self prefs_get_boolean:@PREFS_SYNC_KEYMAP
+ default:darwinSyncKeymap];
+
+ tem = [self prefs_get_string:@PREFS_KEYMAP_FILE default:NULL];
+ if (tem != NULL)
+ darwinKeymapFile = strdup (tem);
+
+ quartzDesiredDepth = [self prefs_get_integer:@PREFS_DEPTH
+ default:quartzDesiredDepth];
+}
+
+/* This will end up at the end of the responder chain. */
+- (void) copy:sender
+{
+ QuartzMessageMainThread (kXquartzPasteboardNotify, 1,
+ AppleWMCopyToPasteboard);
+}
+
+- (BOOL) x_active
+{
+ return _x_active;
+}
+
+@end
+
+static NSArray *
+array_with_strings_and_numbers (int nitems, const char **items,
+ const char *numbers)
+{
+ NSMutableArray *array, *subarray;
+ NSString *string;
+ NSString *number;
+ int i;
+
+ /* (Can't autorelease on the X server thread) */
+
+ array = [[NSMutableArray alloc] initWithCapacity:nitems];
+
+ for (i = 0; i < nitems; i++)
+ {
+ subarray = [[NSMutableArray alloc] initWithCapacity:2];
+
+ string = [[NSString alloc] initWithUTF8String:items[i]];
+ [subarray addObject:string];
+ [string release];
+
+ if (numbers[i] != 0)
+ {
+ number = [[NSString alloc] initWithFormat:@"%d", numbers[i]];
+ [subarray addObject:number];
+ [number release];
+ }
+ else
+ [subarray addObject:@""];
+
+ [array addObject:subarray];
+ [subarray release];
+ }
+
+ return array;
+}
+
+void
+X11ApplicationSetWindowMenu (int nitems, const char **items,
+ const char *shortcuts)
+{
+ NSArray *array;
+
+ array = array_with_strings_and_numbers (nitems, items, shortcuts);
+
+ /* Send the array of strings over to the appkit thread */
+
+ message_kit_thread (@selector (set_window_menu:), array);
+ [array release];
+}
+
+void
+X11ApplicationSetWindowMenuCheck (int idx)
+{
+ NSNumber *n;
+
+ n = [[NSNumber alloc] initWithInt:idx];
+
+ message_kit_thread (@selector (set_window_menu_check:), n);
+
+ [n release];
+}
+
+void
+X11ApplicationSetFrontProcess (void)
+{
+ message_kit_thread (@selector (set_front_process:), nil);
+}
+
+void
+X11ApplicationSetCanQuit (int state)
+{
+ NSNumber *n;
+
+ n = [[NSNumber alloc] initWithBool:state];
+
+ message_kit_thread (@selector (set_can_quit:), n);
+
+ [n release];
+}
+
+void
+X11ApplicationServerReady (void)
+{
+ message_kit_thread (@selector (server_ready:), nil);
+}
+
+void
+X11ApplicationShowHideMenubar (int state)
+{
+ NSNumber *n;
+
+ n = [[NSNumber alloc] initWithBool:state];
+
+ message_kit_thread (@selector (show_hide_menubar:), n);
+
+ [n release];
+}
+
+static void *
+create_thread (void *func, void *arg)
+{
+ pthread_attr_t attr;
+ pthread_t tid;
+
+ pthread_attr_init (&attr);
+
+ pthread_attr_setscope (&attr, PTHREAD_SCOPE_SYSTEM);
+ pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
+
+ pthread_create (&tid, &attr, func, arg);
+
+ pthread_attr_destroy (&attr);
+
+ return (void *) tid;
+}
+
+static void
+check_xinitrc (void)
+{
+ char *tem, buf[1024];
+ NSString *msg;
+
+ if ([X11App prefs_get_boolean:@PREFS_DONE_XINIT_CHECK default:NO])
+ return;
+
+ tem = getenv ("HOME");
+ if (tem == NULL)
+ goto done;
+
+ snprintf (buf, sizeof (buf), "%s/.xinitrc", tem);
+ if (access (buf, F_OK) != 0)
+ goto done;
+
+ /* FIXME: put localized strings into Resources/English.lproj */
+
+ msg = NSLocalizedString (
+@"You have an existing ~/.xinitrc file.\n\n\
+Windows displayed by X11 applications may not have titlebars, or may look \
+different to windows displayed by native applications.\n\n\
+Would you like to move aside the existing file and use the standard X11 \
+environment?", @"");
+
+ if (NSRunAlertPanel (nil, msg, NSLocalizedString (@"Yes", @""),
+ NSLocalizedString (@"No", @""), nil)
+ == NSAlertDefaultReturn)
+ {
+ char buf2[1024];
+ int i = -1;
+
+ snprintf (buf2, sizeof (buf2), "%s.old", buf);
+
+ for (i = 1; access (buf2, F_OK) == 0; i++)
+ snprintf (buf2, sizeof (buf2), "%s.old.%d", buf, i);
+
+ rename (buf, buf2);
+ }
+
+done:
+ [X11App prefs_set_boolean:@PREFS_DONE_XINIT_CHECK value:YES];
+ [X11App prefs_synchronize];
+}
+
+void
+X11ApplicationMain (int argc, const char *argv[],
+ void (*server_thread) (void *), void *server_arg)
+{
+ NSAutoreleasePool *pool;
+
+#ifdef DEBUG
+ while (access ("/tmp/x11-block", F_OK) == 0)
+ sleep (1);
+#endif
+
+ pool = [[NSAutoreleasePool alloc] init];
+
+ X11App = (X11Application *) [X11Application sharedApplication];
+
+ init_ports ();
+
+ [NSApp read_defaults];
+
+ [NSBundle loadNibNamed:@"main" owner:NSApp];
+
+ [[NSNotificationCenter defaultCenter] addObserver:NSApp
+ selector:@selector (became_key:)
+ name:NSWindowDidBecomeKeyNotification object:nil];
+
+ check_xinitrc ();
+
+ if (!create_thread (server_thread, server_arg))
+ {
+ fprintf (stderr, "can't create secondary thread\n");
+ exit (1);
+ }
+
+ [NSApp run];
+
+ /* not reached */
+}
+
+\f
+/* event conversion */
+
+static inline unsigned short
+convert_flags (unsigned int nsflags)
+{
+ unsigned int xflags;
+
+ if (nsflags == ~0)
+ return 0xffff;
+
+ xflags = 0;
+
+ if (nsflags & NSAlphaShiftKeyMask)
+ xflags |= LockMask;
+ if (nsflags & NSShiftKeyMask)
+ xflags |= ShiftMask;
+ if (nsflags & NSControlKeyMask)
+ xflags |= ControlMask;
+ if (nsflags & NSAlternateKeyMask)
+ xflags |= Mod1Mask;
+ if (nsflags & NSCommandKeyMask)
+ xflags |= Mod2Mask;
+ /* FIXME: secondaryfn? */
+
+ return xflags;
+}
+
+static void
+send_nsevent (NSEventType type, NSEvent *e)
+{
+ static unsigned int button_state = 0;
+
+ xEvent xe;
+
+ memset (&xe, 0, sizeof (xe));
+
+ switch (type)
+ {
+ NSRect screen;
+ NSPoint location;
+ NSWindow *window;
+ int pointer_x, pointer_y, count;
+
+ case NSLeftMouseDown:
+ xe.u.u.type = ButtonPress;
+ xe.u.u.detail = 1;
+ goto do_press_event;
+
+ case NSRightMouseDown:
+ xe.u.u.type = ButtonPress;
+ xe.u.u.detail = 3;
+ goto do_press_event;
+
+ case NSOtherMouseDown:
+ xe.u.u.type = ButtonPress;
+ xe.u.u.detail = 2; /* FIXME? */
+ goto do_press_event;
+
+ do_press_event:
+ if (RootlessKnowsWindowNumber ([e windowNumber]) == NULL)
+ {
+ /* X server doesn't grok this window, drop the event.
+
+ Note: theoretically this isn't necessary, but if I click
+ on the menubar, we get sent a LeftMouseDown when the
+ release happens, but no LeftMouseUp is ever seen! */
+
+ break;
+ }
+ goto do_event;
+
+ case NSLeftMouseUp:
+ xe.u.u.type = ButtonRelease;
+ xe.u.u.detail = 1;
+ goto do_release_event;
+
+ case NSRightMouseUp:
+ xe.u.u.type = ButtonRelease;
+ xe.u.u.detail = 3;
+ goto do_release_event;
+
+ case NSOtherMouseUp:
+ xe.u.u.type = ButtonRelease;
+ xe.u.u.detail = 2; /* FIXME? */
+ goto do_release_event;
+
+ do_release_event:
+ if ((button_state & (1 << xe.u.u.detail)) == 0)
+ {
+ /* X didn't see the button press for this release, so skip it */
+ break;
+ }
+ goto do_event;
+
+ case NSMouseMoved:
+ case NSLeftMouseDragged:
+ case NSRightMouseDragged:
+ case NSOtherMouseDragged:
+ /* convert location to global top-left coordinates */
+
+ location = [e locationInWindow];
+ window = [e window];
+ screen = [[[NSScreen screens] objectAtIndex:0] frame];
+
+ if (window != nil)
+ {
+ NSRect frame = [window frame];
+ pointer_x = location.x + frame.origin.x;
+ pointer_y = (((screen.origin.y + screen.size.height)
+ - location.y) - frame.origin.y);
+ }
+ else
+ {
+ pointer_x = location.x;
+ pointer_y = (screen.origin.y + screen.size.height) - location.y;
+ }
+
+ xe.u.keyButtonPointer.rootX = pointer_x;
+ xe.u.keyButtonPointer.rootY = pointer_y;
+ xe.u.u.type = MotionNotify;
+ goto do_event;
+
+ case NSKeyDown:
+ xe.u.u.type = KeyPress;
+ xe.u.u.detail = [e keyCode];
+ goto do_event;
+
+ case NSKeyUp:
+ xe.u.u.type = KeyRelease;
+ xe.u.u.detail = [e keyCode];
+ goto do_event;
+
+ case NSScrollWheel:
+ xe.u.keyButtonPointer.state = convert_flags ([e modifierFlags]);
+ count = [e deltaY];
+ xe.u.u.detail = count > 0 ? 4 : 5;
+ for (count = abs (count); count-- > 0;)
+ {
+ xe.u.u.type = ButtonPress;
+ DarwinEnqueueEvent (&xe);
+ xe.u.u.type = ButtonRelease;
+ DarwinEnqueueEvent (&xe);
+ }
+ xe.u.u.type = 0;
+ break;
+
+ case NSFlagsChanged:
+ do_event:
+ xe.u.keyButtonPointer.state = convert_flags ([e modifierFlags]);
+ DarwinEnqueueEvent (&xe);
+ break;
+
+ default: break; /* for gcc */
+ }
+
+ if (xe.u.u.type == ButtonPress)
+ button_state |= (1 << xe.u.u.detail);
+ else if (xe.u.u.type == ButtonRelease)
+ button_state &= ~(1 << xe.u.u.detail);
+}
--- /dev/null
+/* X11Controller.h -- connect the IB ui
+ $Id: X11Controller.h,v 1.21 2003/07/24 17:52:29 jharper Exp $
+
+ Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
+
+ Permission is hereby granted, free of charge, to any person
+ obtaining a copy of this software and associated documentation files
+ (the "Software"), to deal in the Software without restriction,
+ including without limitation the rights to use, copy, modify, merge,
+ publish, distribute, sublicense, and/or sell copies of the Software,
+ and to permit persons to whom the Software is furnished to do so,
+ subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT
+ HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ DEALINGS IN THE SOFTWARE.
+
+ Except as contained in this notice, the name(s) of the above
+ copyright holders shall not be used in advertising or otherwise to
+ promote the sale, use or other dealings in this Software without
+ prior written authorization. */
+
+#ifndef X11CONTROLLER_H
+#define X11CONTROLLER_H 1
+
+#if __OBJC__
+
+#import <Cocoa/Cocoa.h>
+#include "x-list.h"
+
+@interface X11Controller : NSObject
+{
+ NSPanel *prefs_panel;
+
+ NSButton *fake_buttons;
+ NSButton *enable_fullscreen;
+ NSButton *use_sysbeep;
+ NSButton *enable_keyequivs;
+ NSButton *sync_keymap;
+ NSButton *enable_auth;
+ NSButton *enable_tcp;
+ NSPopUpButton *depth;
+
+ NSMenuItem *x11_about_item;
+ NSMenuItem *window_separator;
+ NSMenuItem *dock_window_separator;
+ NSMenuItem *apps_separator;
+ NSMenuItem *toggle_fullscreen_item;
+ NSMenu *dock_apps_menu;
+ NSTableView *apps_table;
+
+ NSArray *apps;
+ NSMutableArray *table_apps;
+
+ NSMenu *dock_menu;
+
+ int checked_window_item;
+ x_list *pending_apps;
+
+ BOOL finished_launching;
+ BOOL can_quit;
+}
+
+- (void) set_window_menu:(NSArray *)list;
+- (void) set_window_menu_check:(NSNumber *)n;
+- (void) set_apps_menu:(NSArray *)list;
+- (void) set_can_quit:(BOOL)state;
+- (void) server_ready;
+
+@end
+
+#endif /* __OBJC__ */
+
+extern void X11ControllerMain (int argc, const char *argv[],
+ void (*server_thread) (void *),
+ void *server_arg);
+
+#endif /* X11CONTROLLER_H */
--- /dev/null
+/* X11Controller.m -- connect the IB ui, also the NSApp delegate
+ $Id: X11Controller.m,v 1.36 2003/07/24 17:52:29 jharper Exp $
+
+ Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
+
+ Permission is hereby granted, free of charge, to any person
+ obtaining a copy of this software and associated documentation files
+ (the "Software"), to deal in the Software without restriction,
+ including without limitation the rights to use, copy, modify, merge,
+ publish, distribute, sublicense, and/or sell copies of the Software,
+ and to permit persons to whom the Software is furnished to do so,
+ subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT
+ HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ DEALINGS IN THE SOFTWARE.
+
+ Except as contained in this notice, the name(s) of the above
+ copyright holders shall not be used in advertising or otherwise to
+ promote the sale, use or other dealings in this Software without
+ prior written authorization. */
+#define __DARWIN__
+
+#import "X11Controller.h"
+#import "X11Application.h"
+#import <Carbon/Carbon.h>
+
+
+/* ouch! */
+#define BOOL X_BOOL
+# include "Xproto.h"
+#define WindowPtr X_WindowPtr
+#define Cursor X_Cursor
+# include "quartz.h"
+# define _APPLEWM_SERVER_
+# include "applewm.h"
+# include "X.h"
+#undef Cursor
+#undef WindowPtr
+#undef BOOL
+
+#include <stdio.h>
+#include <unistd.h>
+
+#define TRACE() fprintf (stderr, "%s\n", __FUNCTION__)
+
+@implementation X11Controller
+
+- (void) awakeFromNib
+{
+ X11Application *xapp = NSApp;
+ NSArray *array;
+
+ /* Point X11Application at ourself. */
+ [xapp set_controller:self];
+#if 0
+ array = [xapp prefs_get_array:@PREFS_APPSMENU];
+ if (array != nil)
+ {
+ int count;
+
+ /* convert from [TITLE1 COMMAND1 TITLE2 COMMAND2 ...]
+ to [[TITLE1 COMMAND1] [TITLE2 COMMAND2] ...] format. */
+
+ count = [array count];
+ if (count > 0
+ && ![[array objectAtIndex:0] isKindOfClass:[NSArray class]])
+ {
+ int i;
+ NSMutableArray *copy, *sub;
+
+ copy = [NSMutableArray arrayWithCapacity:(count / 2)];
+
+ for (i = 0; i < count / 2; i++)
+ {
+ sub = [[NSMutableArray alloc] initWithCapacity:3];
+ [sub addObject:[array objectAtIndex:i*2]];
+ [sub addObject:[array objectAtIndex:i*2+1]];
+ [sub addObject:@""];
+ [copy addObject:sub];
+ [sub release];
+ }
+
+ array = copy;
+ }
+
+ [self set_apps_menu:array];
+ }
+ #endif
+}
+
+- (void) item_selected:sender
+{
+ [NSApp activateIgnoringOtherApps:YES];
+
+ QuartzMessageMainThread (kXquartzControllerNotify, 2,
+ AppleWMWindowMenuItem, [sender tag]);
+}
+
+- (void) remove_window_menu
+{
+ NSMenu *menu;
+ int first, count, i;
+
+ /* Work backwards so we don't mess up the indices */
+ menu = [window_separator menu];
+ first = [menu indexOfItem:window_separator] + 1;
+ count = [menu numberOfItems];
+ for (i = count - 1; i >= first; i--)
+ [menu removeItemAtIndex:i];
+
+ menu = [dock_window_separator menu];
+ count = [menu indexOfItem:dock_window_separator];
+ for (i = 0; i < count; i++)
+ [dock_menu removeItemAtIndex:0];
+}
+
+- (void) install_window_menu:(NSArray *)list
+{
+ NSMenu *menu;
+ NSMenuItem *item;
+ int first, count, i;
+
+ menu = [window_separator menu];
+ first = [menu indexOfItem:window_separator] + 1;
+ count = [list count];
+
+ for (i = 0; i < count; i++)
+ {
+ NSString *name, *shortcut;
+
+ name = [[list objectAtIndex:i] objectAtIndex:0];
+ shortcut = [[list objectAtIndex:i] objectAtIndex:1];
+
+ item = (NSMenuItem *) [menu addItemWithTitle:name action:@selector
+ (item_selected:) keyEquivalent:shortcut];
+ [item setTarget:self];
+ [item setTag:i];
+ [item setEnabled:YES];
+
+ item = (NSMenuItem *) [dock_menu insertItemWithTitle:name
+ action:@selector
+ (item_selected:) keyEquivalent:shortcut
+ atIndex:i];
+ [item setTarget:self];
+ [item setTag:i];
+ [item setEnabled:YES];
+ }
+
+ if (checked_window_item >= 0 && checked_window_item < count)
+ {
+ item = (NSMenuItem *) [menu itemAtIndex:first + checked_window_item];
+ [item setState:NSOnState];
+ item = (NSMenuItem *) [dock_menu itemAtIndex:checked_window_item];
+ [item setState:NSOnState];
+ }
+}
+
+- (void) remove_apps_menu
+{
+ NSMenu *menu;
+ NSMenuItem *item;
+ int i;
+
+ if (apps == nil || apps_separator == nil)
+ return;
+
+ menu = [apps_separator menu];
+
+ if (menu != nil)
+ {
+ for (i = [menu numberOfItems] - 1; i >= 0; i--)
+ {
+ item = (NSMenuItem *) [menu itemAtIndex:i];
+ if ([item tag] != 0)
+ [menu removeItemAtIndex:i];
+ }
+ }
+
+ if (dock_apps_menu != nil)
+ {
+ for (i = [dock_apps_menu numberOfItems] - 1; i >= 0; i--)
+ {
+ item = (NSMenuItem *) [dock_apps_menu itemAtIndex:i];
+ if ([item tag] != 0)
+ [dock_apps_menu removeItemAtIndex:i];
+ }
+ }
+
+ [apps release];
+ apps = nil;
+}
+
+- (void) prepend_apps_item:(NSArray *)list index:(int)i menu:(NSMenu *)menu
+{
+ NSString *title, *shortcut = @"";
+ NSArray *group;
+ NSMenuItem *item;
+
+ group = [list objectAtIndex:i];
+ title = [group objectAtIndex:0];
+ if ([group count] >= 3)
+ shortcut = [group objectAtIndex:2];
+
+ if ([title length] != 0)
+ {
+ item = (NSMenuItem *) [menu insertItemWithTitle:title
+ action:@selector (app_selected:)
+ keyEquivalent:shortcut atIndex:0];
+ [item setTarget:self];
+ [item setEnabled:YES];
+ }
+ else
+ {
+ item = (NSMenuItem *) [NSMenuItem separatorItem];
+ [menu insertItem:item atIndex:0];
+ }
+
+ [item setTag:i+1]; /* can't be zero, so add one */
+}
+
+- (void) install_apps_menu:(NSArray *)list
+{
+ NSMenu *menu;
+ int i, count;
+
+ count = [list count];
+
+ if (count == 0 || apps_separator == nil)
+ return;
+
+ menu = [apps_separator menu];
+
+ for (i = count - 1; i >= 0; i--)
+ {
+ if (menu != nil)
+ [self prepend_apps_item:list index:i menu:menu];
+ if (dock_apps_menu != nil)
+ [self prepend_apps_item:list index:i menu:dock_apps_menu];
+ }
+
+ apps = [list retain];
+}
+
+- (void) set_window_menu:(NSArray *)list
+{
+ [self remove_window_menu];
+ [self install_window_menu:list];
+
+ QuartzMessageMainThread (kXquartzControllerNotify, 1,
+ AppleWMWindowMenuNotify);
+}
+
+- (void) set_window_menu_check:(NSNumber *)nn
+{
+ NSMenu *menu;
+ NSMenuItem *item;
+ int first, count;
+ int n = [nn intValue];
+
+ menu = [window_separator menu];
+ first = [menu indexOfItem:window_separator] + 1;
+ count = [menu numberOfItems] - first;
+
+ if (checked_window_item >= 0 && checked_window_item < count)
+ {
+ item = (NSMenuItem *) [menu itemAtIndex:first + checked_window_item];
+ [item setState:NSOffState];
+ item = (NSMenuItem *) [dock_menu itemAtIndex:checked_window_item];
+ [item setState:NSOffState];
+ }
+ if (n >= 0 && n < count)
+ {
+ item = (NSMenuItem *) [menu itemAtIndex:first + n];
+ [item setState:NSOnState];
+ item = (NSMenuItem *) [dock_menu itemAtIndex:n];
+ [item setState:NSOnState];
+ }
+ checked_window_item = n;
+}
+
+- (void) set_apps_menu:(NSArray *)list
+{
+ [self remove_apps_menu];
+ [self install_apps_menu:list];
+}
+
+- (void) launch_client:(NSString *)command
+{
+ QuartzRunClient ([command cString]);
+}
+
+- (void) app_selected:sender
+{
+ int tag;
+ NSString *item;
+
+ tag = [sender tag] - 1;
+ if (apps == nil || tag < 0 || tag >= [apps count])
+ return;
+
+ item = [[apps objectAtIndex:tag] objectAtIndex:1];
+
+ [self launch_client:item];
+}
+
+- (IBAction) apps_table_show:sender
+{
+ NSArray *columns;
+
+ if (table_apps == nil)
+ {
+ table_apps = [[NSMutableArray alloc] initWithCapacity:1];
+
+ if (apps != nil)
+ [table_apps addObjectsFromArray:apps];
+ }
+
+ columns = [apps_table tableColumns];
+ [[columns objectAtIndex:0] setIdentifier:@"0"];
+ [[columns objectAtIndex:1] setIdentifier:@"1"];
+ [[columns objectAtIndex:2] setIdentifier:@"2"];
+
+ [apps_table setDataSource:self];
+ [apps_table selectRow:0 byExtendingSelection:NO];
+
+ [[apps_table window] makeKeyAndOrderFront:sender];
+}
+
+- (IBAction) apps_table_cancel:sender
+{
+ [[apps_table window] orderOut:sender];
+
+ [table_apps release];
+ table_apps = nil;
+}
+
+- (IBAction) apps_table_done:sender
+{
+ [apps_table deselectAll:sender]; /* flush edits? */
+
+ [self remove_apps_menu];
+ [self install_apps_menu:table_apps];
+
+ [NSApp prefs_set_array:@PREFS_APPSMENU value:table_apps];
+ [NSApp prefs_synchronize];
+
+ [[apps_table window] orderOut:sender];
+
+ [table_apps release];
+ table_apps = nil;
+}
+
+- (IBAction) apps_table_new:sender
+{
+ NSMutableArray *item;
+
+ int row = [apps_table selectedRow], i;
+
+ if (row < 0)
+ row = 0;
+ else
+ row = row + 1;
+
+ i = row;
+ if (i > [table_apps count])
+ return; /* avoid exceptions */
+
+ item = [[NSMutableArray alloc] initWithCapacity:3];
+ [item addObject:@""];
+ [item addObject:@""];
+ [item addObject:@""];
+
+ [table_apps insertObject:item atIndex:i];
+ [item release];
+
+ [apps_table noteNumberOfRowsChanged];
+ [apps_table selectRow:row byExtendingSelection:NO];
+}
+
+- (IBAction) apps_table_duplicate:sender
+{
+ int row = [apps_table selectedRow], i;
+ NSObject *a;
+
+ if (row < 0)
+ {
+ [self apps_table_new:sender];
+ return;
+ }
+
+ i = row;
+ if (i > [table_apps count] - 1)
+ return; /* avoid exceptions */
+
+ a = [table_apps objectAtIndex:i];
+ [table_apps insertObject:[a copy] atIndex:i];
+
+ [apps_table noteNumberOfRowsChanged];
+ [apps_table selectRow:row+1 byExtendingSelection:NO];
+}
+
+- (IBAction) apps_table_delete:sender
+{
+ int row = [apps_table selectedRow];
+
+ if (row >= 0)
+ {
+ int i = row;
+
+ if (i > [table_apps count] - 1)
+ return; /* avoid exceptions */
+
+ [table_apps removeObjectAtIndex:i];
+ }
+
+ [apps_table noteNumberOfRowsChanged];
+}
+
+- (int) numberOfRowsInTableView:(NSTableView *)tableView
+{
+ if (table_apps == nil)
+ return 0;
+
+ return [table_apps count];
+}
+
+- (id) tableView:(NSTableView *)tableView
+ objectValueForTableColumn:(NSTableColumn *)tableColumn row:(int)row
+{
+ NSArray *item;
+ int col;
+
+ if (table_apps == nil)
+ return nil;
+
+ col = [[tableColumn identifier] intValue];
+
+ item = [table_apps objectAtIndex:row];
+ if ([item count] > col)
+ return [item objectAtIndex:col];
+ else
+ return @"";
+}
+
+- (void) tableView:(NSTableView *)tableView setObjectValue:(id)object
+ forTableColumn:(NSTableColumn *)tableColumn row:(int)row
+{
+ NSMutableArray *item;
+ int col;
+
+ if (table_apps == nil)
+ return;
+
+ col = [[tableColumn identifier] intValue];
+
+ item = [table_apps objectAtIndex:row];
+ [item replaceObjectAtIndex:col withObject:object];
+}
+
+- (void) hide_window:sender
+{
+ if ([X11App x_active])
+ QuartzMessageMainThread (kXquartzControllerNotify, 1, AppleWMHideWindow);
+ else
+ NSBeep (); /* FIXME: something here */
+}
+
+- (IBAction)bring_to_front:sender
+{
+ QuartzMessageMainThread (kXquartzControllerNotify, 1,
+ AppleWMBringAllToFront);
+}
+
+- (IBAction)close_window:sender
+{
+ if ([X11App x_active])
+ QuartzMessageMainThread (kXquartzControllerNotify, 1, AppleWMCloseWindow);
+ else
+ [[NSApp keyWindow] performClose:sender];
+}
+
+- (IBAction)minimize_window:sender
+{
+ if ([X11App x_active])
+ QuartzMessageMainThread (kXquartzControllerNotify, 1, AppleWMMinimizeWindow);
+ else
+ [[NSApp keyWindow] performMiniaturize:sender];
+}
+
+- (IBAction)zoom_window:sender
+{
+ if ([X11App x_active])
+ QuartzMessageMainThread (kXquartzControllerNotify, 1, AppleWMZoomWindow);
+ else
+ [[NSApp keyWindow] performZoom:sender];
+}
+
+- (IBAction) next_window:sender
+{
+ QuartzMessageMainThread (kXquartzControllerNotify, 1, AppleWMNextWindow);
+}
+
+- (IBAction) previous_window:sender
+{
+ QuartzMessageMainThread (kXquartzControllerNotify,
+ 1, AppleWMPreviousWindow);
+}
+
+- (IBAction) enable_fullscreen_changed:sender
+{
+ int value = ![enable_fullscreen intValue];
+
+ QuartzMessageMainThread (kXquartzSetRootless, 1, value);
+
+ [NSApp prefs_set_boolean:@PREFS_ROOTLESS value:value];
+ [NSApp prefs_synchronize];
+}
+
+- (IBAction) toggle_fullscreen:sender
+{
+ QuartzMessageMainThread (kXquartzToggleFullscreen, 0);
+}
+
+- (void) set_can_quit:(BOOL)state
+{
+ can_quit = state;
+}
+
+- (IBAction)prefs_changed:sender
+{
+ darwinFakeButtons = [fake_buttons intValue];
+ quartzUseSysBeep = [use_sysbeep intValue];
+ X11EnableKeyEquivalents = [enable_keyequivs intValue];
+ darwinSyncKeymap = [sync_keymap intValue];
+
+ /* after adding prefs here, also add to [X11Application read_defaults]
+ and below */
+
+ [NSApp prefs_set_boolean:@PREFS_FAKEBUTTONS value:darwinFakeButtons];
+ [NSApp prefs_set_boolean:@PREFS_SYSBEEP value:quartzUseSysBeep];
+ [NSApp prefs_set_boolean:@PREFS_KEYEQUIVS value:X11EnableKeyEquivalents];
+ [NSApp prefs_set_boolean:@PREFS_SYNC_KEYMAP value:darwinSyncKeymap];
+ [NSApp prefs_set_boolean:@PREFS_NO_AUTH value:![enable_auth intValue]];
+ [NSApp prefs_set_boolean:@PREFS_NO_TCP value:![enable_tcp intValue]];
+ [NSApp prefs_set_integer:@PREFS_DEPTH value:[depth selectedTag]];
+
+ [NSApp prefs_synchronize];
+}
+
+- (IBAction) prefs_show:sender
+{
+ [fake_buttons setIntValue:darwinFakeButtons];
+ [use_sysbeep setIntValue:quartzUseSysBeep];
+ [enable_keyequivs setIntValue:X11EnableKeyEquivalents];
+ [sync_keymap setIntValue:darwinSyncKeymap];
+ [sync_keymap setEnabled:darwinKeymapFile == NULL];
+
+ [enable_auth setIntValue:![NSApp prefs_get_boolean:@PREFS_NO_AUTH default:NO]];
+ [enable_tcp setIntValue:![NSApp prefs_get_boolean:@PREFS_NO_TCP default:NO]];
+ [depth selectItemAtIndex:[depth indexOfItemWithTag:[NSApp prefs_get_integer:@PREFS_DEPTH default:-1]]];
+
+ [enable_fullscreen setIntValue:!quartzEnableRootless];
+
+ [prefs_panel makeKeyAndOrderFront:sender];
+}
+
+- (IBAction) quit:sender
+{
+ QuartzMessageMainThread (kXdarwinQuit, 0);
+}
+
+- (IBAction) x11_help:sender
+{
+ AHLookupAnchor (CFSTR ("Mac Help"), CFSTR ("mchlp2276"));
+}
+
+- (BOOL) validateMenuItem:(NSMenuItem *)item
+{
+ NSMenu *menu = [item menu];
+
+ if (item == toggle_fullscreen_item)
+ {
+ return !quartzEnableRootless;
+ }
+ else if (menu == [window_separator menu] || menu == dock_menu
+ || (menu == [x11_about_item menu] && [item tag] == 42))
+ {
+ return (AppleWMSelectedEvents () & AppleWMControllerNotifyMask) != 0;
+ }
+ else
+ {
+ return TRUE;
+ }
+}
+
+- (void) applicationDidHide:(NSNotification *)notify
+{
+ QuartzMessageMainThread (kXquartzControllerNotify, 1, AppleWMHideAll);
+}
+
+- (void) applicationDidUnhide:(NSNotification *)notify
+{
+ QuartzMessageMainThread (kXquartzControllerNotify, 1, AppleWMShowAll);
+}
+
+- (NSApplicationTerminateReply) applicationShouldTerminate:sender
+{
+ NSString *msg;
+
+ if (can_quit || [X11App prefs_get_boolean:@PREFS_NO_QUIT_ALERT default:NO])
+ {
+ return NSTerminateNow;
+ }
+
+ /* Make sure we're frontmost. */
+ [NSApp activateIgnoringOtherApps:YES];
+
+ msg = NSLocalizedString (@"Are you sure you want to quit X11?\n\n\
+If you quit X11, any X11 applications you are running will stop immediately \
+and you will lose any changes you have not saved.", @"");
+
+ /* FIXME: safe to run the alert in here? Or should we return Later
+ and then run the alert on a timer? It seems to work here, so.. */
+
+ return (NSRunAlertPanel (nil, msg, NSLocalizedString (@"Quit", @""),
+ NSLocalizedString (@"Cancel", @""), nil)
+ == NSAlertDefaultReturn) ? NSTerminateNow : NSTerminateCancel;
+}
+
+- (void) applicationWillTerminate:(NSNotification *)aNotification
+{
+ [X11App prefs_synchronize];
+
+ /* shutdown the X server, it will exit () for us. */
+ QuartzMessageMainThread (kXdarwinQuit, 0);
+
+ /* In case it doesn't, exit anyway after a while. */
+ while (sleep (10) != 0) ;
+ exit (1);
+}
+
+- (void) server_ready
+{
+ x_list *node;
+
+ finished_launching = YES;
+
+ for (node = pending_apps; node != NULL; node = node->next)
+ {
+ NSString *filename = node->data;
+ QuartzRunClient ([filename UTF8String]);
+ [filename release];
+ }
+
+ x_list_free (pending_apps);
+ pending_apps = NULL;
+}
+
+- (BOOL) application:(NSApplication *)app openFile:(NSString *)filename
+{
+#if 0
+ const char *name = [filename UTF8String];
+
+ if (finished_launching)
+ QuartzRunClient (name);
+ else if (name[0] != ':') /* ignore display names */
+ pending_apps = x_list_prepend (pending_apps, [filename retain]);
+
+ /* FIXME: report failures. */
+ return YES;
+#endif
+ return NO;
+}
+
+@end
+
+void X11ControllerMain (int argc, const char *argv[],
+ void (*server_thread) (void *), void *server_arg)
+{
+ X11ApplicationMain (argc, argv, server_thread, server_arg);
+}
--- /dev/null
+.\" $XFree86: xc/programs/Xserver/hw/darwin/XDarwin.man,v 1.4 2002/01/09 18:01:58 torrey Exp $
+.\"
+.TH XQUARTZ 1 __vendorversion__
+.SH NAME
+Xquartz \- X window system server for Quartz operating system
+.SH SYNOPSIS
+.B Xquartz
+[ options ] ...
+.SH DESCRIPTION
+.I Xquartz
+is the X window server for Mac OS X provided by Apple.
+.I Xquartz
+runs in parallel with Aqua in rootless mode. In rootless mode, the X
+window system and Mac OS X share your display. The root window of the
+X11 display is the size of the screen and contains all the other
+windows. The X11 root window is not displayed in rootless mode as Mac
+OS X handles the desktop background.
+.SH OPTIONS
+.PP
+In addition to the normal server options described in the \fIXserver(1)\fP
+manual page, \fIXquartz\fP accepts the following command line switches:
+.TP 8
+.B \-fakebuttons
+Emulates a 3 button mouse using modifier keys. By default, the Command modifier
+is used to emulate button 2 and Option is used for button 3. Thus, clicking the
+first mouse button while holding down Command will act like clicking
+button 2. Holding down Option will simulate button 3.
+.TP 8
+.B \-nofakebuttons
+Do not emulate a 3 button mouse. This is the default.
+.TP 8
+.B "\-fakemouse2 \fImodifiers\fP"
+Change the modifier keys used to emulate the second mouse button. By default,
+Command is used to emulate the second button. Any combination of the following
+modifier names may be used: Shift, Option, Control, Command, Fn. For example,
+.B \-fakemouse2 """Option,Shift""
+will set holding Option, Shift and clicking on button one as equivalent to
+clicking the second mouse button.
+.TP 8
+.B "\-fakemouse3 \fImodifiers\fP"
+Change the modifier keys used to emulate the third mouse button. By default,
+Option is used to emulate the third button. Any combination of the following
+modifier names may be used: Shift, Option, Control, Command, Fn. For example,
+.B \-fakemouse3 """Control,Shift""
+will set holding Control, Shift and clicking on button one as equivalent to
+clicking the third mouse button.
+.TP 8
+.B "\-swapAltMeta"
+Swaps the meaning of the Alt and Meta modifier keys.
+.TP 8
+.B "\-keymap \fIfile\fP"
+On startup \fIXquartz\fP translates a Darwin keymapping into an X keymap.
+The default is to read this keymapping from USA.keymapping. With this option
+the keymapping will be read from \fIfile\fP instead. If the file's path is
+not specified, it will be searched for in Library/Keyboards/ underneath the
+following directories (in order): ~, /, /Network, /System.
+.TP 8
+.B \-nokeymap
+On startup \fIXquartz\fP translates a Darwin keymapping into an X keymap.
+With this option \fIXquartz\fP queries the kernel for the current keymapping
+instead of reading it from a file. This will often fail on newer kernels.
+.TP 8
+.B "\-depth \fIdepth\fP"
+Specifies the color bit depth to use. Currently only 15, and 24 color
+bits per pixel are supported. If not specified, defaults to the depth
+of the main display.
+.SH CUSTOMIZATION
+\fIXquartz\fP can also be customized using the defaults(1) command. The available options are:
+.TP 8
+.B defaults write com.apple.x11 enable_fake_buttons -boolean true
+Equivalent to the \fB-fakebuttons\fP command line option.
+.TP 8
+.B defaults write com.apple.x11 fake_button2 \fImodifiers\fP
+Equivalent to the \fB-fakemouse2\fP option.
+.TP 8
+.B defaults write com.apple.x11 fake_button3 \fImodifiers\fP
+Equivalent to the \fB-fakemouse3\fP option.
+.TP 8
+.B defaults write com.apple.x11 swap_alt_meta -boolean true
+Equivalent to the \fB-swapAltMeta\fP option.
+.TP 8
+.B defaults write com.apple.x11 keymap_file \fIfilename\fP
+Equivalent to the \fB-keymap\fP option.
+.TP 8
+.B defaults write com.apple.x11 no_quit_alert -boolean true
+Disables the alert dialog displayed when attempting to quit X11.
+.TP 8
+.B defaults write com.apple.x11 no_auth -boolean true
+Stops the X server requiring that clients authenticate themselves when
+connecting. See Xsecurity(__miscmansuffix__).
+.TP 8
+.B defaults write com.apple.x11 nolisten_tcp -boolean true
+Prevents the X server accepting remote connections.
+.TP 8
+.B defaults write com.apple.x11 xinit_kills_server -boolean false
+Stops the X server exiting when the xinitrc script terminates.
+.TP 8
+.B defaults write com.apple.x11 fullscreen_hotkeys -boolean false
+Allows system hotkeys to be handled while in X11 fullscreen mode.
+.TP 8
+.B defaults write com.apple.x11 enable_system_beep -boolean false
+Don't use the standard system beep effect for X11 alerts.
+.TP 8
+.B defaults write com.apple.x11 enable_key_equivalents -boolean false
+Disable menu keyboard equivalents while X11 windows are focused.
+.TP 8
+.B defaults write com.apple.x11 depth \fIdepth\fP
+Equivalent to the \fB-depth\fP option.
+.SH "SEE ALSO"
+.PP
+X(__miscmansuffix__), XFree86(1), Xserver(1), xdm(1), xinit(1)
+.PP
+.SH AUTHORS
+XFree86 was originally ported to Mac OS X Server by John Carmack. Dave
+Zarzycki used this as the basis of his port of XFree86 4.0 to Darwin 1.0.
+Torrey T. Lyons improved and integrated this code into the XFree86
+Project's mainline for the 4.0.2 release.
+.PP
+The following members of the XonX Team contributed to the following
+releases (in alphabetical order):
+.TP 4
+XFree86 4.1.0:
+.br
+Rob Braun - Darwin x86 support
+.br
+Torrey T. Lyons - Project Lead
+.br
+Andreas Monitzer - Cocoa version of XDarwin front end
+.br
+Gregory Robert Parker - Original Quartz implementation
+.br
+Christoph Pfisterer - Dynamic shared X libraries
+.br
+Toshimitsu Tanaka - Japanese localization
+.TP 4
+XFree86 4.2.0:
+.br
+Rob Braun - Darwin x86 support
+.br
+Pablo Di Noto - Spanish localization
+.br
+Paul Edens - Dutch localization
+.br
+Kyunghwan Kim - Korean localization
+.br
+Mario Klebsch - Non-US keyboard support
+.br
+Torrey T. Lyons - Project Lead
+.br
+Andreas Monitzer - German localization
+.br
+Patrik Montgomery - Swedish localization
+.br
+Greg Parker - Rootless support
+.br
+Toshimitsu Tanaka - Japanese localization
+.br
+Olivier Verdier - French localization
--- /dev/null
+/* $XFree86: xc/programs/Xserver/GL/dri/xf86dri.c,v 1.10 2000/12/07 20:26:14 dawes Exp $ */
+/**************************************************************************
+
+Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
+Copyright 2000 VA Linux Systems, Inc.
+Copyright (c) 2002 Apple Computer, Inc.
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/*
+ * Authors:
+ * Kevin E. Martin <martin@valinux.com>
+ * Jens Owen <jens@valinux.com>
+ * Rickard E. (Rik) Faith <faith@valinux.com>
+ *
+ */
+
+#define NEED_REPLIES
+#define NEED_EVENTS
+#include "X.h"
+#include "Xproto.h"
+#include "misc.h"
+#include "dixstruct.h"
+#include "extnsionst.h"
+#include "colormapst.h"
+#include "cursorstr.h"
+#include "scrnintstr.h"
+#include "servermd.h"
+#define _APPLEDRI_SERVER_
+#include "appledristr.h"
+#include "swaprep.h"
+#include "dri.h"
+#include "dri-surface.h"
+#include "dristruct.h"
+#include "rootless-common.h"
+#include "X11Application.h"
+
+static int DRIErrorBase;
+
+static DISPATCH_PROC(ProcAppleDRIDispatch);
+static DISPATCH_PROC(SProcAppleDRIDispatch);
+
+static void AppleDRIResetProc(ExtensionEntry* extEntry);
+
+static unsigned char DRIReqCode = 0;
+static int DRIEventBase = 0;
+
+extern void AppleDRIExtensionInit(void);
+
+static void SNotifyEvent(xAppleDRINotifyEvent *from, xAppleDRINotifyEvent *to);
+
+typedef struct _DRIEvent *DRIEventPtr;
+typedef struct _DRIEvent {
+ DRIEventPtr next;
+ ClientPtr client;
+ XID clientResource;
+ unsigned int mask;
+} DRIEventRec;
+
+void
+AppleDRIExtensionInit(void)
+{
+ ExtensionEntry* extEntry;
+
+ if (DRIExtensionInit() &&
+ (extEntry = AddExtension(APPLEDRINAME,
+ AppleDRINumberEvents,
+ AppleDRINumberErrors,
+ ProcAppleDRIDispatch,
+ SProcAppleDRIDispatch,
+ AppleDRIResetProc,
+ StandardMinorOpcode))) {
+ DRIReqCode = (unsigned char)extEntry->base;
+ DRIErrorBase = extEntry->errorBase;
+ DRIEventBase = extEntry->eventBase;
+ EventSwapVector[DRIEventBase] = (EventSwapPtr) SNotifyEvent;
+ }
+}
+
+/*ARGSUSED*/
+static void
+AppleDRIResetProc (
+ ExtensionEntry* extEntry
+)
+{
+ DRIReset();
+}
+
+static int
+ProcAppleDRIQueryVersion(
+ register ClientPtr client
+)
+{
+ xAppleDRIQueryVersionReply rep;
+ register int n;
+
+ REQUEST_SIZE_MATCH(xAppleDRIQueryVersionReq);
+ rep.type = X_Reply;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+ rep.majorVersion = APPLE_DRI_MAJOR_VERSION;
+ rep.minorVersion = APPLE_DRI_MINOR_VERSION;
+ rep.patchVersion = APPLE_DRI_PATCH_VERSION;
+ if (client->swapped) {
+ swaps(&rep.sequenceNumber, n);
+ swapl(&rep.length, n);
+ }
+ WriteToClient(client, sizeof(xAppleDRIQueryVersionReply), (char *)&rep);
+ return (client->noClientException);
+}
+
+\f
+/* surfaces */
+
+static int
+ProcAppleDRIQueryDirectRenderingCapable(
+ register ClientPtr client
+)
+{
+ xAppleDRIQueryDirectRenderingCapableReply rep;
+ Bool isCapable;
+
+ REQUEST(xAppleDRIQueryDirectRenderingCapableReq);
+ REQUEST_SIZE_MATCH(xAppleDRIQueryDirectRenderingCapableReq);
+ rep.type = X_Reply;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+
+ if (!DRIQueryDirectRenderingCapable( screenInfo.screens[stuff->screen],
+ &isCapable)) {
+ return BadValue;
+ }
+ rep.isCapable = isCapable;
+
+ if (!LocalClient(client))
+ rep.isCapable = 0;
+
+ WriteToClient(client,
+ sizeof(xAppleDRIQueryDirectRenderingCapableReply), (char *)&rep);
+ return (client->noClientException);
+}
+
+static int
+ProcAppleDRIAuthConnection(
+ register ClientPtr client
+)
+{
+ xAppleDRIAuthConnectionReply rep;
+
+ REQUEST(xAppleDRIAuthConnectionReq);
+ REQUEST_SIZE_MATCH(xAppleDRIAuthConnectionReq);
+
+ rep.type = X_Reply;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+ rep.authenticated = 1;
+
+ if (!DRIAuthConnection( screenInfo.screens[stuff->screen], stuff->magic)) {
+ ErrorF("Failed to authenticate %u\n", stuff->magic);
+ rep.authenticated = 0;
+ }
+ WriteToClient(client, sizeof(xAppleDRIAuthConnectionReply), (char *)&rep);
+ return (client->noClientException);
+}
+
+static void surface_notify (void *_arg, void *data)
+{
+ DRISurfaceNotifyArg *arg = _arg;
+ int client_index = (int) data;
+ ClientPtr client;
+ xAppleDRINotifyEvent se;
+
+ if (client_index < 0 || client_index >= currentMaxClients)
+ return;
+
+ client = clients[client_index];
+ if (client == NULL || client == serverClient || client->clientGone)
+ return;
+
+ se.type = DRIEventBase + AppleDRISurfaceNotify;
+ se.kind = arg->kind;
+ se.arg = arg->id;
+ se.sequenceNumber = client->sequence;
+ se.time = currentTime.milliseconds;
+ WriteEventsToClient (client, 1, (xEvent *) &se);
+}
+
+static int
+ProcAppleDRICreateSurface(
+ ClientPtr client
+)
+{
+ xAppleDRICreateSurfaceReply rep;
+ DrawablePtr pDrawable;
+ xp_surface_id sid;
+ unsigned int key[2];
+
+ REQUEST(xAppleDRICreateSurfaceReq);
+ REQUEST_SIZE_MATCH(xAppleDRICreateSurfaceReq);
+ rep.type = X_Reply;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+
+ if (!(pDrawable = (DrawablePtr)SecurityLookupDrawable(
+ (Drawable)stuff->drawable,
+ client,
+ SecurityReadAccess))) {
+ return BadValue;
+ }
+
+ rep.key_0 = rep.key_1 = rep.uid = 0;
+
+ if (!DRICreateSurface( screenInfo.screens[stuff->screen],
+ (Drawable)stuff->drawable, pDrawable,
+ stuff->client_id, &sid, key,
+ surface_notify, (void *) client->index)) {
+ return BadValue;
+ }
+
+ rep.key_0 = key[0];
+ rep.key_1 = key[1];
+ rep.uid = sid;
+
+ WriteToClient(client, sizeof(xAppleDRICreateSurfaceReply), (char *)&rep);
+ return (client->noClientException);
+}
+
+static int
+ProcAppleDRIDestroySurface(
+ register ClientPtr client
+)
+{
+ REQUEST(xAppleDRIDestroySurfaceReq);
+ DrawablePtr pDrawable;
+ REQUEST_SIZE_MATCH(xAppleDRIDestroySurfaceReq);
+
+ if (!(pDrawable = (DrawablePtr)SecurityLookupDrawable(
+ (Drawable)stuff->drawable,
+ client,
+ SecurityReadAccess))) {
+ return BadValue;
+ }
+
+ if (!DRIDestroySurface( screenInfo.screens[stuff->screen],
+ (Drawable)stuff->drawable,
+ pDrawable, NULL, NULL)) {
+ return BadValue;
+ }
+
+ return (client->noClientException);
+}
+
+\f
+/* dispatch */
+
+static int
+ProcAppleDRIDispatch (
+ register ClientPtr client
+)
+{
+ REQUEST(xReq);
+
+ switch (stuff->data)
+ {
+ case X_AppleDRIQueryVersion:
+ return ProcAppleDRIQueryVersion(client);
+ case X_AppleDRIQueryDirectRenderingCapable:
+ return ProcAppleDRIQueryDirectRenderingCapable(client);
+ }
+
+ if (!LocalClient(client))
+ return DRIErrorBase + AppleDRIClientNotLocal;
+
+ switch (stuff->data)
+ {
+ case X_AppleDRIAuthConnection:
+ return ProcAppleDRIAuthConnection(client);
+ case X_AppleDRICreateSurface:
+ return ProcAppleDRICreateSurface(client);
+ case X_AppleDRIDestroySurface:
+ return ProcAppleDRIDestroySurface(client);
+ default:
+ return BadRequest;
+ }
+}
+
+static void
+SNotifyEvent(from, to)
+ xAppleDRINotifyEvent *from, *to;
+{
+ to->type = from->type;
+ to->kind = from->kind;
+ cpswaps (from->sequenceNumber, to->sequenceNumber);
+ cpswapl (from->time, to->time);
+ cpswapl (from->arg, to->arg);
+}
+
+static int
+SProcAppleDRIQueryVersion(
+ register ClientPtr client
+)
+{
+ register int n;
+ REQUEST(xAppleDRIQueryVersionReq);
+ swaps(&stuff->length, n);
+ return ProcAppleDRIQueryVersion(client);
+}
+
+static int
+SProcAppleDRIDispatch (
+ register ClientPtr client
+)
+{
+ REQUEST(xReq);
+
+ /* It is bound to be non-local when there is byte swapping */
+ if (!LocalClient(client))
+ return DRIErrorBase + AppleDRIClientNotLocal;
+
+ /* only local clients are allowed DRI access */
+ switch (stuff->data)
+ {
+ case X_AppleDRIQueryVersion:
+ return SProcAppleDRIQueryVersion(client);
+ default:
+ return BadRequest;
+ }
+}
--- /dev/null
+/* $XFree86: xc/programs/Xserver/GL/dri/xf86dri.c,v 1.10 2000/12/07 20:26:14 dawes Exp $ */
+/**************************************************************************
+
+Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
+Copyright 2000 VA Linux Systems, Inc.
+Copyright (c) 2002 Apple Computer, Inc.
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS 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.
+
+**************************************************************************/
+
+#define NEED_REPLIES
+#define NEED_EVENTS
+#include "X.h"
+#include "Xproto.h"
+#include "misc.h"
+#include "dixstruct.h"
+#include "extnsionst.h"
+#include "colormapst.h"
+#include "cursorstr.h"
+#include "scrnintstr.h"
+#include "servermd.h"
+#define _APPLEWM_SERVER_
+#include "applewmstr.h"
+#include "swaprep.h"
+#include "rootless-common.h"
+#include "X11Application.h"
+
+static int WMErrorBase;
+
+static DISPATCH_PROC(ProcAppleWMDispatch);
+static DISPATCH_PROC(SProcAppleWMDispatch);
+
+static void AppleWMResetProc(ExtensionEntry* extEntry);
+
+static unsigned char WMReqCode = 0;
+static int WMEventBase = 0;
+
+static RESTYPE ClientType, EventType; /* resource types for event masks */
+static XID eventResource;
+
+/* Currently selected events */
+static unsigned int eventMask = 0;
+
+extern void AppleWMExtensionInit(void);
+
+static int WMFreeClient (pointer data, XID id);
+static int WMFreeEvents (pointer data, XID id);
+static void SNotifyEvent(xAppleWMNotifyEvent *from, xAppleWMNotifyEvent *to);
+
+typedef struct _WMEvent *WMEventPtr;
+typedef struct _WMEvent {
+ WMEventPtr next;
+ ClientPtr client;
+ XID clientResource;
+ unsigned int mask;
+} WMEventRec;
+
+static inline BoxRec
+make_box (int x, int y, int w, int h)
+{
+ BoxRec r;
+ r.x1 = x;
+ r.y1 = y;
+ r.x2 = x + w;
+ r.y2 = y + h;
+ return r;
+}
+
+void
+AppleWMExtensionInit(void)
+{
+ ExtensionEntry* extEntry;
+
+ ClientType = CreateNewResourceType(WMFreeClient);
+ EventType = CreateNewResourceType(WMFreeEvents);
+ eventResource = FakeClientID(0);
+
+ if (ClientType && EventType &&
+ (extEntry = AddExtension(APPLEWMNAME,
+ AppleWMNumberEvents,
+ AppleWMNumberErrors,
+ ProcAppleWMDispatch,
+ SProcAppleWMDispatch,
+ AppleWMResetProc,
+ StandardMinorOpcode))) {
+ WMReqCode = (unsigned char)extEntry->base;
+ WMErrorBase = extEntry->errorBase;
+ WMEventBase = extEntry->eventBase;
+ EventSwapVector[WMEventBase] = (EventSwapPtr) SNotifyEvent;
+ }
+}
+
+/*ARGSUSED*/
+static void
+AppleWMResetProc (
+ ExtensionEntry* extEntry
+)
+{
+}
+
+static int
+ProcAppleWMQueryVersion(
+ register ClientPtr client
+)
+{
+ xAppleWMQueryVersionReply rep;
+ register int n;
+
+ REQUEST_SIZE_MATCH(xAppleWMQueryVersionReq);
+ rep.type = X_Reply;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+ rep.majorVersion = APPLE_WM_MAJOR_VERSION;
+ rep.minorVersion = APPLE_WM_MINOR_VERSION;
+ rep.patchVersion = APPLE_WM_PATCH_VERSION;
+ if (client->swapped) {
+ swaps(&rep.sequenceNumber, n);
+ swapl(&rep.length, n);
+ }
+ WriteToClient(client, sizeof(xAppleWMQueryVersionReply), (char *)&rep);
+ return (client->noClientException);
+}
+
+\f
+/* events */
+
+static inline void
+updateEventMask (WMEventPtr *pHead)
+{
+ WMEventPtr pCur;
+
+ eventMask = 0;
+ for (pCur = *pHead; pCur != NULL; pCur = pCur->next)
+ eventMask |= pCur->mask;
+}
+
+/*ARGSUSED*/
+static int
+WMFreeClient (data, id)
+ pointer data;
+ XID id;
+{
+ WMEventPtr pEvent;
+ WMEventPtr *pHead, pCur, pPrev;
+
+ pEvent = (WMEventPtr) data;
+ pHead = (WMEventPtr *) LookupIDByType(eventResource, EventType);
+ if (pHead) {
+ pPrev = 0;
+ for (pCur = *pHead; pCur && pCur != pEvent; pCur=pCur->next)
+ pPrev = pCur;
+ if (pCur)
+ {
+ if (pPrev)
+ pPrev->next = pEvent->next;
+ else
+ *pHead = pEvent->next;
+ }
+ updateEventMask (pHead);
+ }
+ xfree ((pointer) pEvent);
+ return 1;
+}
+
+/*ARGSUSED*/
+static int
+WMFreeEvents (data, id)
+ pointer data;
+ XID id;
+{
+ WMEventPtr *pHead, pCur, pNext;
+
+ pHead = (WMEventPtr *) data;
+ for (pCur = *pHead; pCur; pCur = pNext) {
+ pNext = pCur->next;
+ FreeResource (pCur->clientResource, ClientType);
+ xfree ((pointer) pCur);
+ }
+ xfree ((pointer) pHead);
+ eventMask = 0;
+ return 1;
+}
+
+static int
+ProcAppleWMSelectInput (client)
+ register ClientPtr client;
+{
+ REQUEST(xAppleWMSelectInputReq);
+ WMEventPtr pEvent, pNewEvent, *pHead;
+ XID clientResource;
+
+ REQUEST_SIZE_MATCH (xAppleWMSelectInputReq);
+ pHead = (WMEventPtr *)SecurityLookupIDByType(client,
+ eventResource, EventType, SecurityWriteAccess);
+ if (stuff->mask != 0) {
+ if (pHead) {
+ /* check for existing entry. */
+ for (pEvent = *pHead; pEvent; pEvent = pEvent->next)
+ {
+ if (pEvent->client == client)
+ {
+ pEvent->mask = stuff->mask;
+ updateEventMask (pHead);
+ return Success;
+ }
+ }
+ }
+
+ /* build the entry */
+ pNewEvent = (WMEventPtr) xalloc (sizeof (WMEventRec));
+ if (!pNewEvent)
+ return BadAlloc;
+ pNewEvent->next = 0;
+ pNewEvent->client = client;
+ pNewEvent->mask = stuff->mask;
+ /*
+ * add a resource that will be deleted when
+ * the client goes away
+ */
+ clientResource = FakeClientID (client->index);
+ pNewEvent->clientResource = clientResource;
+ if (!AddResource (clientResource, ClientType, (pointer)pNewEvent))
+ return BadAlloc;
+ /*
+ * create a resource to contain a pointer to the list
+ * of clients selecting input. This must be indirect as
+ * the list may be arbitrarily rearranged which cannot be
+ * done through the resource database.
+ */
+ if (!pHead)
+ {
+ pHead = (WMEventPtr *) xalloc (sizeof (WMEventPtr));
+ if (!pHead ||
+ !AddResource (eventResource, EventType, (pointer)pHead))
+ {
+ FreeResource (clientResource, RT_NONE);
+ return BadAlloc;
+ }
+ *pHead = 0;
+ }
+ pNewEvent->next = *pHead;
+ *pHead = pNewEvent;
+ updateEventMask (pHead);
+ } else if (stuff->mask == 0) {
+ /* delete the interest */
+ if (pHead) {
+ pNewEvent = 0;
+ for (pEvent = *pHead; pEvent; pEvent = pEvent->next) {
+ if (pEvent->client == client)
+ break;
+ pNewEvent = pEvent;
+ }
+ if (pEvent) {
+ FreeResource (pEvent->clientResource, ClientType);
+ if (pNewEvent)
+ pNewEvent->next = pEvent->next;
+ else
+ *pHead = pEvent->next;
+ xfree (pEvent);
+ updateEventMask (pHead);
+ }
+ }
+ } else {
+ client->errorValue = stuff->mask;
+ return BadValue;
+ }
+ return Success;
+}
+
+/*
+ * deliver the event
+ */
+
+void
+AppleWMSendEvent (type, mask, which, arg)
+ int type, which, arg;
+ unsigned int mask;
+{
+ WMEventPtr *pHead, pEvent;
+ ClientPtr client;
+ xAppleWMNotifyEvent se;
+
+ pHead = (WMEventPtr *) LookupIDByType(eventResource, EventType);
+ if (!pHead)
+ return;
+ for (pEvent = *pHead; pEvent; pEvent = pEvent->next) {
+ client = pEvent->client;
+ if ((pEvent->mask & mask) == 0
+ || client == serverClient || client->clientGone)
+ {
+ continue;
+ }
+ se.type = type + WMEventBase;
+ se.kind = which;
+ se.arg = arg;
+ se.sequenceNumber = client->sequence;
+ se.time = currentTime.milliseconds;
+ WriteEventsToClient (client, 1, (xEvent *) &se);
+ }
+}
+
+/* Safe to call from any thread. */
+unsigned int
+AppleWMSelectedEvents (void)
+{
+ return eventMask;
+}
+
+\f
+/* general utility functions */
+
+static int
+ProcAppleWMDisableUpdate(
+ register ClientPtr client
+)
+{
+ REQUEST_SIZE_MATCH(xAppleWMDisableUpdateReq);
+
+ xp_disable_update ();
+
+ return (client->noClientException);
+}
+
+static int
+ProcAppleWMReenableUpdate(
+ register ClientPtr client
+)
+{
+ REQUEST_SIZE_MATCH(xAppleWMReenableUpdateReq);
+
+ xp_reenable_update ();
+
+ return (client->noClientException);
+}
+
+\f
+/* window functions */
+
+static int
+ProcAppleWMSetWindowMenu(
+ register ClientPtr client
+)
+{
+ const char *bytes, **items;
+ char *shortcuts;
+ int max_len, nitems, i, j;
+ REQUEST(xAppleWMSetWindowMenuReq);
+
+ REQUEST_AT_LEAST_SIZE(xAppleWMSetWindowMenuReq);
+
+ nitems = stuff->nitems;
+ items = alloca (sizeof (char *) * nitems);
+ shortcuts = alloca (sizeof (char) * nitems);
+
+ max_len = (stuff->length << 2) - sizeof(xAppleWMSetWindowMenuReq);
+ bytes = (char *) &stuff[1];
+
+ for (i = j = 0; i < max_len && j < nitems;)
+ {
+ shortcuts[j] = bytes[i++];
+ items[j++] = bytes + i;
+
+ while (i < max_len)
+ {
+ if (bytes[i++] == 0)
+ break;
+ }
+ }
+
+ X11ApplicationSetWindowMenu (nitems, items, shortcuts);
+
+ return (client->noClientException);
+}
+
+static int
+ProcAppleWMSetWindowMenuCheck(
+ register ClientPtr client
+)
+{
+ REQUEST(xAppleWMSetWindowMenuCheckReq);
+
+ REQUEST_SIZE_MATCH(xAppleWMSetWindowMenuCheckReq);
+
+ X11ApplicationSetWindowMenuCheck (stuff->index);
+
+ return (client->noClientException);
+}
+
+static int
+ProcAppleWMSetFrontProcess(
+ register ClientPtr client
+)
+{
+ REQUEST_SIZE_MATCH(xAppleWMSetFrontProcessReq);
+
+ X11ApplicationSetFrontProcess ();
+
+ return (client->noClientException);
+}
+
+static int
+ProcAppleWMSetWindowLevel(
+ register ClientPtr client
+)
+{
+ REQUEST(xAppleWMSetWindowLevelReq);
+ WindowPtr pWin;
+
+ REQUEST_SIZE_MATCH(xAppleWMSetWindowLevelReq);
+
+ if (!(pWin = SecurityLookupWindow((Drawable)stuff->window,
+ client, SecurityReadAccess))) {
+ return BadValue;
+ }
+
+ if (stuff->level < 0 || stuff->level >= AppleWMNumWindowLevels) {
+ return BadValue;
+ }
+
+ RootlessSetWindowLevel (pWin, stuff->level);
+
+ return (client->noClientException);
+}
+
+static int
+ProcAppleWMSetCanQuit(
+ register ClientPtr client
+)
+{
+ REQUEST(xAppleWMSetCanQuitReq);
+
+ REQUEST_SIZE_MATCH(xAppleWMSetCanQuitReq);
+
+ X11ApplicationSetCanQuit (stuff->state);
+
+ return (client->noClientException);
+}
+
+\f
+/* frame functions */
+
+static int
+ProcAppleWMFrameGetRect(
+ register ClientPtr client
+)
+{
+ xAppleWMFrameGetRectReply rep;
+ BoxRec ir, or, rr;
+ REQUEST(xAppleWMFrameGetRectReq);
+
+ REQUEST_SIZE_MATCH(xAppleWMFrameGetRectReq);
+ rep.type = X_Reply;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+
+ ir = make_box (stuff->ix, stuff->iy, stuff->iw, stuff->ih);
+ or = make_box (stuff->ox, stuff->oy, stuff->ow, stuff->oh);
+
+ if (xp_frame_get_rect (stuff->frame_rect,
+ stuff->frame_class,
+ &or, &ir, &rr) != Success) {
+ return BadValue;
+ }
+
+ rep.x = rr.x1;
+ rep.y = rr.y1;
+ rep.w = rr.x2 - rr.x1;
+ rep.h = rr.y2 - rr.y1;
+
+ WriteToClient(client, sizeof(xAppleWMFrameGetRectReply), (char *)&rep);
+ return (client->noClientException);
+}
+
+static int
+ProcAppleWMFrameHitTest(
+ register ClientPtr client
+)
+{
+ xAppleWMFrameHitTestReply rep;
+ BoxRec ir, or;
+ int ret;
+ REQUEST(xAppleWMFrameHitTestReq);
+
+ REQUEST_SIZE_MATCH(xAppleWMFrameHitTestReq);
+ rep.type = X_Reply;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+
+ ir = make_box (stuff->ix, stuff->iy, stuff->iw, stuff->ih);
+ or = make_box (stuff->ox, stuff->oy, stuff->ow, stuff->oh);
+
+ if (xp_frame_hit_test (stuff->frame_class, stuff->px,
+ stuff->py, &or, &ir, &ret) != Success)
+ {
+ return BadValue;
+ }
+
+ rep.ret = ret;
+
+ WriteToClient(client, sizeof(xAppleWMFrameHitTestReply), (char *)&rep);
+ return (client->noClientException);
+}
+
+static int
+ProcAppleWMFrameDraw(
+ register ClientPtr client
+)
+{
+ BoxRec ir, or;
+ unsigned int title_length, title_max;
+ unsigned char *title_bytes;
+ REQUEST(xAppleWMFrameDrawReq);
+ WindowPtr pWin;
+ xp_window_id wid;
+
+ REQUEST_AT_LEAST_SIZE(xAppleWMFrameDrawReq);
+
+ if (!(pWin = SecurityLookupWindow((Drawable)stuff->window,
+ client, SecurityReadAccess))) {
+ return BadValue;
+ }
+
+ ir = make_box (stuff->ix, stuff->iy, stuff->iw, stuff->ih);
+ or = make_box (stuff->ox, stuff->oy, stuff->ow, stuff->oh);
+
+ title_length = stuff->title_length;
+ title_max = (stuff->length << 2) - sizeof(xAppleWMFrameDrawReq);
+
+ if (title_max < title_length)
+ return BadValue;
+
+ title_bytes = (unsigned char *) &stuff[1];
+
+ wid = RootlessGetPhysicalWindow (pWin, FALSE);
+ if (wid == 0)
+ return BadWindow;
+
+ if (xp_frame_draw (wid, stuff->frame_class,
+ stuff->frame_attr, &or, &ir,
+ title_length, title_bytes) != Success) {
+ return BadValue;
+ }
+
+ return (client->noClientException);
+}
+
+\f
+/* dispatch */
+
+static int
+ProcAppleWMDispatch (
+ register ClientPtr client
+)
+{
+ REQUEST(xReq);
+
+ switch (stuff->data)
+ {
+ case X_AppleWMQueryVersion:
+ return ProcAppleWMQueryVersion(client);
+ }
+
+ if (!LocalClient(client))
+ return WMErrorBase + AppleWMClientNotLocal;
+
+ switch (stuff->data)
+ {
+ case X_AppleWMSelectInput:
+ return ProcAppleWMSelectInput(client);
+ case X_AppleWMDisableUpdate:
+ return ProcAppleWMDisableUpdate(client);
+ case X_AppleWMReenableUpdate:
+ return ProcAppleWMReenableUpdate(client);
+ case X_AppleWMSetWindowMenu:
+ return ProcAppleWMSetWindowMenu(client);
+ case X_AppleWMSetWindowMenuCheck:
+ return ProcAppleWMSetWindowMenuCheck(client);
+ case X_AppleWMSetFrontProcess:
+ return ProcAppleWMSetFrontProcess(client);
+ case X_AppleWMSetWindowLevel:
+ return ProcAppleWMSetWindowLevel(client);
+ case X_AppleWMSetCanQuit:
+ return ProcAppleWMSetCanQuit(client);
+ case X_AppleWMFrameGetRect:
+ return ProcAppleWMFrameGetRect(client);
+ case X_AppleWMFrameHitTest:
+ return ProcAppleWMFrameHitTest(client);
+ case X_AppleWMFrameDraw:
+ return ProcAppleWMFrameDraw(client);
+ default:
+ return BadRequest;
+ }
+}
+
+static void
+SNotifyEvent(from, to)
+ xAppleWMNotifyEvent *from, *to;
+{
+ to->type = from->type;
+ to->kind = from->kind;
+ cpswaps (from->sequenceNumber, to->sequenceNumber);
+ cpswapl (from->time, to->time);
+ cpswapl (from->arg, to->arg);
+}
+
+static int
+SProcAppleWMQueryVersion(
+ register ClientPtr client
+)
+{
+ register int n;
+ REQUEST(xAppleWMQueryVersionReq);
+ swaps(&stuff->length, n);
+ return ProcAppleWMQueryVersion(client);
+}
+
+static int
+SProcAppleWMDispatch (
+ register ClientPtr client
+)
+{
+ REQUEST(xReq);
+
+ /* It is bound to be non-local when there is byte swapping */
+ if (!LocalClient(client))
+ return WMErrorBase + AppleWMClientNotLocal;
+
+ /* only local clients are allowed WM access */
+ switch (stuff->data)
+ {
+ case X_AppleWMQueryVersion:
+ return SProcAppleWMQueryVersion(client);
+ default:
+ return BadRequest;
+ }
+}
--- /dev/null
+/* $XFree86: xc/lib/GL/dri/XF86dri.c,v 1.12 2001/08/27 17:40:57 dawes Exp $ */
+/**************************************************************************
+
+Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
+Copyright 2000 VA Linux Systems, Inc.
+Copyright (c) 2002 Apple Computer, Inc.
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS 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.
+
+**************************************************************************/
+
+/* THIS IS NOT AN X CONSORTIUM STANDARD */
+
+#define NEED_EVENTS
+#define NEED_REPLIES
+#include <X11/Xlibint.h>
+#include "applewmstr.h"
+#include <X11/extensions/Xext.h>
+#include "extutil.h"
+#include <stdio.h>
+
+static XExtensionInfo _applewm_info_data;
+static XExtensionInfo *applewm_info = &_applewm_info_data;
+static char *applewm_extension_name = APPLEWMNAME;
+
+#define AppleWMCheckExtension(dpy,i,val) \
+ XextCheckExtension (dpy, i, applewm_extension_name, val)
+
+/*****************************************************************************
+ * *
+ * private utility routines *
+ * *
+ *****************************************************************************/
+
+static int close_display(Display *dpy, XExtCodes *extCodes);
+static Bool wire_to_event();
+static Status event_to_wire();
+
+static /* const */ XExtensionHooks applewm_extension_hooks = {
+ NULL, /* create_gc */
+ NULL, /* copy_gc */
+ NULL, /* flush_gc */
+ NULL, /* free_gc */
+ NULL, /* create_font */
+ NULL, /* free_font */
+ close_display, /* close_display */
+ wire_to_event, /* wire_to_event */
+ event_to_wire, /* event_to_wire */
+ NULL, /* error */
+ NULL, /* error_string */
+};
+
+static XEXT_GENERATE_FIND_DISPLAY (find_display, applewm_info,
+ applewm_extension_name,
+ &applewm_extension_hooks,
+ AppleWMNumberEvents, NULL)
+
+static XEXT_GENERATE_CLOSE_DISPLAY (close_display, applewm_info)
+
+static Bool wire_to_event (dpy, re, event)
+ Display *dpy;
+ XEvent *re;
+ xEvent *event;
+{
+ XExtDisplayInfo *info = find_display (dpy);
+ XAppleWMNotifyEvent *se;
+ xAppleWMNotifyEvent *sevent;
+
+ AppleWMCheckExtension (dpy, info, False);
+
+ switch ((event->u.u.type & 0x7f) - info->codes->first_event) {
+ case AppleWMControllerNotify:
+ case AppleWMActivationNotify:
+ case AppleWMPasteboardNotify:
+ se = (XAppleWMNotifyEvent *) re;
+ sevent = (xAppleWMNotifyEvent *) event;
+ se->type = sevent->type & 0x7f;
+ se->serial = _XSetLastRequestRead(dpy,(xGenericReply *) event);
+ se->send_event = (sevent->type & 0x80) != 0;
+ se->display = dpy;
+ se->window = 0;
+ se->time = sevent->time;
+ se->kind = sevent->kind;
+ se->arg = sevent->arg;
+ return True;
+ }
+ return False;
+}
+
+static Status event_to_wire (dpy, re, event)
+ Display *dpy;
+ XEvent *re;
+ xEvent *event;
+{
+ XExtDisplayInfo *info = find_display (dpy);
+ XAppleWMNotifyEvent *se;
+ xAppleWMNotifyEvent *sevent;
+
+ AppleWMCheckExtension (dpy, info, False);
+
+ switch ((re->type & 0x7f) - info->codes->first_event) {
+ case AppleWMControllerNotify:
+ case AppleWMActivationNotify:
+ case AppleWMPasteboardNotify:
+ se = (XAppleWMNotifyEvent *) re;
+ sevent = (xAppleWMNotifyEvent *) event;
+ sevent->type = se->type | (se->send_event ? 0x80 : 0);
+ sevent->sequenceNumber = se->serial & 0xffff;
+ sevent->kind = se->kind;
+ sevent->arg = se->arg;
+ sevent->time = se->time;
+ return 1;
+ }
+ return 0;
+}
+
+/*****************************************************************************
+ * *
+ * public Apple-WM Extension routines *
+ * *
+ *****************************************************************************/
+
+#if 0
+#include <stdio.h>
+#define TRACE(msg) fprintf(stderr, "AppleWM%s\n", msg);
+#else
+#define TRACE(msg)
+#endif
+
+
+Bool XAppleWMQueryExtension (dpy, event_basep, error_basep)
+ Display *dpy;
+ int *event_basep, *error_basep;
+{
+ XExtDisplayInfo *info = find_display (dpy);
+
+ TRACE("QueryExtension...");
+ if (XextHasExtension(info)) {
+ *event_basep = info->codes->first_event;
+ *error_basep = info->codes->first_error;
+ TRACE("QueryExtension... return True");
+ return True;
+ } else {
+ TRACE("QueryExtension... return False");
+ return False;
+ }
+}
+
+Bool XAppleWMQueryVersion(dpy, majorVersion, minorVersion, patchVersion)
+ Display* dpy;
+ int* majorVersion;
+ int* minorVersion;
+ int* patchVersion;
+{
+ XExtDisplayInfo *info = find_display (dpy);
+ xAppleWMQueryVersionReply rep;
+ xAppleWMQueryVersionReq *req;
+
+ TRACE("QueryVersion...");
+ AppleWMCheckExtension (dpy, info, False);
+
+ LockDisplay(dpy);
+ GetReq(AppleWMQueryVersion, req);
+ req->reqType = info->codes->major_opcode;
+ req->wmReqType = X_AppleWMQueryVersion;
+ if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("QueryVersion... return False");
+ return False;
+ }
+ *majorVersion = rep.majorVersion;
+ *minorVersion = rep.minorVersion;
+ *patchVersion = rep.patchVersion;
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("QueryVersion... return True");
+ return True;
+}
+
+Bool XAppleWMDisableUpdate(dpy, screen)
+ Display* dpy;
+ int screen;
+{
+ XExtDisplayInfo *info = find_display (dpy);
+ xAppleWMDisableUpdateReq *req;
+
+ TRACE("DisableUpdate...");
+ AppleWMCheckExtension (dpy, info, False);
+
+ LockDisplay(dpy);
+ GetReq(AppleWMDisableUpdate, req);
+ req->reqType = info->codes->major_opcode;
+ req->wmReqType = X_AppleWMDisableUpdate;
+ req->screen = screen;
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("DisableUpdate... return True");
+ return True;
+}
+
+Bool XAppleWMReenableUpdate(dpy, screen)
+ Display* dpy;
+ int screen;
+{
+ XExtDisplayInfo *info = find_display (dpy);
+ xAppleWMReenableUpdateReq *req;
+
+ TRACE("ReenableUpdate...");
+ AppleWMCheckExtension (dpy, info, False);
+
+ LockDisplay(dpy);
+ GetReq(AppleWMReenableUpdate, req);
+ req->reqType = info->codes->major_opcode;
+ req->wmReqType = X_AppleWMReenableUpdate;
+ req->screen = screen;
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("ReenableUpdate... return True");
+ return True;
+}
+
+Bool XAppleWMSelectInput(dpy, mask)
+ Display* dpy;
+ unsigned long mask;
+{
+ XExtDisplayInfo *info = find_display (dpy);
+ xAppleWMSelectInputReq *req;
+
+ TRACE("SelectInput...");
+ AppleWMCheckExtension (dpy, info, False);
+
+ LockDisplay(dpy);
+ GetReq(AppleWMSelectInput, req);
+ req->reqType = info->codes->major_opcode;
+ req->wmReqType = X_AppleWMSelectInput;
+ req->mask = mask;
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("SetlectInput... return True");
+ return True;
+}
+
+Bool XAppleWMSetWindowMenuWithShortcuts(dpy, nitems, items, shortcuts)
+ Display* dpy;
+ int nitems;
+ const char **items;
+ const char *shortcuts;
+{
+ XExtDisplayInfo *info = find_display (dpy);
+ xAppleWMSetWindowMenuReq *req;
+ int i, total_length, len;
+ char *buf, *ptr;
+
+ TRACE("SetWindowMenu...");
+ AppleWMCheckExtension (dpy, info, False);
+
+ LockDisplay(dpy);
+ GetReq(AppleWMSetWindowMenu, req);
+ req->reqType = info->codes->major_opcode;
+ req->wmReqType = X_AppleWMSetWindowMenu;
+ req->nitems = nitems;
+
+ total_length = 0;
+ for (i = 0; i < nitems; i++)
+ total_length += strlen (items[i]) + 2;
+
+ ptr = buf = alloca (total_length);
+ for (i = 0; i < nitems; i++)
+ {
+ len = strlen (items[i]);
+ *ptr++ = shortcuts ? shortcuts[i] : 0;
+ memcpy (ptr, items[i], len);
+ ptr[len] = 0;
+ ptr += len + 1;
+ }
+
+ req->length += (total_length + 3) >> 2;
+ Data (dpy, buf, total_length);
+
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("SetlectInput... return True");
+ return True;
+}
+
+Bool XAppleWMSetWindowMenu(dpy, nitems, items)
+ Display* dpy;
+ int nitems;
+ const char **items;
+{
+ return XAppleWMSetWindowMenuWithShortcuts (dpy, nitems, items, NULL);
+}
+
+Bool XAppleWMSetWindowMenuCheck(dpy, idx)
+ Display* dpy;
+ int idx;
+{
+ XExtDisplayInfo *info = find_display (dpy);
+ xAppleWMSetWindowMenuCheckReq *req;
+
+ TRACE("SetWindowMenuCheck...");
+ AppleWMCheckExtension (dpy, info, False);
+
+ LockDisplay(dpy);
+ GetReq(AppleWMSetWindowMenuCheck, req);
+ req->reqType = info->codes->major_opcode;
+ req->wmReqType = X_AppleWMSetWindowMenuCheck;
+ req->index = idx;
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("SetWindowMenuCheck... return True");
+ return True;
+}
+
+Bool XAppleWMSetFrontProcess(dpy)
+ Display* dpy;
+{
+ XExtDisplayInfo *info = find_display (dpy);
+ xAppleWMSetFrontProcessReq *req;
+
+ TRACE("SetFrontProcess...");
+ AppleWMCheckExtension (dpy, info, False);
+
+ LockDisplay(dpy);
+ GetReq(AppleWMSetFrontProcess, req);
+ req->reqType = info->codes->major_opcode;
+ req->wmReqType = X_AppleWMSetFrontProcess;
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("SetFrontProcess... return True");
+ return True;
+}
+
+Bool XAppleWMSetWindowLevel(dpy, id, level)
+ Display* dpy;
+ Window id;
+ int level;
+{
+ XExtDisplayInfo *info = find_display (dpy);
+ xAppleWMSetWindowLevelReq *req;
+
+ TRACE("SetWindowLevel...");
+ AppleWMCheckExtension (dpy, info, False);
+
+ LockDisplay(dpy);
+ GetReq(AppleWMSetWindowLevel, req);
+ req->reqType = info->codes->major_opcode;
+ req->wmReqType = X_AppleWMSetWindowLevel;
+ req->window = id;
+ req->level = level;
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("SetWindowLevel... return True");
+ return True;
+}
+
+Bool XAppleWMSetCanQuit(dpy, state)
+ Display* dpy;
+ Bool state;
+{
+ XExtDisplayInfo *info = find_display (dpy);
+ xAppleWMSetCanQuitReq *req;
+
+ TRACE("SetCanQuit...");
+ AppleWMCheckExtension (dpy, info, False);
+
+ LockDisplay(dpy);
+ GetReq(AppleWMSetCanQuit, req);
+ req->reqType = info->codes->major_opcode;
+ req->wmReqType = X_AppleWMSetCanQuit;
+ req->state = state;
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("SetCanQuit... return True");
+ return True;
+}
+
+Bool XAppleWMFrameGetRect(dpy, frame_class, frame_rect,
+ ix, iy, iw, ih, ox, oy, ow, oh, rx, ry, rw, rh)
+ Display* dpy;
+ unsigned int frame_class, frame_rect;
+ short ix, iy, iw, ih;
+ short ox, oy, ow, oh;
+ short *rx, *ry, *rw, *rh;
+{
+ XExtDisplayInfo *info = find_display (dpy);
+ xAppleWMFrameGetRectReply rep;
+ xAppleWMFrameGetRectReq *req;
+
+ TRACE("FrameGetRect...");
+ AppleWMCheckExtension (dpy, info, False);
+
+ LockDisplay(dpy);
+ GetReq(AppleWMFrameGetRect, req);
+ req->reqType = info->codes->major_opcode;
+ req->wmReqType = X_AppleWMFrameGetRect;
+ req->frame_class = frame_class;
+ req->frame_rect = frame_rect;
+ req->ix = ix;
+ req->iy = iy;
+ req->iw = iw;
+ req->ih = ih;
+ req->ox = ox;
+ req->oy = oy;
+ req->ow = ow;
+ req->oh = oh;
+ rep.x = rep.y = rep.w = rep.h = 0;
+ if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("FrameGetRect... return False");
+ return False;
+ }
+ *rx = rep.x; *ry = rep.y;
+ *rw = rep.w; *rh = rep.h;
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("FrameGetRect... return True");
+ return True;
+}
+
+unsigned int XAppleWMFrameHitTest(dpy, frame_class, px, py,
+ ix, iy, iw, ih, ox, oy, ow, oh)
+ Display* dpy;
+ unsigned int frame_class;
+ short px, py;
+ short ix, iy, iw, ih;
+ short ox, oy, ow, oh;
+{
+ XExtDisplayInfo *info = find_display (dpy);
+ xAppleWMFrameHitTestReply rep;
+ xAppleWMFrameHitTestReq *req;
+
+ TRACE("FrameHitTest...");
+ AppleWMCheckExtension (dpy, info, False);
+
+ LockDisplay(dpy);
+ GetReq(AppleWMFrameHitTest, req);
+ req->reqType = info->codes->major_opcode;
+ req->wmReqType = X_AppleWMFrameHitTest;
+ req->frame_class = frame_class;
+ req->px = px;
+ req->py = py;
+ req->ix = ix;
+ req->iy = iy;
+ req->iw = iw;
+ req->ih = ih;
+ req->ox = ox;
+ req->oy = oy;
+ req->ow = ow;
+ req->oh = oh;
+ rep.ret = 0;
+ if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("FrameHitTest... return False");
+ return False;
+ }
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("FrameHiTest... return True");
+ return rep.ret;
+}
+
+Bool XAppleWMFrameDraw(dpy, screen, window,
+ frame_class, frame_attr,
+ ix, iy, iw, ih, ox, oy, ow, oh,
+ title_length, title_bytes)
+ Display* dpy;
+ int screen;
+ Window window;
+ unsigned int frame_class, frame_attr;
+ short ix, iy, iw, ih;
+ short ox, oy, ow, oh;
+ unsigned int title_length;
+ const unsigned char *title_bytes;
+{
+ XExtDisplayInfo *info = find_display (dpy);
+ xAppleWMFrameDrawReq *req;
+
+ TRACE("FrameDraw...");
+ AppleWMCheckExtension (dpy, info, False);
+
+ LockDisplay(dpy);
+ GetReq(AppleWMFrameDraw, req);
+ req->reqType = info->codes->major_opcode;
+ req->wmReqType = X_AppleWMFrameDraw;
+ req->screen = screen;
+ req->window = window;
+ req->frame_class = frame_class;
+ req->frame_attr = frame_attr;
+ req->ix = ix;
+ req->iy = iy;
+ req->iw = iw;
+ req->ih = ih;
+ req->ox = ox;
+ req->oy = oy;
+ req->ow = ow;
+ req->oh = oh;
+ req->title_length = title_length;
+
+ req->length += (title_length + 3)>>2;
+ Data (dpy, title_bytes, title_length);
+
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("FrameDraw... return True");
+ return True;
+}
--- /dev/null
+/* $XFree86: xc/lib/GL/dri/xf86dri.h,v 1.7 2000/12/07 20:26:02 dawes Exp $ */
+/**************************************************************************
+
+Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
+Copyright 2000 VA Linux Systems, Inc.
+Copyright (c) 2002 Apple Computer, Inc.
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+#ifndef _APPLEWM_H_
+#define _APPLEWM_H_
+
+#include <X11/Xfuncproto.h>
+
+#define X_AppleWMQueryVersion 0
+#define X_AppleWMFrameGetRect 1
+#define X_AppleWMFrameHitTest 2
+#define X_AppleWMFrameDraw 3
+#define X_AppleWMDisableUpdate 4
+#define X_AppleWMReenableUpdate 5
+#define X_AppleWMSelectInput 6
+#define X_AppleWMSetWindowMenuCheck 7
+#define X_AppleWMSetFrontProcess 8
+#define X_AppleWMSetWindowLevel 9
+#define X_AppleWMSetCanQuit 10
+#define X_AppleWMSetWindowMenu 11
+
+/* Events */
+#define AppleWMControllerNotify 0
+#define AppleWMActivationNotify 1
+#define AppleWMPasteboardNotify 2
+#define AppleWMNumberEvents 3
+
+#define AppleWMControllerNotifyMask (1L << 0)
+#define AppleWMActivationNotifyMask (1L << 1)
+#define AppleWMPasteboardNotifyMask (1L << 2)
+
+/* "Kinds" of ControllerNotify events */
+#define AppleWMMinimizeWindow 0
+#define AppleWMZoomWindow 1
+#define AppleWMCloseWindow 2
+#define AppleWMBringAllToFront 3
+#define AppleWMHideWindow 4
+#define AppleWMHideAll 5
+#define AppleWMShowAll 6
+#define AppleWMWindowMenuItem 9
+#define AppleWMWindowMenuNotify 10
+#define AppleWMNextWindow 11
+#define AppleWMPreviousWindow 12
+
+/* "Kinds" of ActivationNotify events */
+#define AppleWMIsActive 0
+#define AppleWMIsInactive 1
+
+/* "Kinds" of PasteboardNotify events */
+#define AppleWMCopyToPasteboard 0
+
+/* Errors */
+#define AppleWMClientNotLocal 0
+#define AppleWMOperationNotSupported 1
+#define AppleWMNumberErrors (AppleWMOperationNotSupported + 1)
+
+/* Window level ids */
+#define AppleWMWindowLevelNormal 0
+#define AppleWMWindowLevelFloating 1
+#define AppleWMWindowLevelTornOff 2
+#define AppleWMWindowLevelDock 3
+#define AppleWMWindowLevelDesktop 4
+#define AppleWMNumWindowLevels 5
+
+#ifndef _APPLEWM_SERVER_
+
+typedef struct {
+ int type; /* of event */
+ unsigned long serial; /* # of last request processed by server */
+ Bool send_event; /* true if this came frome a SendEvent request */
+ Display *display; /* Display the event was read from */
+ Window window; /* window of event */
+ Time time; /* server timestamp when event happened */
+ int kind; /* subtype of event */
+ int arg;
+} XAppleWMNotifyEvent;
+
+_XFUNCPROTOBEGIN
+
+Bool XAppleWMQueryExtension (Display *dpy, int *event_base, int *error_base);
+
+Bool XAppleWMQueryVersion (Display *dpy, int *majorVersion,
+ int *minorVersion, int *patchVersion);
+
+Bool XAppleWMDisableUpdate (Display *dpy, int screen);
+
+Bool XAppleWMReenableUpdate (Display *dpy, int screen);
+
+Bool XAppleWMSelectInput (Display *dpy, unsigned long mask);
+
+Bool XAppleWMSetWindowMenu (Display *dpy, int nitems, const char **items);
+Bool XAppleWMSetWindowMenuWithShortcuts (Display *dpy, int nitems,
+ const char **items,
+ const char *shortcuts);
+
+Bool XAppleWMSetWindowMenuCheck (Display *dpy, int index);
+
+Bool XAppleWMSetFrontProcess (Display *dpy);
+
+Bool XAppleWMSetWindowLevel (Display *dpy, Window id, int level);
+
+Bool XAppleWMSetCanQuit (Display *dpy, Bool state);
+
+Bool XAppleWMFrameGetRect (Display *dpy,
+ unsigned int frame_class, unsigned int frame_rect,
+ short inner_x, short inner_y,
+ short inner_w, short inner_h,
+ short outer_x, short outer_y,
+ short outer_w, short outer_h,
+ short *ret_x, short *ret_y,
+ short *ret_w, short *ret_h);
+
+unsigned int XAppleWMFrameHitTest (Display *dpy,
+ unsigned int frame_class,
+ short point_x, short point_y,
+ short inner_x, short inner_y,
+ short inner_w, short inner_h,
+ short outer_x, short outer_y,
+ short outer_w, short outer_h);
+
+Bool XAppleWMFrameDraw (Display *dpy, int screen, Window window,
+ unsigned int frame_class, unsigned int frame_attr,
+ short inner_x, short inner_y,
+ short inner_w, short inner_h,
+ short outer_x, short outer_y,
+ short outer_w, short outer_h,
+ unsigned int title_length,
+ const unsigned char * title_bytes);
+
+_XFUNCPROTOEND
+
+#endif /* _APPLEWM_SERVER_ */
+#endif /* _APPLEWM_H_ */
--- /dev/null
+/* $XFree86: xc/lib/GL/dri/xf86dristr.h,v 1.9 2001/03/21 16:01:08 dawes Exp $ */
+/**************************************************************************
+
+Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
+Copyright 2000 VA Linux Systems, Inc.
+Copyright (c) 2002 Apple Computer, Inc.
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/*
+ * Authors:
+ * Kevin E. Martin <martin@valinux.com>
+ * Jens Owen <jens@valinux.com>
+ * Rickard E. (Rik) Fiath <faith@valinux.com>
+ *
+ */
+
+#ifndef _APPLEWMSTR_H_
+#define _APPLEWMSTR_H_
+
+#include "applewm.h"
+
+#define APPLEWMNAME "Apple-WM"
+
+#define APPLE_WM_MAJOR_VERSION 1 /* current version numbers */
+#define APPLE_WM_MINOR_VERSION 0
+#define APPLE_WM_PATCH_VERSION 0
+
+typedef struct _AppleWMQueryVersion {
+ CARD8 reqType; /* always WMReqCode */
+ CARD8 wmReqType; /* always X_WMQueryVersion */
+ CARD16 length B16;
+} xAppleWMQueryVersionReq;
+#define sz_xAppleWMQueryVersionReq 4
+
+typedef struct {
+ BYTE type; /* X_Reply */
+ BOOL pad1;
+ CARD16 sequenceNumber B16;
+ CARD32 length B32;
+ CARD16 majorVersion B16; /* major version of WM protocol */
+ CARD16 minorVersion B16; /* minor version of WM protocol */
+ CARD32 patchVersion B32; /* patch version of WM protocol */
+ CARD32 pad3 B32;
+ CARD32 pad4 B32;
+ CARD32 pad5 B32;
+ CARD32 pad6 B32;
+} xAppleWMQueryVersionReply;
+#define sz_xAppleWMQueryVersionReply 32
+
+typedef struct _AppleWMQueryDirectRenderingCapable {
+ CARD8 reqType; /* always WMReqCode */
+ CARD8 wmReqType; /* X_WMQueryDirectRenderingCapable */
+ CARD16 length B16;
+ CARD32 screen B32;
+} xAppleWMQueryDirectRenderingCapableReq;
+#define sz_xAppleWMQueryDirectRenderingCapableReq 8
+
+typedef struct {
+ BYTE type; /* X_Reply */
+ BOOL pad1;
+ CARD16 sequenceNumber B16;
+ CARD32 length B32;
+ BOOL isCapable;
+ BOOL pad2;
+ BOOL pad3;
+ BOOL pad4;
+ CARD32 pad5 B32;
+ CARD32 pad6 B32;
+ CARD32 pad7 B32;
+ CARD32 pad8 B32;
+ CARD32 pad9 B32;
+} xAppleDRIQueryDirectRenderingCapableReply;
+#define sz_xAppleWMQueryDirectRenderingCapableReply 32
+
+typedef struct _AppleWMAuthConnection {
+ CARD8 reqType; /* always WMReqCode */
+ CARD8 wmReqType; /* always X_WMCloseConnection */
+ CARD16 length B16;
+ CARD32 screen B32;
+ CARD32 magic B32;
+} xAppleWMAuthConnectionReq;
+#define sz_xAppleWMAuthConnectionReq 12
+
+typedef struct {
+ BYTE type;
+ BOOL pad1;
+ CARD16 sequenceNumber B16;
+ CARD32 length B32;
+ CARD32 authenticated B32;
+ CARD32 pad2 B32;
+ CARD32 pad3 B32;
+ CARD32 pad4 B32;
+ CARD32 pad5 B32;
+ CARD32 pad6 B32;
+} xAppleWMAuthConnectionReply;
+#define zx_xAppleWMAuthConnectionReply 32
+
+typedef struct _AppleWMCreateSurface {
+ CARD8 reqType; /* always WMReqCode */
+ CARD8 wmReqType; /* always X_WMCreateSurface */
+ CARD16 length B16;
+ CARD32 screen B32;
+ CARD32 drawable B32;
+ CARD32 client_id B32;
+} xAppleWMCreateSurfaceReq;
+#define sz_xAppleWMCreateSurfaceReq 16
+
+typedef struct {
+ BYTE type; /* X_Reply */
+ BOOL pad1;
+ CARD16 sequenceNumber B16;
+ CARD32 length B32;
+ CARD32 key_0 B32;
+ CARD32 key_1 B32;
+ CARD32 uid B32;
+ CARD32 pad4 B32;
+ CARD32 pad5 B32;
+ CARD32 pad6 B32;
+} xAppleWMCreateSurfaceReply;
+#define sz_xAppleWMCreateSurfaceReply 32
+
+typedef struct _AppleWMDestroySurface {
+ CARD8 reqType; /* always WMReqCode */
+ CARD8 wmReqType; /* always X_WMDestroySurface */
+ CARD16 length B16;
+ CARD32 screen B32;
+ CARD32 drawable B32;
+} xAppleWMDestroySurfaceReq;
+#define sz_xAppleWMDestroySurfaceReq 12
+
+typedef struct _AppleWMDisableUpdate {
+ CARD8 reqType; /* always WMReqCode */
+ CARD8 wmReqType; /* always X_WMDisableUpdate */
+ CARD16 length B16;
+ CARD32 screen B32;
+} xAppleWMDisableUpdateReq;
+#define sz_xAppleWMDisableUpdateReq 8
+
+typedef struct _AppleWMReenableUpdate {
+ CARD8 reqType; /* always WMReqCode */
+ CARD8 wmReqType; /* always X_WMReenableUpdate */
+ CARD16 length B16;
+ CARD32 screen B32;
+} xAppleWMReenableUpdateReq;
+#define sz_xAppleWMReenableUpdateReq 8
+
+typedef struct _AppleWMSelectInput {
+ CARD8 reqType; /* always WMReqCode */
+ CARD8 wmReqType; /* always X_WMSelectInput */
+ CARD16 length B16;
+ CARD32 mask B32;
+} xAppleWMSelectInputReq;
+#define sz_xAppleWMSelectInputReq 8
+
+typedef struct _AppleWMNotify {
+ BYTE type; /* always eventBase + event type */
+ BYTE kind;
+ CARD16 sequenceNumber B16;
+ Time time B32; /* time of change */
+ CARD16 pad1 B16;
+ CARD32 arg B32;
+ CARD32 pad3 B32;
+} xAppleWMNotifyEvent;
+#define sz_xAppleWMNotifyEvent 20
+
+typedef struct _AppleWMSetWindowMenu {
+ CARD8 reqType; /* always WMReqCode */
+ CARD8 wmReqType; /* always X_WMSetWindowMenu */
+ CARD16 length B16;
+ CARD16 nitems B16;
+ CARD16 pad1 B16;
+} xAppleWMSetWindowMenuReq;
+#define sz_xAppleWMSetWindowMenuReq 8
+
+typedef struct _AppleWMSetWindowMenuCheck {
+ CARD8 reqType; /* always WMReqCode */
+ CARD8 wmReqType; /* always X_WMSetWindowMenuCheck */
+ CARD16 length B16;
+ CARD32 index;
+} xAppleWMSetWindowMenuCheckReq;
+#define sz_xAppleWMSetWindowMenuCheckReq 8
+
+typedef struct _AppleWMSetFrontProcess {
+ CARD8 reqType; /* always WMReqCode */
+ CARD8 wmReqType; /* always X_WMSetFrontProcess */
+ CARD16 length B16;
+} xAppleWMSetFrontProcessReq;
+#define sz_xAppleWMSetFrontProcessReq 4
+
+typedef struct _AppleWMSetWindowLevel {
+ CARD8 reqType; /* always WMReqCode */
+ CARD8 wmReqType; /* always X_WMSetWindowLevel */
+ CARD16 length B16;
+ CARD32 window;
+ CARD32 level;
+} xAppleWMSetWindowLevelReq;
+#define sz_xAppleWMSetWindowLevelReq 12
+
+typedef struct _AppleWMSetCanQuit {
+ CARD8 reqType; /* always WMReqCode */
+ CARD8 wmReqType; /* always X_WMSetCanQuit */
+ CARD16 length B16;
+ CARD32 state;
+} xAppleWMSetCanQuitReq;
+#define sz_xAppleWMSetCanQuitReq 8
+
+typedef struct _AppleWMFrameGetRect {
+ CARD8 reqType; /* always WMReqCode */
+ CARD8 wmReqType; /* always X_WMFrameGetRect */
+ CARD16 length B16;
+ CARD16 frame_class B16;
+ CARD16 frame_rect B16;
+ CARD16 ix B16;
+ CARD16 iy B16;
+ CARD16 iw B16;
+ CARD16 ih B16;
+ CARD16 ox B16;
+ CARD16 oy B16;
+ CARD16 ow B16;
+ CARD16 oh B16;
+} xAppleWMFrameGetRectReq;
+#define sz_xAppleWMFrameGetRectReq 24
+
+typedef struct {
+ BYTE type; /* X_Reply */
+ BOOL pad1;
+ CARD16 sequenceNumber B16;
+ CARD32 length B32;
+ CARD16 x B16;
+ CARD16 y B16;
+ CARD16 w B16;
+ CARD16 h B16;
+ CARD32 pad3 B32;
+ CARD32 pad4 B32;
+ CARD32 pad5 B32;
+ CARD32 pad6 B32;
+} xAppleWMFrameGetRectReply;
+#define sz_xAppleWMFrameGetRectReply 32
+
+typedef struct _AppleWMFrameHitTest {
+ CARD8 reqType; /* always WMReqCode */
+ CARD8 wmReqType; /* always X_WMFrameHitTest */
+ CARD16 length B16;
+ CARD16 frame_class B16;
+ CARD16 pad1 B16;
+ CARD16 px B16;
+ CARD16 py B16;
+ CARD16 ix B16;
+ CARD16 iy B16;
+ CARD16 iw B16;
+ CARD16 ih B16;
+ CARD16 ox B16;
+ CARD16 oy B16;
+ CARD16 ow B16;
+ CARD16 oh B16;
+} xAppleWMFrameHitTestReq;
+#define sz_xAppleWMFrameHitTestReq 28
+
+typedef struct {
+ BYTE type; /* X_Reply */
+ BOOL pad1;
+ CARD16 sequenceNumber B16;
+ CARD32 length B32;
+ CARD32 ret B32;
+ CARD32 pad2 B32;
+ CARD32 pad3 B32;
+ CARD32 pad4 B32;
+ CARD32 pad5 B32;
+ CARD32 pad6 B32;
+} xAppleWMFrameHitTestReply;
+#define sz_xAppleWMFrameHitTestReply 32
+
+typedef struct _AppleWMFrameDraw {
+ CARD8 reqType; /* always WMReqCode */
+ CARD8 wmReqType; /* always X_WMFrameDraw */
+ CARD16 length B16;
+ CARD32 screen B32;
+ CARD32 window B32;
+ CARD16 frame_class B16;
+ CARD16 frame_attr B16;
+ CARD16 ix B16;
+ CARD16 iy B16;
+ CARD16 iw B16;
+ CARD16 ih B16;
+ CARD16 ox B16;
+ CARD16 oy B16;
+ CARD16 ow B16;
+ CARD16 oh B16;
+ CARD32 title_length B32;
+} xAppleWMFrameDrawReq;
+#define sz_xAppleWMFrameDrawReq 36
+
+#ifdef _APPLEWM_SERVER_
+
+void AppleWMSendEvent (
+#if NeedFunctionPrototypes
+ int /* type */,
+ unsigned int /* mask */,
+ int /* which */,
+ int /* arg */
+#endif
+);
+
+unsigned int AppleWMSelectedEvents (
+#if NeedFunctionPrototypes
+ void
+#endif
+);
+
+#endif /* _APPLEWM_SERVER_ */
+#endif /* _APPLEWMSTR_H_ */
--- /dev/null
+/* bundle-main.c -- X server launcher
+ $Id: bundle-main.c,v 1.17 2003/09/11 00:17:10 jharper Exp $
+
+ Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
+
+ Permission is hereby granted, free of charge, to any person
+ obtaining a copy of this software and associated documentation files
+ (the "Software"), to deal in the Software without restriction,
+ including without limitation the rights to use, copy, modify, merge,
+ publish, distribute, sublicense, and/or sell copies of the Software,
+ and to permit persons to whom the Software is furnished to do so,
+ subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT
+ HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ DEALINGS IN THE SOFTWARE.
+
+ Except as contained in this notice, the name(s) of the above
+ copyright holders shall not be used in advertising or otherwise to
+ promote the sale, use or other dealings in this Software without
+ prior written authorization.
+
+ Parts of this file are derived from xdm, which has this copyright:
+
+ Copyright 1988, 1998 The Open Group
+
+ Permission to use, copy, modify, distribute, and sell this software
+ and its documentation for any purpose is hereby granted without fee,
+ provided that the above copyright notice appear in all copies and
+ that both that copyright notice and this permission notice appear in
+ supporting documentation.
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ Except as contained in this notice, the name of The Open Group shall
+ not be used in advertising or otherwise to promote the sale, use or
+ other dealings in this Software without prior written authorization
+ from The Open Group. */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/socket.h>
+#include <sys/utsname.h>
+#include <ifaddrs.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <time.h>
+#include <sys/wait.h>
+#include <setjmp.h>
+#include <sys/ioctl.h>
+
+#include <X11/Xlib.h>
+#include <X11/Xauth.h>
+
+#include <CoreFoundation/CoreFoundation.h>
+#include <SystemConfiguration/SystemConfiguration.h>
+
+#define X_SERVER "/usr/X11R6/bin/Xquartz"
+#define XTERM_PATH "/usr/X11R6/bin/xterm"
+#define WM_PATH "/usr/X11R6/bin/quartz-wm"
+#define DEFAULT_XINITRC "/usr/X11R6/lib/X11/xinit/xinitrc"
+#include <mach-o/dyld.h>
+
+/* what xinit does */
+#ifndef SHELL
+# define SHELL "sh"
+#endif
+
+#undef FALSE
+#define FALSE 0
+#undef TRUE
+#define TRUE 1
+
+#define MAX_DISPLAYS 64
+
+static int server_pid = -1, client_pid = -1;
+static int xinit_kills_server = FALSE;
+static jmp_buf exit_continuation;
+static const char *server_name = NULL;
+static Display *server_dpy;
+
+static char *auth_file;
+
+typedef struct addr_list_struct addr_list;
+
+struct addr_list_struct {
+ addr_list *next;
+ Xauth auth;
+};
+
+static addr_list *addresses;
+
+\f
+/* Utility functions. */
+
+/* Return the current host name. Matches what Xlib does. */
+static char *
+host_name (void)
+{
+#ifdef NEED_UTSNAME
+ static struct utsname name;
+
+ uname(&name);
+
+ return name.nodename;
+#else
+ static char buf[100];
+
+ gethostname(buf, sizeof(buf));
+
+ return buf;
+#endif
+}
+
+static int
+read_boolean_pref (CFStringRef name, int default_)
+{
+ int value;
+ Boolean ok;
+
+ value = CFPreferencesGetAppBooleanValue (name,
+ CFSTR ("com.apple.x11"), &ok);
+ return ok ? value : default_;
+}
+
+static inline int
+binary_equal (const void *a, const void *b, int length)
+{
+ return memcmp (a, b, length) == 0;
+}
+
+static inline void *
+binary_dup (const void *a, int length)
+{
+ void *b = malloc (length);
+ if (b != NULL)
+ memcpy (b, a, length);
+ return b;
+}
+
+static inline void
+binary_free (void *data, int length)
+{
+ if (data != NULL)
+ free (data);
+}
+
+\f
+/* Functions for managing the authentication entries. */
+
+/* Returns true if something matching AUTH is in our list of auth items */
+static int
+check_auth_item (Xauth *auth)
+{
+ addr_list *a;
+
+ for (a = addresses; a != NULL; a = a->next)
+ {
+ if (a->auth.family == auth->family
+ && a->auth.address_length == auth->address_length
+ && binary_equal (a->auth.address, auth->address, auth->address_length)
+ && a->auth.number_length == auth->number_length
+ && binary_equal (a->auth.number, auth->number, auth->number_length)
+ && a->auth.name_length == auth->name_length
+ && binary_equal (a->auth.name, auth->name, auth->name_length))
+ {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+/* Add one item to our list of auth items. */
+static void
+add_auth_item (Xauth *auth)
+{
+ addr_list *a = malloc (sizeof (addr_list));
+
+ a->auth.family = auth->family;
+ a->auth.address_length = auth->address_length;
+ a->auth.address = binary_dup (auth->address, auth->address_length);
+ a->auth.number_length = auth->number_length;
+ a->auth.number = binary_dup (auth->number, auth->number_length);
+ a->auth.name_length = auth->name_length;
+ a->auth.name = binary_dup (auth->name, auth->name_length);
+ a->auth.data_length = auth->data_length;
+ a->auth.data = binary_dup (auth->data, auth->data_length);
+
+ a->next = addresses;
+ addresses = a;
+}
+
+/* Free all allocated auth items. */
+static void
+free_auth_items (void)
+{
+ addr_list *a;
+
+ while ((a = addresses) != NULL)
+ {
+ addresses = a->next;
+
+ binary_free (a->auth.address, a->auth.address_length);
+ binary_free (a->auth.number, a->auth.number_length);
+ binary_free (a->auth.name, a->auth.name_length);
+ binary_free (a->auth.data, a->auth.data_length);
+ free (a);
+ }
+}
+
+/* Add the unix domain auth item. */
+static void
+define_local (Xauth *auth)
+{
+ char *host = host_name ();
+
+#ifdef DEBUG
+ fprintf (stderr, "x11: hostname is %s\n", host);
+#endif
+
+ auth->family = FamilyLocal;
+ auth->address_length = strlen (host);
+ auth->address = host;
+
+ add_auth_item (auth);
+}
+
+/* Add the tcp auth item. */
+static void
+define_named (Xauth *auth, const char *name)
+{
+ struct ifaddrs *addrs, *ptr;
+
+ if (getifaddrs (&addrs) != 0)
+ return;
+
+ for (ptr = addrs; ptr != NULL; ptr = ptr->ifa_next)
+ {
+ if (ptr->ifa_addr->sa_family != AF_INET)
+ continue;
+
+ auth->family = FamilyInternet;
+ auth->address_length = sizeof (struct sockaddr_in);
+ auth->address = (char *) &(((struct sockaddr_in *) ptr->ifa_addr)->sin_addr);
+
+#ifdef DEBUG
+ fprintf (stderr, "x11: ipaddr is %d.%d.%d.%d\n",
+ (unsigned char) auth->address[0],
+ (unsigned char) auth->address[1],
+ (unsigned char) auth->address[2],
+ (unsigned char) auth->address[3]);
+#endif
+
+ add_auth_item (auth);
+ }
+
+ freeifaddrs (addrs);
+}
+
+/* Parse the display number from NAME and add it to AUTH. */
+static void
+set_auth_number (Xauth *auth, const char *name)
+{
+ char *colon;
+ char *dot, *number;
+
+ colon = strrchr(name, ':');
+ if (colon != NULL)
+ {
+ colon++;
+ dot = strchr(colon, '.');
+
+ if (dot != NULL)
+ auth->number_length = dot - colon;
+ else
+ auth->number_length = strlen (colon);
+
+ number = malloc (auth->number_length + 1);
+ if (number != NULL)
+ {
+ strncpy (number, colon, auth->number_length);
+ number[auth->number_length] = '\0';
+ }
+ else
+ {
+ auth->number_length = 0;
+ }
+
+ auth->number = number;
+ }
+}
+
+/* Put 128 bits of random data into DATA. If possible, it will be "high
+ quality" */
+static int
+generate_mit_magic_cookie (char data[16])
+{
+ int fd, ret, i;
+ long *ldata = (long *) data;
+
+ fd = open ("/dev/random", O_RDONLY);
+ if (fd > 0)
+ {
+ ret = read (fd, data, 16);
+ if (ret == 16)
+ return TRUE;
+
+ close (fd);
+ }
+
+ /* fall back to the usual crappy rng */
+
+ srand48 (getpid () ^ time (NULL));
+
+ for (i = 0; i < 4; i++)
+ ldata[i] = lrand48 ();
+
+ return TRUE;
+}
+
+/* Create the keys we'll be using for the display named NAME. */
+static int
+make_auth_keys (const char *name)
+{
+ Xauth auth;
+ char key[16];
+
+ if (auth_file == NULL)
+ return FALSE;
+
+ auth.name = "MIT-MAGIC-COOKIE-1";
+ auth.name_length = strlen (auth.name);
+
+ if (!generate_mit_magic_cookie (key))
+ {
+ auth_file = NULL;
+ return FALSE;
+ }
+
+ auth.data = key;
+ auth.data_length = 16;
+
+ set_auth_number (&auth, name);
+
+ define_named (&auth, host_name ());
+ define_local (&auth);
+
+ free (auth.number);
+
+ return TRUE;
+}
+
+/* If ADD-ENTRIES is true, merge our auth entries into the existing
+ Xauthority file. If ADD-ENTRIES is false, remove our entries. */
+static int
+write_auth_file (int add_entries)
+{
+ char *home, newname[1024];
+ int fd, ret;
+ FILE *new_fh, *old_fh;
+ addr_list *addr;
+ Xauth *auth;
+
+ if (auth_file == NULL)
+ return FALSE;
+
+ home = getenv ("HOME");
+ if (home == NULL)
+ {
+ auth_file = NULL;
+ return FALSE;
+ }
+
+ snprintf (newname, sizeof (newname), "%s/.XauthorityXXXXXX", home);
+ mktemp (newname);
+
+ if (XauLockAuth (auth_file, 1, 2, 10) != LOCK_SUCCESS)
+ {
+ /* FIXME: do something here? */
+
+ auth_file = NULL;
+ return FALSE;
+ }
+
+ fd = open (newname, O_WRONLY | O_CREAT | O_TRUNC, 0600);
+ if (fd >= 0)
+ {
+ new_fh = fdopen (fd, "w");
+ if (new_fh != NULL)
+ {
+ if (add_entries)
+ {
+ for (addr = addresses; addr != NULL; addr = addr->next)
+ {
+ XauWriteAuth (new_fh, &addr->auth);
+ }
+ }
+
+ old_fh = fopen (auth_file, "r");
+ if (old_fh != NULL)
+ {
+ while ((auth = XauReadAuth (old_fh)) != NULL)
+ {
+ if (!check_auth_item (auth))
+ XauWriteAuth (new_fh, auth);
+ XauDisposeAuth (auth);
+ }
+ fclose (old_fh);
+ }
+
+ fclose (new_fh);
+ unlink (auth_file);
+
+ ret = rename (newname, auth_file);
+
+ if (ret != 0)
+ auth_file = NULL;
+
+ XauUnlockAuth (auth_file);
+ return ret == 0;
+ }
+
+ close (fd);
+ }
+
+ XauUnlockAuth (auth_file);
+ auth_file = NULL;
+ return FALSE;
+}
+
+\f
+/* Subprocess management functions. */
+
+static int
+start_server (char **xargv)
+{
+ int child;
+
+ child = fork ();
+
+ switch (child)
+ {
+ case -1: /* error */
+ perror ("fork");
+ return FALSE;
+
+ case 0: /* child */
+ execv (X_SERVER, xargv);
+ perror ("Couldn't exec " X_SERVER);
+ _exit (1);
+
+ default: /* parent */
+ server_pid = child;
+ return TRUE;
+ }
+}
+
+static int
+wait_for_server (void)
+{
+ int count = 100;
+
+ while (count-- > 0)
+ {
+ int status;
+
+ server_dpy = XOpenDisplay (server_name);
+ if (server_dpy != NULL)
+ return TRUE;
+
+ if (waitpid (server_pid, &status, WNOHANG) == server_pid)
+ return FALSE;
+
+ sleep (1);
+ }
+
+ return FALSE;
+}
+
+static int
+start_client (void)
+{
+ int child;
+
+ child = fork ();
+
+ switch (child)
+ {
+ char *tem, buf[1024];
+
+ case -1: /* error */
+ perror ("fork");
+ return FALSE;
+
+ case 0: /* child */
+ /* cd $HOME */
+ tem = getenv ("HOME");
+ if (tem != NULL)
+ chdir (tem);
+
+ /* Setup environment */
+
+ setenv ("DISPLAY", server_name, TRUE);
+ tem = getenv ("PATH");
+ if (tem != NULL && tem[0] != NULL)
+ snprintf (buf, sizeof (buf), "%s:/usr/X11R6/bin", tem);
+ else
+ snprintf (buf, sizeof (buf), "/bin:/usr/bin:/usr/X11R6/bin");
+ setenv ("PATH", buf, TRUE);
+
+#if 1
+ setenv("GTK_USE_XFT","1",0);
+ system(WM_PATH " &");
+ execl("/usr/local/bin/synfigstudio","/usr/local/bin/synfigstudio",NULL);
+
+#else
+ /* First look for .xinitrc in user's home directory. */
+
+ tem = getenv ("HOME");
+ if (tem != NULL)
+ {
+ snprintf (buf, sizeof (buf), "%s/.xinitrc", tem);
+ if (access (buf, R_OK) == 0)
+ execlp (SHELL, SHELL, buf, NULL);
+ }
+
+ /* Then try the default xinitrc in the lib directory. */
+
+ if (access (DEFAULT_XINITRC, R_OK) == 0)
+ execlp (SHELL, SHELL, DEFAULT_XINITRC, NULL);
+
+ /* Then fallback to hardcoding an xterm and the window manager. */
+
+ system (XTERM_PATH " &");
+ execl (WM_PATH, WM_PATH, NULL);
+
+#endif
+ perror ("exec");
+ _exit (1);
+
+ default: /* parent */
+ client_pid = child;
+ return TRUE;
+ }
+}
+
+static void
+sigchld_handler (int sig)
+{
+ int pid, status;
+
+again:
+ pid = waitpid (WAIT_ANY, &status, WNOHANG);
+
+ if (pid > 0)
+ {
+ if (pid == server_pid)
+ {
+ server_pid = -1;
+
+ if (client_pid >= 0)
+ kill (client_pid, SIGTERM);
+ }
+ else if (pid == client_pid)
+ {
+ client_pid = -1;
+
+ if (server_pid >= 0 && xinit_kills_server)
+ kill (server_pid, SIGTERM);
+ }
+ goto again;
+ }
+
+ if (server_pid == -1 && client_pid == -1)
+ longjmp (exit_continuation, 1);
+
+ signal (SIGCHLD, sigchld_handler);
+}
+
+\f
+/* Server utilities. */
+
+static Boolean
+display_exists_p (int number)
+{
+ char buf[64];
+ void *conn;
+ char *fullname = NULL;
+ int idisplay, iscreen;
+ char *conn_auth_name, *conn_auth_data;
+ int conn_auth_namelen, conn_auth_datalen;
+
+ extern void *_X11TransConnectDisplay ();
+ extern void _XDisconnectDisplay ();
+
+ /* Since connecting to the display waits for a few seconds if the
+ display doesn't exist, check for trivial non-existence - if the
+ socket in /tmp exists or not.. (note: if the socket exists, the
+ server may still not, so we need to try to connect in that case..) */
+
+ sprintf (buf, "/tmp/.X11-unix/X%d", number);
+ if (access (buf, F_OK) != 0)
+ return FALSE;
+
+ /* This is a private function that we shouldn't really be calling,
+ but it's the best way to see if the server exists (without
+ needing to hold the necessary authentication to use it) */
+
+ sprintf (buf, ":%d", number);
+ conn = _X11TransConnectDisplay (buf, &fullname, &idisplay, &iscreen,
+ &conn_auth_name, &conn_auth_namelen,
+ &conn_auth_data, &conn_auth_datalen);
+ if (conn == NULL)
+ return FALSE;
+
+ _XDisconnectDisplay (conn);
+ return TRUE;
+}
+
+\f
+/* Monitoring when the system's ip addresses change. */
+
+static Boolean pending_timer;
+
+static void
+timer_callback (CFRunLoopTimerRef timer, void *info)
+{
+ pending_timer = FALSE;
+
+ /* Update authentication names. Need to write .Xauthority file first
+ without the existing entries, then again with the new entries.. */
+
+ write_auth_file (FALSE);
+
+ free_auth_items ();
+ make_auth_keys (server_name);
+
+ write_auth_file (TRUE);
+}
+
+/* This function is called when the system's ip addresses may have changed. */
+static void
+ipaddr_callback (SCDynamicStoreRef store, CFArrayRef changed_keys, void *info)
+{
+ if (auth_file != NULL && !pending_timer)
+ {
+ CFRunLoopTimerRef timer;
+
+ timer = CFRunLoopTimerCreate (NULL, CFAbsoluteTimeGetCurrent () + 1.0,
+ 0.0, 0, 0, timer_callback, NULL);
+ CFRunLoopAddTimer (CFRunLoopGetCurrent (), timer,
+ kCFRunLoopDefaultMode);
+ CFRelease (timer);
+
+ pending_timer = TRUE;
+ }
+}
+
+/* This code adapted from "Living in a Dynamic TCP/IP Environment" technote. */
+static Boolean
+install_ipaddr_source (void)
+{
+ CFRunLoopSourceRef source = NULL;
+
+ SCDynamicStoreContext context = {0};
+ SCDynamicStoreRef ref;
+
+ ref = SCDynamicStoreCreate (NULL,
+ CFSTR ("AddIPAddressListChangeCallbackSCF"),
+ ipaddr_callback, &context);
+
+ if (ref != NULL)
+ {
+ const void *keys[2];
+
+ /* This should tell us when any IPV4 address changes */
+ keys[0] = (SCDynamicStoreKeyCreateNetworkServiceEntity
+ (NULL, kSCDynamicStoreDomainState,
+ kSCCompAnyRegex, kSCEntNetIPv4));
+
+ /* This should tell us when the hostname(s) change */
+ keys[1] = SCDynamicStoreKeyCreateHostNames (NULL);
+
+ if (keys[0] != NULL && keys[1] != NULL)
+ {
+ CFArrayRef pattern_array;
+
+ pattern_array = CFArrayCreate (NULL, keys, 2,
+ &kCFTypeArrayCallBacks);
+
+ if (pattern_array != NULL)
+ {
+ SCDynamicStoreSetNotificationKeys (ref, NULL, pattern_array);
+ source = SCDynamicStoreCreateRunLoopSource (NULL, ref, 0);
+
+ CFRelease (pattern_array);
+ }
+
+ if (keys[0] != NULL)
+ CFRelease (keys[0]);
+ if (keys[1] != NULL)
+ CFRelease (keys[1]);
+ }
+
+ CFRelease (ref);
+ }
+
+ if (source != NULL)
+ {
+ CFRunLoopAddSource (CFRunLoopGetCurrent (),
+ source, kCFRunLoopDefaultMode);
+ CFRelease (source);
+ }
+
+ return source != NULL;
+}
+
+
+\f
+/* Entrypoint. */
+int
+main (int argc, char **argv)
+{
+ char **xargv;
+ int i, j;
+ int fd;
+
+
+
+
+
+
+ xargv = alloca (sizeof (char *) * (argc + 32));
+
+ if (!read_boolean_pref (CFSTR ("no_auth"), FALSE))
+ auth_file = XauFileName ();
+
+ /* The standard X11 behaviour is for the server to quit when the first
+ client exits. But it can be useful for debugging (and to mimic our
+ behaviour in the beta releases) to not do that. */
+
+ xinit_kills_server = read_boolean_pref (CFSTR ("xinit_kills_server"), TRUE);
+
+ for (i = 1; i < argc; i++)
+ {
+ if (argv[i][0] == ':')
+ server_name = argv[i];
+ }
+
+ if (server_name == NULL)
+ {
+ static char name[8];
+
+ /* No display number specified, so search for the first unused.
+
+ There's a big old race condition here if two servers start at
+ the same time, but that's fairly unlikely. We could create
+ lockfiles or something, but that's seems more likely to cause
+ problems than the race condition itself.. */
+
+ for (i = 2; i < MAX_DISPLAYS; i++)
+ {
+ if (!display_exists_p (i))
+ break;
+ }
+
+ if (i == MAX_DISPLAYS)
+ {
+ fprintf (stderr, "%s: couldn't allocate a display number", argv[0]);
+ exit (1);
+ }
+
+ sprintf (name, ":%d", i);
+ server_name = name;
+ }
+
+ if (auth_file != NULL)
+ {
+ /* Create new Xauth keys and add them to the .Xauthority file */
+
+ make_auth_keys (server_name);
+ write_auth_file (TRUE);
+ }
+
+ /* Construct our new argv */
+
+ i = j = 0;
+
+ xargv[i++] = argv[j++];
+
+ if (auth_file != NULL)
+ {
+ xargv[i++] = "-auth";
+ xargv[i++] = auth_file;
+ }
+
+ /* By default, don't listen on tcp sockets if Xauth is disabled. */
+
+ if (read_boolean_pref (CFSTR ("nolisten_tcp"), auth_file == NULL))
+ {
+ xargv[i++] = "-nolisten";
+ xargv[i++] = "tcp";
+ }
+
+ while (j < argc)
+ {
+ if (argv[j++][0] != ':')
+ xargv[i++] = argv[j-1];
+ }
+
+ xargv[i++] = (char *) server_name;
+ xargv[i++] = NULL;
+
+ /* Detach from any controlling terminal and connect stdin to /dev/null */
+
+#ifdef TIOCNOTTY
+ fd = open ("/dev/tty", O_RDONLY);
+ if (fd != -1)
+ {
+ ioctl (fd, TIOCNOTTY, 0);
+ close (fd);
+ }
+#endif
+
+ fd = open ("/dev/null", O_RDWR, 0);
+ if (fd >= 0)
+ {
+ dup2 (fd, 0);
+ if (fd > 0)
+ close (fd);
+ }
+
+ if (!start_server (xargv))
+ return 1;
+
+ if (!wait_for_server ())
+ {
+ kill (server_pid, SIGTERM);
+ return 1;
+ }
+
+ if (!start_client ())
+ {
+ kill (server_pid, SIGTERM);
+ return 1;
+ }
+
+ signal (SIGCHLD, sigchld_handler);
+
+ if (NSIsSymbolNameDefined("_ASKInitialize"))
+ {
+ NSSymbol *symbol = NSLookupAndBindSymbol("_ASKInitialize");
+ if (symbol)
+ {
+ void (*initializeASKFunc)(void) = NSAddressOfSymbol(symbol);
+ if (initializeASKFunc)
+ {
+ initializeASKFunc();
+ }
+ else
+ return 666;
+ }
+ else return 667;
+ }else
+ return 668;
+
+ if (setjmp (exit_continuation) == 0)
+ {
+ if (install_ipaddr_source ())
+ CFRunLoopRun ();
+ else
+ while (1) pause ();
+ }
+
+ signal (SIGCHLD, SIG_IGN);
+
+ if (auth_file != NULL)
+ {
+ /* Remove our Xauth keys */
+
+ write_auth_file (FALSE);
+ }
+
+ free_auth_items ();
+
+ return 0;
+}
--- /dev/null
+/* darwin-input.c -- code to manage the input event queue
+ $Id: darwin-input.c,v 1.4 2002/12/13 00:22:51 jharper Exp $ */
+
+/*
+ * Copyright (c) 2001-2002 Torrey T. Lyons. All Rights Reserved.
+ * Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name(s) of the above copyright
+ * holders shall not be used in advertising or otherwise to promote the sale,
+ * use or other dealings in this Software without prior written authorization.
+ */
+
+#include "darwin.h"
+
+#include "mipointer.h" // mi software cursor
+
+#include <pthread.h>
+
+#define QUEUE_SIZE 256
+
+static struct {
+ pthread_mutex_t mutex;
+
+ /* DIX looks at these two integer values, when they're equal
+ it won't call ProcessInputEvents (). */
+ HWEventQueueType head, tail;
+
+ xEvent events[QUEUE_SIZE];
+} event_queue;
+
+/* fd[0] = reading, fd[1] = writing */
+static int event_fd[2];
+
+void
+DarwinEnqueueEvent (const xEvent *e)
+{
+ int newtail, oldtail;
+ int need_write = FALSE;
+
+ pthread_mutex_lock (&event_queue.mutex);
+
+ oldtail = (event_queue.tail - 1) % QUEUE_SIZE;
+
+ if (e->u.u.type == MotionNotify
+ && event_queue.tail != event_queue.head
+ && event_queue.events[oldtail].u.u.type == MotionNotify)
+ {
+ /* Two adjacent motion notify events. Coalesce them. */
+
+ memcpy (&event_queue.events[oldtail], e, sizeof (xEvent));
+ }
+ else
+ {
+ newtail = (event_queue.tail + 1) % QUEUE_SIZE;
+
+ if (newtail != event_queue.head)
+ {
+ memcpy (&event_queue.events[event_queue.tail], e, sizeof (xEvent));
+ event_queue.tail = newtail;
+ need_write = TRUE;
+ }
+ }
+
+ pthread_mutex_unlock (&event_queue.mutex);
+
+ if (need_write)
+ write (event_fd[1], &need_write, sizeof (need_write));
+}
+
+Bool
+DarwinDequeueEvent (xEvent *e)
+{
+ Bool ret = FALSE;
+ int unused;
+
+ pthread_mutex_lock (&event_queue.mutex);
+
+ if (event_queue.head != event_queue.tail)
+ {
+ memcpy (e, &event_queue.events[event_queue.head], sizeof (xEvent));
+ event_queue.head = (event_queue.head + 1) % QUEUE_SIZE;
+ ret = TRUE;
+ }
+
+ pthread_mutex_unlock (&event_queue.mutex);
+
+ if (ret)
+ read (event_fd[0], &unused, sizeof (unused));
+
+ return ret;
+}
+
+void
+DarwinInputPreInit (void)
+{
+ if (pipe (event_fd) != 0)
+ {
+ perror ("pipe");
+ exit (1);
+ }
+
+ event_queue.head = event_queue.tail = 0;
+ pthread_mutex_init (&event_queue.mutex, NULL);
+}
+
+void
+DarwinInputInit (void)
+{
+ SetInputCheck (&event_queue.head, &event_queue.tail);
+}
+
+\f
+/*
+ =============================================================================
+
+ mouse and keyboard callbacks
+
+ =============================================================================
+*/
+
+/*
+ * DarwinChangePointerControl
+ * Set mouse acceleration and thresholding
+ * FIXME: We currently ignore the threshold in ctrl->threshold.
+ */
+static void DarwinChangePointerControl(DeviceIntPtr device, PtrCtrl *ctrl)
+{
+ /* do nothing here */
+}
+
+
+/*
+ * DarwinMouseProc
+ * Handle the initialization, etc. of a mouse
+ */
+
+int DarwinMouseProc(DeviceIntPtr pPointer, int what)
+{
+ char map[6];
+
+ switch (what) {
+
+ case DEVICE_INIT:
+ pPointer->public.on = FALSE;
+
+ // Set button map.
+ map[1] = 1;
+ map[2] = 2;
+ map[3] = 3;
+ map[4] = 4;
+ map[5] = 5;
+ InitPointerDeviceStruct( (DevicePtr)pPointer,
+ map,
+ 5, // numbuttons (4 & 5 are scroll wheel)
+ miPointerGetMotionEvents,
+ DarwinChangePointerControl,
+ 0 );
+ break;
+
+ case DEVICE_ON:
+ pPointer->public.on = TRUE;
+ AddEnabledDevice(event_fd[0]);
+ return Success;
+
+ case DEVICE_CLOSE:
+ case DEVICE_OFF:
+ pPointer->public.on = FALSE;
+ RemoveEnabledDevice(event_fd[0]);
+ return Success;
+ }
+
+ return Success;
+}
+
+/*
+ * DarwinKeybdProc
+ * Callback from X
+ */
+int DarwinKeybdProc(DeviceIntPtr pDev, int onoff)
+{
+ switch ( onoff ) {
+ case DEVICE_INIT:
+ DarwinKeyboardInit( pDev );
+ break;
+ case DEVICE_ON:
+ pDev->public.on = TRUE;
+ AddEnabledDevice(event_fd[0]);
+ break;
+ case DEVICE_OFF:
+ pDev->public.on = FALSE;
+ RemoveEnabledDevice(event_fd[0]);
+ break;
+ case DEVICE_CLOSE:
+ break;
+ }
+
+ return Success;
+}
--- /dev/null
+/* darwin-keyboard.c -- Keyboard support for the Darwin X Server
+
+ Copyright (c) 2001-2002 Torrey T. Lyons. All Rights Reserved.
+ Copyright (c) 2003 Apple Computer, Inc. All Rights Reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. The name of the author may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
+
+/* $XFree86: xc/programs/Xserver/hw/darwin/darwinKeyboard.c,v 1.16 2002/03/28 02:21:08 torrey Exp $ */
+
+
+/* An X keyCode must be in the range XkbMinLegalKeyCode (8) to
+ XkbMaxLegalKeyCode(255).
+
+ The keyCodes we get from the kernel range from 0 to 127, so we need to
+ offset the range before passing the keyCode to X.
+
+ An X KeySym is an extended ascii code that is device independent.
+
+ The modifier map is accessed by the keyCode, but the normal map is
+ accessed by keyCode - MIN_KEYCODE. Sigh. */
+
+
+/* Define this to get a diagnostic output to stderr which is helpful
+ in determining how the X server is interpreting the Darwin keymap. */
+#undef DUMP_DARWIN_KEYMAP
+
+/* Define this to use Alt for Mode_switch. */
+#define ALT_IS_MODE_SWITCH 1
+
+#include "darwin.h"
+#include "darwin-keyboard.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "darwin.h"
+#include "quartz-audio.h"
+
+/* For NX_ constants */
+#include <IOKit/hidsystem/IOLLEvent.h>
+#include <IOKit/hidsystem/ev_keymap.h>
+
+#include "keysym.h"
+
+static darwin_keyboard_info info;
+
+static void
+DarwinChangeKeyboardControl (DeviceIntPtr device, KeybdCtrl *ctrl)
+{
+ /* keyclick, bell volume / pitch, autorepeat, LED's */
+}
+
+/* Use the key_map field of INFO to populate the mod_map and
+ modifier_keycodes fields */
+static void
+build_modifier_maps (darwin_keyboard_info *info)
+{
+ int i;
+ KeySym *k;
+
+ memset (info->mod_map, NoSymbol, sizeof (info->mod_map));
+ memset (info->modifier_keycodes, 0, sizeof (info->modifier_keycodes));
+
+ for (i = 0; i < NUM_KEYCODES; i++)
+ {
+ k = info->key_map + i * GLYPHS_PER_KEY;
+
+ switch (k[0])
+ {
+ case XK_Shift_L:
+ info->modifier_keycodes[NX_MODIFIERKEY_SHIFT][0] = i;
+ info->mod_map[MIN_KEYCODE + i] = ShiftMask;
+ break;
+
+ case XK_Shift_R:
+ info->modifier_keycodes[NX_MODIFIERKEY_SHIFT][1] = i;
+ info->mod_map[MIN_KEYCODE + i] = ShiftMask;
+ break;
+
+ case XK_Control_L:
+ info->modifier_keycodes[NX_MODIFIERKEY_CONTROL][0] = i;
+ info->mod_map[MIN_KEYCODE + i] = ControlMask;
+ break;
+
+ case XK_Control_R:
+ info->modifier_keycodes[NX_MODIFIERKEY_CONTROL][1] = i;
+ info->mod_map[MIN_KEYCODE + i] = ControlMask;
+ break;
+
+ case XK_Caps_Lock:
+ info->modifier_keycodes[NX_MODIFIERKEY_ALPHALOCK][0] = i;
+ info->mod_map[MIN_KEYCODE + i] = LockMask;
+ break;
+
+ case XK_Alt_L:
+ info->modifier_keycodes[NX_MODIFIERKEY_ALTERNATE][0] = i;
+ info->mod_map[MIN_KEYCODE + i] = Mod1Mask;
+ break;
+
+ case XK_Alt_R:
+ info->modifier_keycodes[NX_MODIFIERKEY_ALTERNATE][1] = i;
+ info->mod_map[MIN_KEYCODE + i] = Mod1Mask;
+ break;
+
+ case XK_Mode_switch:
+ info->mod_map[MIN_KEYCODE + i] = Mod1Mask;
+ break;
+
+ case XK_Meta_L:
+ info->modifier_keycodes[NX_MODIFIERKEY_COMMAND][0] = i;
+ info->mod_map[MIN_KEYCODE + i] = Mod2Mask;
+ break;
+
+ case XK_Meta_R:
+ info->modifier_keycodes[NX_MODIFIERKEY_COMMAND][1] = i;
+ info->mod_map[MIN_KEYCODE + i] = Mod2Mask;
+ break;
+
+ case XK_Num_Lock:
+ info->mod_map[MIN_KEYCODE + i] = Mod3Mask;
+ break;
+ }
+
+ if (darwinSwapAltMeta)
+ {
+ switch (k[0])
+ {
+ case XK_Alt_L:
+ k[0] = XK_Meta_L; break;
+ case XK_Alt_R:
+ k[0] = XK_Meta_R; break;
+ case XK_Meta_L:
+ k[0] = XK_Alt_L; break;
+ case XK_Meta_R:
+ k[0] = XK_Alt_R; break;
+ }
+ }
+
+#if ALT_IS_MODE_SWITCH
+ if (k[0] == XK_Alt_L || k[0] == XK_Alt_R)
+ k[0] = XK_Mode_switch;
+#endif
+ }
+}
+
+static void
+load_keyboard_mapping (KeySymsRec *keysyms)
+{
+ memset (info.key_map, 0, sizeof (info.key_map));
+
+ if (darwinKeymapFile == NULL
+ || !DarwinParseKeymapFile (&info))
+ {
+ /* Load the system keymapping. */
+
+ DarwinReadSystemKeymap (&info);
+ }
+
+ build_modifier_maps (&info);
+
+#ifdef DUMP_DARWIN_KEYMAP
+ ErrorF("Darwin -> X converted keyboard map\n");
+ for (i = 0, k = map; i < NX_NUMKEYCODES; i++, k += GLYPHS_PER_KEY) {
+ int j;
+ ErrorF("0x%02x:", i);
+ for (j = 0; j < GLYPHS_PER_KEY; j++) {
+ if (k[j] == NoSymbol) {
+ ErrorF("\tNoSym");
+ } else {
+ ErrorF("\t0x%x", k[j]);
+ }
+ }
+ ErrorF("\n");
+ }
+#endif
+
+ keysyms->map = info.key_map;
+ keysyms->mapWidth = GLYPHS_PER_KEY;
+ keysyms->minKeyCode = MIN_KEYCODE;
+ keysyms->maxKeyCode = MAX_KEYCODE;
+}
+
+/* Get the Darwin keyboard map and compute an equivalent X keyboard map
+ and modifier map. Set the new keyboard device structure. */
+void
+DarwinKeyboardInit (DeviceIntPtr pDev)
+{
+ KeySymsRec keysyms;
+ BellProcPtr bellProc;
+
+ load_keyboard_mapping (&keysyms);
+
+ /* Initialize the seed, so we don't reload the keymap unnecessarily
+ (and possibly overwrite xinitrc changes) */
+ DarwinSystemKeymapSeed ();
+
+ bellProc = QuartzBell;
+
+ InitKeyboardDeviceStruct ((DevicePtr) pDev, &keysyms, info.mod_map,
+ bellProc, DarwinChangeKeyboardControl);
+}
+
+/* Borrowed from dix/devices.c */
+static Bool
+InitModMap(register KeyClassPtr keyc)
+{
+ int i, j;
+ CARD8 keysPerModifier[8];
+ CARD8 mask;
+
+ if (keyc->modifierKeyMap != NULL)
+ xfree (keyc->modifierKeyMap);
+
+ keyc->maxKeysPerModifier = 0;
+ for (i = 0; i < 8; i++)
+ keysPerModifier[i] = 0;
+ for (i = 8; i < MAP_LENGTH; i++)
+ {
+ for (j = 0, mask = 1; j < 8; j++, mask <<= 1)
+ {
+ if (mask & keyc->modifierMap[i])
+ {
+ if (++keysPerModifier[j] > keyc->maxKeysPerModifier)
+ keyc->maxKeysPerModifier = keysPerModifier[j];
+ }
+ }
+ }
+ keyc->modifierKeyMap = (KeyCode *)xalloc(8*keyc->maxKeysPerModifier);
+ if (!keyc->modifierKeyMap && keyc->maxKeysPerModifier)
+ return (FALSE);
+ bzero((char *)keyc->modifierKeyMap, 8*(int)keyc->maxKeysPerModifier);
+ for (i = 0; i < 8; i++)
+ keysPerModifier[i] = 0;
+ for (i = 8; i < MAP_LENGTH; i++)
+ {
+ for (j = 0, mask = 1; j < 8; j++, mask <<= 1)
+ {
+ if (mask & keyc->modifierMap[i])
+ {
+ keyc->modifierKeyMap[(j*keyc->maxKeysPerModifier) +
+ keysPerModifier[j]] = i;
+ keysPerModifier[j]++;
+ }
+ }
+ }
+ return TRUE;
+}
+
+void
+DarwinKeyboardReload (DeviceIntPtr pDev)
+{
+ KeySymsRec keysyms;
+
+ load_keyboard_mapping (&keysyms);
+
+ if (SetKeySymsMap (&pDev->key->curKeySyms, &keysyms))
+ {
+ /* now try to update modifiers. */
+
+ memmove (pDev->key->modifierMap, info.mod_map, MAP_LENGTH);
+ InitModMap (pDev->key);
+ }
+
+ SendMappingNotify (MappingKeyboard, MIN_KEYCODE, NUM_KEYCODES, 0);
+ SendMappingNotify (MappingModifier, 0, 0, 0);
+}
+
+/* Return the keycode for an NX_MODIFIERKEY_* modifier. side = 0 for left
+ or 1 for right. Returns 0 if key+side is not a known modifier. */
+int
+DarwinModifierNXKeyToNXKeycode (int key, int side)
+{
+ return info.modifier_keycodes[key][side];
+}
+
+/* This allows the ddx layer to prevent some keys from being remapped
+ as modifier keys. */
+Bool
+LegalModifier (unsigned int key, DevicePtr pDev)
+{
+ return 1;
+}
--- /dev/null
+/* darwin-keyboard.h
+ $Id: darwin-keyboard.h,v 1.1 2003/01/22 01:54:10 jharper Exp $
+
+ Copyright (c) 2003 Apple Computer, Inc. All rights reserved.
+
+ Permission is hereby granted, free of charge, to any person
+ obtaining a copy of this software and associated documentation files
+ (the "Software"), to deal in the Software without restriction,
+ including without limitation the rights to use, copy, modify, merge,
+ publish, distribute, sublicense, and/or sell copies of the Software,
+ and to permit persons to whom the Software is furnished to do so,
+ subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT
+ HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ DEALINGS IN THE SOFTWARE.
+
+ Except as contained in this notice, the name(s) of the above
+ copyright holders shall not be used in advertising or otherwise to
+ promote the sale, use or other dealings in this Software without
+ prior written authorization. */
+
+#ifndef DARWIN_KEYBOARD_H
+#define DARWIN_KEYBOARD_H 1
+
+#include "X.h"
+
+/* Each key can generate 4 glyphs. They are, in order:
+ unshifted, shifted, modeswitch unshifted, modeswitch shifted */
+
+#ifndef MIN_KEYCODE
+# define MIN_KEYCODE 8
+#endif
+
+#define GLYPHS_PER_KEY 4
+#define NUM_KEYCODES 248
+#define MAX_KEYCODE NUM_KEYCODES + MIN_KEYCODE - 1
+
+typedef struct darwin_keyboard_info_struct darwin_keyboard_info;
+
+struct darwin_keyboard_info_struct {
+ unsigned char mod_map[MAX_KEYCODE+1];
+ KeySym key_map[NUM_KEYCODES * GLYPHS_PER_KEY];
+ unsigned char modifier_keycodes[32][2];
+};
+
+extern int DarwinReadSystemKeymap (darwin_keyboard_info *info);
+extern int DarwinParseKeymapFile (darwin_keyboard_info *info);
+
+#endif /* DARWIN_KEYBOARD_H */
--- /dev/null
+/* darwin-new-keymap.c -- code to build a keymap from the system
+ $Id: darwin-new-keymap.c,v 1.7 2003/02/21 22:33:19 jharper Exp $
+
+ Copyright (c) 2003 Apple Computer, Inc. All rights reserved.
+
+ Permission is hereby granted, free of charge, to any person
+ obtaining a copy of this software and associated documentation files
+ (the "Software"), to deal in the Software without restriction,
+ including without limitation the rights to use, copy, modify, merge,
+ publish, distribute, sublicense, and/or sell copies of the Software,
+ and to permit persons to whom the Software is furnished to do so,
+ subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT
+ HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ DEALINGS IN THE SOFTWARE.
+
+ Except as contained in this notice, the name(s) of the above
+ copyright holders shall not be used in advertising or otherwise to
+ promote the sale, use or other dealings in this Software without
+ prior written authorization. */
+
+
+#define Cursor X_Cursor
+# include "darwin-keyboard.h"
+# include "keysym.h"
+#undef Cursor
+
+#include <CoreServices/CoreServices.h>
+#include <Carbon/Carbon.h>
+
+#include "keysym2ucs.h"
+
+#define HACK_MISSING 1
+#define HACK_KEYPAD 1
+
+enum {
+ MOD_COMMAND = 256,
+ MOD_SHIFT = 512,
+ MOD_OPTION = 2048,
+ MOD_CONTROL = 4096,
+};
+
+#define UKEYSYM(u) ((u) | 0x01000000)
+
+/* Table of keycode->keysym mappings we use to fallback on for important
+ keys that are often not in the Unicode mapping. */
+
+const static struct {
+ unsigned short keycode;
+ KeySym keysym;
+} known_keys[] = {
+ {55, XK_Meta_L},
+ {56, XK_Shift_L},
+ {57, XK_Caps_Lock},
+ {58, XK_Alt_L},
+ {59, XK_Control_L},
+ {60, XK_Shift_R},
+ {61, XK_Alt_R},
+ {62, XK_Control_R},
+
+ {122, XK_F1},
+ {120, XK_F2},
+ {99, XK_F3},
+ {118, XK_F4},
+ {96, XK_F5},
+ {97, XK_F6},
+ {98, XK_F7},
+ {100, XK_F8},
+ {101, XK_F9},
+ {109, XK_F10},
+ {103, XK_F11},
+ {111, XK_F12},
+ {105, XK_F13},
+ {107, XK_F14},
+ {113, XK_F15},
+};
+
+/* Table of keycode->old,new-keysym mappings we use to fixup the numeric
+ keypad entries. */
+
+const static struct {
+ unsigned short keycode;
+ KeySym normal, keypad;
+} known_numeric_keys[] = {
+ {65, XK_period, XK_KP_Decimal},
+ {67, XK_asterisk, XK_KP_Multiply},
+ {69, XK_plus, XK_KP_Add},
+ {75, XK_slash, XK_KP_Divide},
+ {76, 0x01000003, XK_KP_Enter},
+ {78, XK_minus, XK_KP_Subtract},
+ {81, XK_equal, XK_KP_Equal},
+ {82, XK_0, XK_KP_0},
+ {83, XK_1, XK_KP_1},
+ {84, XK_2, XK_KP_2},
+ {85, XK_3, XK_KP_3},
+ {86, XK_4, XK_KP_4},
+ {87, XK_5, XK_KP_5},
+ {88, XK_6, XK_KP_6},
+ {89, XK_7, XK_KP_7},
+ {91, XK_8, XK_KP_8},
+ {92, XK_9, XK_KP_9},
+};
+
+/* Table mapping normal keysyms to their dead equivalents.
+ FIXME: all the unicode keysyms (apart from circumflex) were guessed. */
+
+const static struct {
+ KeySym normal, dead;
+} dead_keys[] = {
+ {XK_grave, XK_dead_grave},
+ {XK_acute, XK_dead_acute},
+ {XK_asciicircum, XK_dead_circumflex},
+ {UKEYSYM (0x2c6), XK_dead_circumflex}, /* MODIFIER LETTER CIRCUMFLEX ACCENT */
+ {XK_asciitilde, XK_dead_tilde},
+ {UKEYSYM (0x2dc), XK_dead_tilde}, /* SMALL TILDE */
+ {XK_macron, XK_dead_macron},
+ {XK_breve, XK_dead_breve},
+ {XK_abovedot, XK_dead_abovedot},
+ {XK_diaeresis, XK_dead_diaeresis},
+ {UKEYSYM (0x2da), XK_dead_abovering}, /* DOT ABOVE */
+ {XK_doubleacute, XK_dead_doubleacute},
+ {XK_caron, XK_dead_caron},
+ {XK_cedilla, XK_dead_cedilla},
+ {XK_ogonek, XK_dead_ogonek},
+ {UKEYSYM (0x269), XK_dead_iota}, /* LATIN SMALL LETTER IOTA */
+ {UKEYSYM (0x2ec), XK_dead_voiced_sound}, /* MODIFIER LETTER VOICING */
+/* {XK_semivoiced_sound, XK_dead_semivoiced_sound}, */
+ {UKEYSYM (0x323), XK_dead_belowdot}, /* COMBINING DOT BELOW */
+ {UKEYSYM (0x309), XK_dead_hook}, /* COMBINING HOOK ABOVE */
+ {UKEYSYM (0x31b), XK_dead_horn}, /* COMBINING HORN */
+};
+
+unsigned int
+DarwinSystemKeymapSeed (void)
+{
+ static unsigned int seed;
+
+ static KeyboardLayoutRef last_key_layout;
+ KeyboardLayoutRef key_layout;
+
+ KLGetCurrentKeyboardLayout (&key_layout);
+
+ if (key_layout != last_key_layout)
+ seed++;
+
+ last_key_layout = key_layout;
+
+ return seed;
+}
+
+static inline UniChar
+macroman2ucs (unsigned char c)
+{
+ /* Precalculated table mapping MacRoman-128 to Unicode. Generated
+ by creating single element CFStringRefs then extracting the
+ first character. */
+
+ static const unsigned short table[128] = {
+ 0xc4, 0xc5, 0xc7, 0xc9, 0xd1, 0xd6, 0xdc, 0xe1,
+ 0xe0, 0xe2, 0xe4, 0xe3, 0xe5, 0xe7, 0xe9, 0xe8,
+ 0xea, 0xeb, 0xed, 0xec, 0xee, 0xef, 0xf1, 0xf3,
+ 0xf2, 0xf4, 0xf6, 0xf5, 0xfa, 0xf9, 0xfb, 0xfc,
+ 0x2020, 0xb0, 0xa2, 0xa3, 0xa7, 0x2022, 0xb6, 0xdf,
+ 0xae, 0xa9, 0x2122, 0xb4, 0xa8, 0x2260, 0xc6, 0xd8,
+ 0x221e, 0xb1, 0x2264, 0x2265, 0xa5, 0xb5, 0x2202, 0x2211,
+ 0x220f, 0x3c0, 0x222b, 0xaa, 0xba, 0x3a9, 0xe6, 0xf8,
+ 0xbf, 0xa1, 0xac, 0x221a, 0x192, 0x2248, 0x2206, 0xab,
+ 0xbb, 0x2026, 0xa0, 0xc0, 0xc3, 0xd5, 0x152, 0x153,
+ 0x2013, 0x2014, 0x201c, 0x201d, 0x2018, 0x2019, 0xf7, 0x25ca,
+ 0xff, 0x178, 0x2044, 0x20ac, 0x2039, 0x203a, 0xfb01, 0xfb02,
+ 0x2021, 0xb7, 0x201a, 0x201e, 0x2030, 0xc2, 0xca, 0xc1,
+ 0xcb, 0xc8, 0xcd, 0xce, 0xcf, 0xcc, 0xd3, 0xd4,
+ 0xf8ff, 0xd2, 0xda, 0xdb, 0xd9, 0x131, 0x2c6, 0x2dc,
+ 0xaf, 0x2d8, 0x2d9, 0x2da, 0xb8, 0x2dd, 0x2db, 0x2c7,
+ };
+
+ if (c < 128)
+ return c;
+ else
+ return table[c - 128];
+}
+
+static KeySym
+make_dead_key (KeySym in)
+{
+ int i;
+
+ for (i = 0; i < sizeof (dead_keys) / sizeof (dead_keys[0]); i++)
+ {
+ if (dead_keys[i].normal == in)
+ return dead_keys[i].dead;
+ }
+
+ return in;
+}
+
+int
+DarwinReadSystemKeymap (darwin_keyboard_info *info)
+{
+ KeyboardLayoutRef key_layout;
+ const void *chr_data;
+ int num_keycodes = NUM_KEYCODES;
+ UInt32 keyboard_type = 0;
+ int is_uchr, i, j;
+ OSStatus err;
+ KeySym *k;
+
+ KLGetCurrentKeyboardLayout (&key_layout);
+ KLGetKeyboardLayoutProperty (key_layout, kKLuchrData, &chr_data);
+
+ if (chr_data != NULL)
+ {
+ is_uchr = 1;
+ keyboard_type = LMGetKbdType ();
+ }
+ else
+ {
+ KLGetKeyboardLayoutProperty (key_layout, kKLKCHRData, &chr_data);
+
+ if (chr_data == NULL)
+ {
+ fprintf (stderr, "couldn't get uchr or kchr resource\n");
+ return FALSE;
+ }
+
+ is_uchr = 0;
+ num_keycodes = 128;
+ }
+
+
+ /* Scan the keycode range for the Unicode character that each
+ key produces in the four shift states. Then convert that to
+ an X11 keysym (which may just the bit that says "this is
+ Unicode" if it can't find the real symbol.) */
+
+ for (i = 0; i < num_keycodes; i++)
+ {
+ static const int mods[4] = {0, MOD_SHIFT, MOD_OPTION,
+ MOD_OPTION | MOD_SHIFT};
+
+ k = info->key_map + i * GLYPHS_PER_KEY;
+
+ for (j = 0; j < 4; j++)
+ {
+ if (is_uchr)
+ {
+ UniChar s[8];
+ UniCharCount len;
+ UInt32 dead_key_state, extra_dead;
+
+ dead_key_state = 0;
+ err = UCKeyTranslate (chr_data, i, kUCKeyActionDown,
+ mods[j] >> 8, keyboard_type, 0,
+ &dead_key_state, 8, &len, s);
+ if (err != noErr)
+ continue;
+
+ if (len == 0 && dead_key_state != 0)
+ {
+ /* Found a dead key. Work out which one it is, but
+ remembering that it's dead. */
+
+ extra_dead = 0;
+ err = UCKeyTranslate (chr_data, i, kUCKeyActionDown,
+ mods[j] >> 8, keyboard_type,
+ kUCKeyTranslateNoDeadKeysMask,
+ &extra_dead, 8, &len, s);
+ if (err != noErr)
+ continue;
+ }
+
+ if (len > 0 && s[0] != 0x0010)
+ {
+ k[j] = ucs2keysym (s[0]);
+
+ if (dead_key_state != 0)
+ k[j] = make_dead_key (k[j]);
+ }
+ }
+ else
+ {
+ UInt32 c, state = 0;
+ UInt16 code;
+
+ code = i | mods[j];
+ c = KeyTranslate (chr_data, code, &state);
+
+ /* Dead keys are only processed on key-down, so ask
+ to translate those events. When we find a dead key,
+ translating the matching key up event will give
+ us the actual dead character. */
+
+ if (state != 0)
+ {
+ UInt32 state2 = 0;
+ c = KeyTranslate (chr_data, code | 128, &state2);
+ }
+
+ /* Characters seem to be in MacRoman encoding. */
+
+ if (c != 0 && c != 0x0010)
+ {
+ k[j] = ucs2keysym (macroman2ucs (c & 255));
+
+ if (state != 0)
+ k[j] = make_dead_key (k[j]);
+ }
+ }
+ }
+
+ if (k[3] == k[2])
+ k[3] = NoSymbol;
+ if (k[2] == k[1])
+ k[2] = NoSymbol;
+ if (k[1] == k[0])
+ k[1] = NoSymbol;
+ if (k[0] == k[2] && k[1] == k[3])
+ k[2] = k[3] = NoSymbol;
+ }
+
+ /* Fix up some things that are normally missing.. */
+
+ if (HACK_MISSING)
+ {
+ for (i = 0; i < sizeof (known_keys) / sizeof (known_keys[0]); i++)
+ {
+ k = info->key_map + known_keys[i].keycode * GLYPHS_PER_KEY;
+
+ if (k[0] == NoSymbol && k[1] == NoSymbol
+ && k[2] == NoSymbol && k[3] == NoSymbol)
+ {
+ k[0] = known_keys[i].keysym;
+ }
+ }
+ }
+
+ /* And some more things. We find the right symbols for the numeric
+ keypad, but not the KP_ keysyms. So try to convert known keycodes. */
+
+ if (HACK_KEYPAD)
+ {
+ for (i = 0; i < sizeof (known_numeric_keys)
+ / sizeof (known_numeric_keys[0]); i++)
+ {
+ k = info->key_map + known_numeric_keys[i].keycode * GLYPHS_PER_KEY;
+
+ if (k[0] == known_numeric_keys[i].normal)
+ {
+ k[0] = known_numeric_keys[i].keypad;
+ }
+ }
+ }
+
+ return TRUE;
+}
--- /dev/null
+/* darwin-old-keymap.c -- ugly code we need to keep around for now
+
+ Copyright (c) 2001-2002 Torrey T. Lyons. All Rights Reserved.
+
+ The code to parse the Darwin keymap is derived from dumpkeymap.c
+ by Eric Sunshine, which includes the following copyright:
+
+ Copyright (C) 1999,2000 by Eric Sunshine <sunshine@sunshineco.com>
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. The name of the author may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
+
+#include "darwin.h"
+#include "darwin-keyboard.h"
+#include <errno.h>
+#include <sys/stat.h>
+#include <drivers/event_status_driver.h>
+#include <IOKit/hidsystem/ev_keymap.h>
+#include <architecture/byte_order.h> // For the NXSwap*
+
+#define XK_TECHNICAL // needed to get XK_Escape
+#define XK_PUBLISHING
+#include "keysym.h"
+
+static FILE *fref = NULL;
+static char *inBuffer = NULL;
+
+// FIXME: It would be nice to support some of the extra keys in XF86keysym.h,
+// at least the volume controls that now ship on every Apple keyboard.
+
+#define UK(a) NoSymbol // unknown symbol
+
+static KeySym const next_to_x[256] = {
+ NoSymbol, NoSymbol, NoSymbol, XK_KP_Enter,
+ NoSymbol, NoSymbol, NoSymbol, NoSymbol,
+ XK_BackSpace, XK_Tab, XK_Linefeed, NoSymbol,
+ NoSymbol, XK_Return, NoSymbol, NoSymbol,
+ NoSymbol, NoSymbol, NoSymbol, NoSymbol,
+ NoSymbol, NoSymbol, NoSymbol, NoSymbol,
+ NoSymbol, NoSymbol, NoSymbol, XK_Escape,
+ NoSymbol, NoSymbol, NoSymbol, NoSymbol,
+ XK_space, XK_exclam, XK_quotedbl, XK_numbersign,
+ XK_dollar, XK_percent, XK_ampersand, XK_apostrophe,
+ XK_parenleft, XK_parenright, XK_asterisk, XK_plus,
+ XK_comma, XK_minus, XK_period, XK_slash,
+ XK_0, XK_1, XK_2, XK_3,
+ XK_4, XK_5, XK_6, XK_7,
+ XK_8, XK_9, XK_colon, XK_semicolon,
+ XK_less, XK_equal, XK_greater, XK_question,
+ XK_at, XK_A, XK_B, XK_C,
+ XK_D, XK_E, XK_F, XK_G,
+ XK_H, XK_I, XK_J, XK_K,
+ XK_L, XK_M, XK_N, XK_O,
+ XK_P, XK_Q, XK_R, XK_S,
+ XK_T, XK_U, XK_V, XK_W,
+ XK_X, XK_Y, XK_Z, XK_bracketleft,
+ XK_backslash, XK_bracketright,XK_asciicircum, XK_underscore,
+ XK_grave, XK_a, XK_b, XK_c,
+ XK_d, XK_e, XK_f, XK_g,
+ XK_h, XK_i, XK_j, XK_k,
+ XK_l, XK_m, XK_n, XK_o,
+ XK_p, XK_q, XK_r, XK_s,
+ XK_t, XK_u, XK_v, XK_w,
+ XK_x, XK_y, XK_z, XK_braceleft,
+ XK_bar, XK_braceright, XK_asciitilde, XK_BackSpace,
+// 128
+ NoSymbol, XK_Agrave, XK_Aacute, XK_Acircumflex,
+ XK_Atilde, XK_Adiaeresis, XK_Aring, XK_Ccedilla,
+ XK_Egrave, XK_Eacute, XK_Ecircumflex, XK_Ediaeresis,
+ XK_Igrave, XK_Iacute, XK_Icircumflex, XK_Idiaeresis,
+// 144
+ XK_ETH, XK_Ntilde, XK_Ograve, XK_Oacute,
+ XK_Ocircumflex, XK_Otilde, XK_Odiaeresis, XK_Ugrave,
+ XK_Uacute, XK_Ucircumflex, XK_Udiaeresis, XK_Yacute,
+ XK_THORN, XK_mu, XK_multiply, XK_division,
+// 160
+ XK_copyright, XK_exclamdown, XK_cent, XK_sterling,
+ UK(fraction), XK_yen, UK(fhook), XK_section,
+ XK_currency, XK_rightsinglequotemark,
+ XK_leftdoublequotemark,
+ XK_guillemotleft,
+ XK_leftanglebracket,
+ XK_rightanglebracket,
+ UK(filigature), UK(flligature),
+// 176
+ XK_registered, XK_endash, XK_dagger, XK_doubledagger,
+ XK_periodcentered,XK_brokenbar, XK_paragraph, UK(bullet),
+ XK_singlelowquotemark,
+ XK_doublelowquotemark,
+ XK_rightdoublequotemark,
+ XK_guillemotright,
+ XK_ellipsis, UK(permille), XK_notsign, XK_questiondown,
+// 192
+ XK_onesuperior, XK_dead_grave, XK_dead_acute, XK_dead_circumflex,
+ XK_dead_tilde, XK_dead_macron, XK_dead_breve, XK_dead_abovedot,
+ XK_dead_diaeresis,
+ XK_twosuperior, XK_dead_abovering,
+ XK_dead_cedilla,
+ XK_threesuperior,
+ XK_dead_doubleacute,
+ XK_dead_ogonek, XK_dead_caron,
+// 208
+ XK_emdash, XK_plusminus, XK_onequarter, XK_onehalf,
+ XK_threequarters,
+ XK_agrave, XK_aacute, XK_acircumflex,
+ XK_atilde, XK_adiaeresis, XK_aring, XK_ccedilla,
+ XK_egrave, XK_eacute, XK_ecircumflex, XK_ediaeresis,
+// 224
+ XK_igrave, XK_AE, XK_iacute, XK_ordfeminine,
+ XK_icircumflex, XK_idiaeresis, XK_eth, XK_ntilde,
+ XK_Lstroke, XK_Ooblique, XK_OE, XK_masculine,
+ XK_ograve, XK_oacute, XK_ocircumflex, XK_otilde,
+// 240
+ XK_odiaeresis, XK_ae, XK_ugrave, XK_uacute,
+ XK_ucircumflex, XK_idotless, XK_udiaeresis, XK_ygrave,
+ XK_lstroke, XK_ooblique, XK_oe, XK_ssharp,
+ XK_thorn, XK_ydiaeresis, NoSymbol, NoSymbol,
+ };
+
+#define MIN_SYMBOL 0xAC
+static KeySym const symbol_to_x[] = {
+ XK_Left, XK_Up, XK_Right, XK_Down
+ };
+int const NUM_SYMBOL = sizeof(symbol_to_x) / sizeof(symbol_to_x[0]);
+
+#define MIN_FUNCKEY 0x20
+static KeySym const funckey_to_x[] = {
+ XK_F1, XK_F2, XK_F3, XK_F4,
+ XK_F5, XK_F6, XK_F7, XK_F8,
+ XK_F9, XK_F10, XK_F11, XK_F12,
+ XK_Insert, XK_Delete, XK_Home, XK_End,
+ XK_Page_Up, XK_Page_Down, XK_F13, XK_F14,
+ XK_F15
+ };
+int const NUM_FUNCKEY = sizeof(funckey_to_x) / sizeof(funckey_to_x[0]);
+
+typedef struct {
+ KeySym normalSym;
+ KeySym keypadSym;
+} darwinKeyPad_t;
+
+static darwinKeyPad_t const normal_to_keypad[] = {
+ { XK_0, XK_KP_0 },
+ { XK_1, XK_KP_1 },
+ { XK_2, XK_KP_2 },
+ { XK_3, XK_KP_3 },
+ { XK_4, XK_KP_4 },
+ { XK_5, XK_KP_5 },
+ { XK_6, XK_KP_6 },
+ { XK_7, XK_KP_7 },
+ { XK_8, XK_KP_8 },
+ { XK_9, XK_KP_9 },
+ { XK_equal, XK_KP_Equal },
+ { XK_asterisk, XK_KP_Multiply },
+ { XK_plus, XK_KP_Add },
+ { XK_comma, XK_KP_Separator },
+ { XK_minus, XK_KP_Subtract },
+ { XK_period, XK_KP_Decimal },
+ { XK_slash, XK_KP_Divide }
+};
+int const NUM_KEYPAD = sizeof(normal_to_keypad) / sizeof(normal_to_keypad[0]);
+
+
+//-----------------------------------------------------------------------------
+// Data Stream Object
+// Can be configured to treat embedded "numbers" as being composed of
+// either 1, 2, or 4 bytes, apiece.
+//-----------------------------------------------------------------------------
+typedef struct _DataStream
+{
+ unsigned char const *data;
+ unsigned char const *data_end;
+ short number_size; // Size in bytes of a "number" in the stream.
+} DataStream;
+
+static DataStream* new_data_stream( unsigned char const* data, int size )
+{
+ DataStream* s = (DataStream*)xalloc( sizeof(DataStream) );
+ s->data = data;
+ s->data_end = data + size;
+ s->number_size = 1; // Default to byte-sized numbers.
+ return s;
+}
+
+static void destroy_data_stream( DataStream* s )
+{
+ xfree(s);
+}
+
+static unsigned char get_byte( DataStream* s )
+{
+ assert(s->data + 1 <= s->data_end);
+ return *s->data++;
+}
+
+static short get_word( DataStream* s )
+{
+ short hi, lo;
+ assert(s->data + 2 <= s->data_end);
+ hi = *s->data++;
+ lo = *s->data++;
+ return ((hi << 8) | lo);
+}
+
+static int get_dword( DataStream* s )
+{
+ int b1, b2, b3, b4;
+ assert(s->data + 4 <= s->data_end);
+ b4 = *s->data++;
+ b3 = *s->data++;
+ b2 = *s->data++;
+ b1 = *s->data++;
+ return ((b4 << 24) | (b3 << 16) | (b2 << 8) | b1);
+}
+
+static int get_number( DataStream* s )
+{
+ switch (s->number_size) {
+ case 4: return get_dword(s);
+ case 2: return get_word(s);
+ default: return get_byte(s);
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Utility functions to help parse Darwin keymap
+//-----------------------------------------------------------------------------
+
+/*
+ * bits_set
+ * Calculate number of bits set in the modifier mask.
+ */
+static short bits_set( short mask )
+{
+ short n = 0;
+
+ for ( ; mask != 0; mask >>= 1)
+ if ((mask & 0x01) != 0)
+ n++;
+ return n;
+}
+
+/*
+ * parse_next_char_code
+ * Read the next character code from the Darwin keymapping
+ * and write it to the X keymap.
+ */
+static void parse_next_char_code(
+ DataStream *s,
+ KeySym *k )
+{
+ const short charSet = get_number(s);
+ const short charCode = get_number(s);
+
+ if (charSet == 0) { // ascii character
+ if (charCode >= 0 && charCode < 256)
+ *k = next_to_x[charCode];
+ } else if (charSet == 0x01) { // symbol character
+ if (charCode >= MIN_SYMBOL &&
+ charCode <= MIN_SYMBOL + NUM_SYMBOL)
+ *k = symbol_to_x[charCode - MIN_SYMBOL];
+ } else if (charSet == 0xFE) { // function key
+ if (charCode >= MIN_FUNCKEY &&
+ charCode <= MIN_FUNCKEY + NUM_FUNCKEY)
+ *k = funckey_to_x[charCode - MIN_FUNCKEY];
+ }
+}
+
+/*
+ * DarwinReadKeymapFile
+ * Read the appropriate keymapping from a keymapping file.
+ */
+static Bool _DarwinReadKeymapFile(
+ NXKeyMapping *keyMap)
+{
+ struct stat st;
+ NXEventSystemDevice info[20];
+ int interface = 0, handler_id = 0;
+ int map_interface, map_handler_id, map_size = 0;
+ unsigned int i, size;
+ int *bufferEnd;
+ union km_tag {
+ int *intP;
+ char *charP;
+ } km;
+ char *filename;
+
+ filename = DarwinFindLibraryFile (darwinKeymapFile, "Keyboards");
+ if (filename == NULL) {
+ FatalError("Could not find keymapping file %s.\n", darwinKeymapFile);
+ return FALSE;
+ }
+
+ fref = fopen( filename, "rb" );
+ xfree (filename);
+
+ if (fref == NULL) {
+ ErrorF("Unable to open keymapping file '%s' (errno %d).\n",
+ darwinKeymapFile, errno);
+ return FALSE;
+ }
+ if (fstat(fileno(fref), &st) == -1) {
+ ErrorF("Could not stat keymapping file '%s' (errno %d).\n",
+ darwinKeymapFile, errno);
+ return FALSE;
+ }
+
+ // check to make sure we don't crash later
+ if (st.st_size <= 16*sizeof(int)) {
+ ErrorF("Keymapping file '%s' is invalid (too small).\n",
+ darwinKeymapFile);
+ return FALSE;
+ }
+
+ inBuffer = (char*) xalloc( st.st_size );
+ bufferEnd = (int *) (inBuffer + st.st_size);
+ if (fread(inBuffer, st.st_size, 1, fref) != 1) {
+ ErrorF("Could not read %qd bytes from keymapping file '%s' (errno %d).\n",
+ st.st_size, darwinKeymapFile, errno);
+ return FALSE;
+ }
+
+ if (strncmp( inBuffer, "KYM1", 4 ) == 0) {
+ // Magic number OK.
+ } else if (strncmp( inBuffer, "KYMP", 4 ) == 0) {
+ ErrorF("Keymapping file '%s' is intended for use with the original NeXT keyboards and cannot be used by XDarwin.\n", darwinKeymapFile);
+ return FALSE;
+ } else {
+ ErrorF("Keymapping file '%s' has a bad magic number and cannot be used by XDarwin.\n", darwinKeymapFile);
+ return FALSE;
+ }
+
+ // find the keyboard interface and handler id
+ {NXEventHandle hid;
+ NXEventSystemInfoType info_type;
+
+ size = sizeof( info ) / sizeof( int );
+ hid = NXOpenEventStatus ();
+ info_type = NXEventSystemInfo (hid, NX_EVS_DEVICE_INFO,
+ (int *) info, &size);
+ NXCloseEventStatus (hid);
+ if (!info_type) {
+ ErrorF("Error reading event status driver info.\n");
+ return FALSE;
+ }}
+
+ size = size * sizeof( int ) / sizeof( info[0] );
+ for( i = 0; i < size; i++) {
+ if (info[i].dev_type == NX_EVS_DEVICE_TYPE_KEYBOARD) {
+ Bool hasInterface = FALSE;
+ Bool hasMatch = FALSE;
+
+ interface = info[i].interface;
+ handler_id = info[i].id;
+
+ // Find an appropriate keymapping:
+ // The first time we try to match both interface and handler_id.
+ // If we can't match both, we take the first match for interface.
+
+ do {
+ km.charP = inBuffer;
+ km.intP++;
+ while (km.intP+3 < bufferEnd) {
+ map_interface = NXSwapBigIntToHost(*(km.intP++));
+ map_handler_id = NXSwapBigIntToHost(*(km.intP++));
+ map_size = NXSwapBigIntToHost(*(km.intP++));
+ if (map_interface == interface) {
+ if (map_handler_id == handler_id || hasInterface) {
+ hasMatch = TRUE;
+ break;
+ } else {
+ hasInterface = TRUE;
+ }
+ }
+ km.charP += map_size;
+ }
+ } while (hasInterface && !hasMatch);
+
+ if (hasMatch) {
+ // fill in NXKeyMapping structure
+ keyMap->size = map_size;
+ keyMap->mapping = (char*) xalloc(map_size);
+ memcpy(keyMap->mapping, km.charP, map_size);
+ return TRUE;
+ }
+ } // if dev_id == keyboard device
+ } // foreach info struct
+
+ // The keymapping file didn't match any of the info structs
+ // returned by NXEventSystemInfo.
+ ErrorF("Keymapping file '%s' did not contain appropriate keyboard interface.\n", darwinKeymapFile);
+ return FALSE;
+}
+
+static Bool DarwinReadKeymapFile(NXKeyMapping *keyMap)
+{
+ Bool ret;
+
+ ret = _DarwinReadKeymapFile (keyMap);
+
+ if (inBuffer != NULL)
+ xfree (inBuffer);
+ if (fref != NULL)
+ fclose (fref);
+
+ return ret;
+}
+
+int DarwinParseKeymapFile (darwin_keyboard_info *info)
+{
+ short numMods, numKeys, numPadKeys = 0;
+ NXKeyMapping keyMap;
+ DataStream *keyMapStream;
+ unsigned char const *numPadStart = 0;
+ Bool haveKeymap;
+ int i;
+ KeySym *k;
+
+ if (darwinKeymapFile == NULL)
+ return FALSE;
+
+ haveKeymap = DarwinReadKeymapFile(&keyMap);
+ if (!haveKeymap) {
+ ErrorF("Reverting to system keymapping.\n");
+ return FALSE;
+ }
+
+ keyMapStream = new_data_stream( (unsigned char const*)keyMap.mapping,
+ keyMap.size );
+
+ // check the type of map
+ if (get_word(keyMapStream)) {
+ keyMapStream->number_size = 2;
+ ErrorF("Current 16-bit keymapping may not be interpreted correctly.\n");
+ }
+
+ // Compute the modifier map and
+ // insert X modifier KeySyms into keyboard map.
+ // Store modifier keycodes in modifierKeycodes.
+ numMods = get_number(keyMapStream);
+ while (numMods-- > 0) {
+ int left = 1; // first keycode is left
+ short const charCode = get_number(keyMapStream);
+ short numKeyCodes = get_number(keyMapStream);
+
+ // This is just a marker, not a real modifier.
+ // Store numeric keypad keys for later.
+ if (charCode == NX_MODIFIERKEY_NUMERICPAD) {
+ numPadStart = keyMapStream->data;
+ numPadKeys = numKeyCodes;
+ }
+
+ while (numKeyCodes-- > 0) {
+ const short keyCode = get_number(keyMapStream);
+ if (charCode != NX_MODIFIERKEY_NUMERICPAD) {
+ switch (charCode) {
+ case NX_MODIFIERKEY_ALPHALOCK:
+ info->key_map[keyCode * GLYPHS_PER_KEY] = XK_Caps_Lock;
+ break;
+ case NX_MODIFIERKEY_SHIFT:
+ info->key_map[keyCode * GLYPHS_PER_KEY] =
+ (left ? XK_Shift_L : XK_Shift_R);
+ break;
+ case NX_MODIFIERKEY_CONTROL:
+ info->key_map[keyCode * GLYPHS_PER_KEY] =
+ (left ? XK_Control_L : XK_Control_R);
+ break;
+ case NX_MODIFIERKEY_ALTERNATE:
+ info->key_map[keyCode * GLYPHS_PER_KEY] =
+ (left ? XK_Alt_L : XK_Alt_R);
+ break;
+ case NX_MODIFIERKEY_COMMAND:
+ info->key_map[keyCode * GLYPHS_PER_KEY] =
+ (left ? XK_Meta_L : XK_Meta_R);
+ break;
+ case NX_MODIFIERKEY_SECONDARYFN:
+ info->key_map[keyCode * GLYPHS_PER_KEY] =
+ (left ? XK_Control_L : XK_Control_R);
+ break;
+ case NX_MODIFIERKEY_HELP:
+ info->key_map[keyCode * GLYPHS_PER_KEY] = XK_Help;
+ break;
+ }
+ }
+ left = 0;
+ }
+ }
+
+ // Convert the Darwin keyboard map to an X keyboard map.
+ // A key can have a different character code for each combination of
+ // modifiers. We currently ignore all modifier combinations except
+ // those with Shift, AlphaLock, and Alt.
+ numKeys = get_number(keyMapStream);
+ for (i = 0, k = info->key_map; i < numKeys; i++, k += GLYPHS_PER_KEY) {
+ short const charGenMask = get_number(keyMapStream);
+ if (charGenMask != 0xFF) { // is key bound?
+ short numKeyCodes = 1 << bits_set(charGenMask);
+
+ // Record unmodified case
+ parse_next_char_code( keyMapStream, k );
+ numKeyCodes--;
+
+ // If AlphaLock and Shift modifiers produce different codes,
+ // we record the Shift case since X handles AlphaLock.
+ if (charGenMask & 0x01) { // AlphaLock
+ parse_next_char_code( keyMapStream, k+1 );
+ numKeyCodes--;
+ }
+
+ if (charGenMask & 0x02) { // Shift
+ parse_next_char_code( keyMapStream, k+1 );
+ numKeyCodes--;
+
+ if (charGenMask & 0x01) { // Shift-AlphaLock
+ get_number(keyMapStream); get_number(keyMapStream);
+ numKeyCodes--;
+ }
+ }
+
+ // Skip the Control cases
+ if (charGenMask & 0x04) { // Control
+ get_number(keyMapStream); get_number(keyMapStream);
+ numKeyCodes--;
+
+ if (charGenMask & 0x01) { // Control-AlphaLock
+ get_number(keyMapStream); get_number(keyMapStream);
+ numKeyCodes--;
+ }
+
+ if (charGenMask & 0x02) { // Control-Shift
+ get_number(keyMapStream); get_number(keyMapStream);
+ numKeyCodes--;
+
+ if (charGenMask & 0x01) { // Shift-Control-AlphaLock
+ get_number(keyMapStream); get_number(keyMapStream);
+ numKeyCodes--;
+ }
+ }
+ }
+
+ // Process Alt cases
+ if (charGenMask & 0x08) { // Alt
+ parse_next_char_code( keyMapStream, k+2 );
+ numKeyCodes--;
+
+ if (charGenMask & 0x01) { // Alt-AlphaLock
+ parse_next_char_code( keyMapStream, k+3 );
+ numKeyCodes--;
+ }
+
+ if (charGenMask & 0x02) { // Alt-Shift
+ parse_next_char_code( keyMapStream, k+3 );
+ numKeyCodes--;
+
+ if (charGenMask & 0x01) { // Alt-Shift-AlphaLock
+ get_number(keyMapStream); get_number(keyMapStream);
+ numKeyCodes--;
+ }
+ }
+ }
+
+ while (numKeyCodes-- > 0) {
+ get_number(keyMapStream); get_number(keyMapStream);
+ }
+
+ if (k[3] == k[2]) k[3] = NoSymbol;
+ if (k[2] == k[1]) k[2] = NoSymbol;
+ if (k[1] == k[0]) k[1] = NoSymbol;
+ if (k[0] == k[2] && k[1] == k[3]) k[2] = k[3] = NoSymbol;
+ }
+ }
+
+ // Now we have to go back through the list of keycodes that are on the
+ // numeric keypad and update the X keymap.
+ keyMapStream->data = numPadStart;
+ while(numPadKeys-- > 0) {
+ const short keyCode = get_number(keyMapStream);
+ k = &info->key_map[keyCode * GLYPHS_PER_KEY];
+ for (i = 0; i < NUM_KEYPAD; i++) {
+ if (*k == normal_to_keypad[i].normalSym) {
+ k[0] = normal_to_keypad[i].keypadSym;
+ break;
+ }
+ }
+ }
+
+ // free Darwin keyboard map
+ destroy_data_stream( keyMapStream );
+ xfree( keyMap.mapping );
+
+ return TRUE;
+}
--- /dev/null
+/**************************************************************
+ *
+ * Shared code for the Darwin X Server
+ * running with Quartz or the IOKit
+ *
+ **************************************************************/
+/*
+ * Copyright (c) 2001-2002 Torrey T. Lyons. All Rights Reserved.
+ * Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name(s) of the above copyright
+ * holders shall not be used in advertising or otherwise to promote the sale,
+ * use or other dealings in this Software without prior written authorization.
+ */
+/* $XFree86: xc/programs/Xserver/hw/darwin/darwin.c,v 1.45 2002/03/28 02:21:08 torrey Exp $ */
+
+#include <CoreGraphics/CoreGraphics.h>
+
+#include "X.h"
+#include "Xproto.h"
+#include "os.h"
+#include "servermd.h"
+#include "inputstr.h"
+#include "scrnintstr.h"
+#include "mibstore.h" // mi backing store implementation
+#include "mipointer.h" // mi software cursor
+#include "micmap.h" // mi colormap code
+#include "fb.h" // fb framebuffer code
+#include "site.h"
+#include "globals.h"
+#include "xf86Version.h"
+#include "dix.h"
+#include "dri-surface.h"
+#define _APPLEDRI_SERVER_
+#include "appledristr.h"
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/syslimits.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <dirent.h>
+
+#define NO_CFPLUGIN
+#include <IOKit/IOKitLib.h>
+#include <IOKit/hidsystem/IOHIDLib.h>
+#include <IOKit/hidsystem/ev_keymap.h>
+
+#include "darwin.h"
+#include "quartz.h"
+#include "rootless-common.h"
+#include "pseudoramiX.h"
+#include "X11Application.h"
+
+/* Fake button press/release for scroll wheel move. */
+#define SCROLLWHEELUPFAKE 4
+#define SCROLLWHEELDOWNFAKE 5
+
+/* X server shared global variables */
+int darwinScreensFound = 0;
+int darwinScreenIndex = 0;
+int darwinFakeButtons = 1;
+Bool darwinSwapAltMeta = FALSE;
+
+/* location of X11's (0,0) point in global screen coordinates */
+int darwinMainScreenX = 0;
+int darwinMainScreenY = 0;
+
+/* parameters read from the command line or user preferences */
+char *darwinKeymapFile;
+Bool darwinSyncKeymap = TRUE;
+
+/* modifier masks for faking mouse buttons */
+static int darwinFakeMouse2Mask = Mod1Mask; /* option */
+static int darwinFakeMouse3Mask = Mod2Mask; /* command */
+
+static DeviceIntPtr darwinPointer;
+static DeviceIntPtr darwinKeyboard;
+
+/* Track our view of the keyboard state. Everything we sent to dix will
+ be represented here until released. */
+static CARD8 keysDown[DOWN_LENGTH];
+static int lockMods;
+
+#define SetBit(ptr,bit) \
+ do {((BYTE *) ptr)[(bit) >> 3] |= (1 << ((bit) & 7));} while (0)
+
+#define ClearBit(ptr,bit) \
+ do {((BYTE *) ptr)[(bit) >> 3] &= ~(1 << ((bit) & 7));} while (0)
+
+/* Common pixmap formats */
+static PixmapFormatRec formats[] = {
+ { 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(formats)/sizeof(formats[0]);
+
+#ifndef OSNAME
+#define OSNAME " Mac OS X"
+#endif
+#ifndef OSVENDOR
+#define OSVENDOR " Apple"
+#endif
+#ifndef PRE_RELEASE
+#define PRE_RELEASE XF86_VERSION_SNAP
+#endif
+
+extern void AppleDRIExtensionInit(void);
+extern void AppleWMExtensionInit(void);
+
+static void
+DarwinPrintBanner (void)
+{
+ ErrorF("\nXFree86 Version %d.%d.%d", XF86_VERSION_MAJOR, XF86_VERSION_MINOR,
+ XF86_VERSION_PATCH);
+#if XF86_VERSION_SNAP > 0
+ ErrorF(".%d", XF86_VERSION_SNAP);
+#endif
+
+#if XF86_VERSION_SNAP >= 900
+ ErrorF(" (%d.%d.0 RC %d)", XF86_VERSION_MAJOR, XF86_VERSION_MINOR + 1,
+ XF86_VERSION_SNAP - 900);
+#endif
+
+#ifdef XF86_CUSTOM_VERSION
+ ErrorF(" (%s)", XF86_CUSTOM_VERSION);
+#endif
+ ErrorF(" / X Window System\n");
+ ErrorF("(protocol Version %d, revision %d, vendor release %d)\n",
+ X_PROTOCOL, X_PROTOCOL_REVISION, VENDOR_RELEASE );
+}
+
+/* X screensaver support. Not implemented. */
+static Bool
+DarwinSaveScreen (ScreenPtr pScreen, int on)
+{
+ return TRUE;
+}
+
+/* This is a callback from dix during AddScreen() from InitOutput().
+ Initialize the screen and communicate information about it back to dix. */
+static Bool
+DarwinAddScreen (int index, ScreenPtr pScreen, int argc, char **argv)
+{
+ int i, dpi;
+ static int foundIndex = 0;
+ Bool ret;
+ VisualPtr visual;
+ DarwinFramebufferPtr dfb;
+
+ /* reset index of found screens for each server generation */
+ if (index == 0)
+ foundIndex = 0;
+
+ /* allocate space for private per screen storage */
+ dfb = xalloc (sizeof (DarwinFramebufferRec));
+ SCREEN_PRIV(pScreen) = dfb;
+
+ /* setup hardware/mode specific details */
+ ret = QuartzAddScreen (foundIndex, pScreen);
+ foundIndex++;
+ if (!ret)
+ return FALSE;
+
+ /* reset the visual list */
+ miClearVisualTypes();
+
+ /* setup a single visual appropriate for our pixel type. Note: we use
+ TrueColor, not DirectColor */
+ if (dfb->componentCount != 1)
+ {
+ if (!miSetVisualTypes (dfb->colorBitsPerPixel, TrueColorMask,
+ dfb->bitsPerComponent, TrueColor))
+ return FALSE;
+#ifdef ENABLE_PSEUDOCOLOR
+ /* FIXME: currently we can't handle pseudocolor windows
+ inside truecolor top-level windows, so disable this. */
+ if (!miSetVisualTypes (8, PseudoColorMask, 8, PseudoColor))
+ return FALSE;
+#endif
+ }
+ else
+ {
+ if (!miSetVisualTypes (8, PseudoColorMask, 8, PseudoColor))
+ return FALSE;
+ }
+
+ /* create the common 8 bit PseudoColor visual; do this last to prevent
+ it becoming the root visual. */
+
+ miSetPixmapDepths();
+
+ /* Machine independent screen init */
+ if (monitorResolution)
+ dpi = monitorResolution;
+ else
+ dpi = 75;
+
+ /* initialize fb */
+ if (!fbScreenInit (pScreen, dfb->framebuffer, dfb->width,
+ dfb->height, dpi, dpi,
+ dfb->pitch/(dfb->bitsPerPixel/8), dfb->bitsPerPixel))
+ {
+ return FALSE;
+ }
+
+ /* set the RGB order correctly for TrueColor */
+ if (dfb->bitsPerPixel > 8)
+ {
+ int bitsPerRGB = dfb->bitsPerComponent;
+
+ for (i = 0, visual = pScreen->visuals;
+ i < pScreen->numVisuals; i++, visual++)
+ {
+ if (visual->class == TrueColor) {
+ visual->offsetRed = bitsPerRGB * 2;
+ visual->offsetGreen = bitsPerRGB;
+ visual->offsetBlue = 0;
+ visual->redMask = ((1<<bitsPerRGB)-1) << visual->offsetRed;
+ visual->greenMask = ((1<<bitsPerRGB)-1) << visual->offsetGreen;
+ visual->blueMask = ((1<<bitsPerRGB)-1) << visual->offsetBlue;
+ }
+ }
+ }
+
+#ifdef RENDER
+ if (! fbPictureInit (pScreen, 0, 0))
+ return FALSE;
+#endif
+
+#ifdef MITSHM
+ ShmRegisterFbFuncs (pScreen);
+#endif
+
+ /* this must be initialized (why doesn't X have a default?) */
+ pScreen->SaveScreen = DarwinSaveScreen;
+
+ /* finish mode dependent screen setup including cursor support */
+ if (!QuartzSetupScreen (index, pScreen))
+ return FALSE;
+
+ /* create and install the default colormap and set black / white pixels */
+ if (!miCreateDefColormap (pScreen))
+ return FALSE;
+
+ dixScreenOrigins[index].x = dfb->x;
+ dixScreenOrigins[index].y = dfb->y;
+
+ ErrorF("Screen %d added: %dx%d @ (%d,%d)\n",
+ index, dfb->width, dfb->height, dfb->x, dfb->y);
+
+ return TRUE;
+}
+
+/* Search for a file in the standard Library paths, which are (in order):
+
+ ~/Library/ user specific
+ /Library/ host specific
+ /Network/Library/ LAN specific
+ /System/Library/ OS specific
+
+ A sub-path can be specified to search in below the various Library
+ directories. Returns a new character string (owned by the caller)
+ containing the full path to the first file found. */
+
+/* Library search paths */
+static const char *libraryPathList[] = {
+ "",
+ "/Network",
+ "/System",
+ NULL
+};
+
+char *
+DarwinFindLibraryFile (const char *file, const char *pathext)
+{
+ char *home;
+ char *fullPath;
+ int i = 0;
+
+ // Return the file name as is if it is already a fully qualified path.
+ if (!access(file, F_OK)) {
+ fullPath = xalloc(strlen(file)+1);
+ strcpy(fullPath, file);
+ return fullPath;
+ }
+
+ fullPath = xalloc(PATH_MAX);
+
+ home = getenv("HOME");
+ if (home) {
+ snprintf(fullPath, PATH_MAX, "%s/Library/%s/%s", home, pathext, file);
+ if (!access(fullPath, F_OK))
+ return fullPath;
+ }
+
+ while (libraryPathList[i]) {
+ snprintf(fullPath, PATH_MAX, "%s/Library/%s/%s", libraryPathList[i++],
+ pathext, file);
+ if (!access(fullPath, F_OK))
+ return fullPath;
+ }
+
+ xfree(fullPath);
+ return NULL;
+}
+
+/* Press or release the given key, specified by NX keycode. xe must already
+ have event time and mouse location filled in. pressed is KeyPress or
+ KeyRelease. keycode is NX keycode without MIN_KEYCODE adjustment. */
+static inline void
+DarwinPressKeycode (xEvent *xe, int pressed, int keycode)
+{
+ if (pressed == KeyRelease && !BitIsOn (keysDown, keycode + MIN_KEYCODE))
+ {
+ /* Don't release keys that aren't pressed. It generates extra
+ KeyPress events instead of just discarding them. */
+
+ return;
+ }
+
+ if (pressed == KeyPress)
+ SetBit (keysDown, keycode + MIN_KEYCODE);
+ else
+ ClearBit (keysDown, keycode + MIN_KEYCODE);
+
+ xe->u.u.type = pressed;
+ xe->u.u.detail = keycode + MIN_KEYCODE;
+ (darwinKeyboard->public.processInputProc) (xe, darwinKeyboard, 1);
+}
+
+/* Ensure that X's idea of what modifiers are down matches the real
+ window server's. Do this by looking at what keys we previously sent
+ X and deciding if they need to be released/toggled yet to make FLAGS
+ become X's current modifier state. */
+static void
+DarwinUpdateModifiers (xEvent xe, unsigned int flags)
+{
+ static const struct {int mask; int nxkey;} pairs[] = {
+ {ShiftMask, NX_MODIFIERKEY_SHIFT},
+ {ControlMask, NX_MODIFIERKEY_CONTROL},
+ {Mod1Mask, NX_MODIFIERKEY_ALTERNATE},
+ {Mod2Mask, NX_MODIFIERKEY_COMMAND},
+ {Mod3Mask, NX_MODIFIERKEY_SECONDARYFN}
+ };
+
+ int i, keycode;
+
+ for (i = 0; i < (int) (sizeof (pairs) / sizeof (pairs[0])); i++)
+ {
+ keycode = DarwinModifierNXKeyToNXKeycode (pairs[i].nxkey, 0);
+
+ if (keycode == 0)
+ continue;
+
+ /* For each known modifier, sync up the state of the key X thinks
+ it's bound to and the real value of the flag. */
+
+ if ((flags & pairs[i].mask)
+ && !BitIsOn (keysDown, keycode + MIN_KEYCODE))
+ {
+ DarwinPressKeycode (&xe, KeyPress, keycode);
+ }
+ else if (!(flags & pairs[i].mask)
+ && BitIsOn (keysDown, keycode + MIN_KEYCODE))
+ {
+ DarwinPressKeycode (&xe, KeyRelease, keycode);
+ }
+ }
+
+ /* Do the same for Lock, but need both press and release to toggle it. */
+
+ if ((flags ^ lockMods) & LockMask)
+ {
+ keycode = DarwinModifierNXKeyToNXKeycode (NX_MODIFIERKEY_ALPHALOCK, 0);
+
+ if (keycode != 0)
+ {
+ DarwinPressKeycode (&xe, KeyPress, keycode);
+ DarwinPressKeycode (&xe, KeyRelease, keycode);
+
+ lockMods ^= LockMask;
+ }
+ }
+}
+
+/* Release all non-modifier keys that we think are currently pressed.
+ Usually this is done when X becomes inactive to avoid leaving keys
+ stuck down when we become active again. Modifiers are handled separately
+ in the function above. */
+static void
+DarwinReleaseKeys (void)
+{
+ KeyClassPtr keyc = darwinKeyboard->key;
+ xEvent xe;
+ int i, x, y;
+
+ memset (&xe, 0, sizeof (xe));
+ xe.u.keyButtonPointer.time = GetTimeInMillis ();
+ xe.u.keyButtonPointer.state = darwinKeyboard->key->state;
+ GetSpritePosition (&x, &y);
+ xe.u.keyButtonPointer.rootX = x;
+ xe.u.keyButtonPointer.rootY = y;
+
+ for (i = 0; i < DOWN_LENGTH * 8; i++)
+ {
+ if (!keyc->modifierMap[i] && BitIsOn (keysDown, i))
+ DarwinPressKeycode (&xe, KeyRelease, i - MIN_KEYCODE);
+ }
+}
+
+static int
+parseModifierString (const char *str)
+{
+ if (strcasecmp (str, "shift") == 0)
+ return ShiftMask;
+ else if (strcasecmp (str, "control") == 0)
+ return ControlMask;
+ else if (strcasecmp (str, "option") == 0)
+ return Mod1Mask;
+ else if (strcasecmp (str, "command") == 0)
+ return Mod2Mask;
+ else if (strcasecmp (str, "fn") == 0)
+ return Mod3Mask;
+ else
+ return 0;
+}
+
+/* Parse a list of modifier names and return a corresponding modifier mask */
+static int
+DarwinParseModifierList (const char *constmodifiers)
+{
+ int result, mask;
+ char *modifiers, *modifier, *p;
+
+ if (constmodifiers == NULL
+ || strlen (constmodifiers) == 0
+ || strcasecmp (constmodifiers, "none") == 0)
+ {
+ return 0;
+ }
+
+ modifiers = strdup (constmodifiers);
+ p = modifiers;
+ result = 0;
+
+ while (p != NULL)
+ {
+ modifier = strsep (&p, " ,+&|/"); /* allow lots of separators */
+ mask = parseModifierString (modifier);
+ if (mask != 0)
+ result |= mask;
+ else
+ ErrorF ("fakebuttons: Unknown modifier \"%s\"\n", modifier);
+ }
+
+ free (modifiers);
+ return result;
+}
+
+void
+DarwinSetFakeButtons (const char *mod2, const char *mod3)
+{
+ if (mod2 != NULL)
+ darwinFakeMouse2Mask = DarwinParseModifierList (mod2);
+ if (mod3 != NULL)
+ darwinFakeMouse3Mask = DarwinParseModifierList (mod3);
+}
+
+/* Read and process events from the event pipe until it is empty. */
+void
+ProcessInputEvents (void)
+{
+ static int here_before = 0;
+
+ /* last known modifier state */
+ static unsigned int current_flags = 0;
+
+ /* button number and modifier mask of currently pressed fake button */
+ static int fake_button;
+ static unsigned int fake_button_mask, fake_button_modifier;
+
+ xEvent xe;
+
+ if (!here_before)
+ {
+ X11ApplicationServerReady ();
+ here_before = TRUE;
+ }
+
+ while (DarwinDequeueEvent (&xe))
+ {
+ unsigned int real_state;
+
+ real_state = xe.u.keyButtonPointer.state;
+ xe.u.keyButtonPointer.state |= fake_button_modifier;
+
+ /* Filter event for faked mouse button presses. */
+ if (darwinFakeButtons)
+ {
+ switch (xe.u.u.type)
+ {
+ case ButtonPress:
+ if (xe.u.u.detail != 1)
+ break;
+ if ((xe.u.keyButtonPointer.state & darwinFakeMouse2Mask)
+ == darwinFakeMouse2Mask)
+ {
+ fake_button = 2;
+ fake_button_modifier = Button2Mask;
+ fake_button_mask = darwinFakeMouse2Mask;
+ xe.u.u.detail = 2;
+ }
+ else if ((xe.u.keyButtonPointer.state & darwinFakeMouse3Mask)
+ == darwinFakeMouse3Mask)
+ {
+ fake_button = 3;
+ fake_button_modifier = Button3Mask;
+ fake_button_mask = darwinFakeMouse3Mask;
+ xe.u.u.detail = 3;
+ }
+ break;
+
+ case ButtonRelease:
+ if (fake_button != 0 && xe.u.u.detail == 1)
+ xe.u.u.detail = fake_button;
+ break;
+ }
+ }
+
+ xe.u.keyButtonPointer.state &= ~fake_button_mask;
+
+ switch (xe.u.u.type)
+ {
+ case 0: /* flags-changed */
+ case KeyPress:
+ if (current_flags == 0
+ && darwinSyncKeymap && darwinKeymapFile == NULL)
+ {
+ /* See if keymap has changed. */
+
+ static unsigned int last_seed;
+ unsigned int this_seed;
+
+ this_seed = DarwinSystemKeymapSeed ();
+ if (this_seed != last_seed)
+ {
+ last_seed = this_seed;
+ DarwinKeyboardReload (darwinKeyboard);
+ }
+ }
+ /* fall through */
+
+ case KeyRelease:
+ case ButtonPress:
+ case ButtonRelease:
+ case MotionNotify:
+
+ /* Initialize time field. */
+
+ xe.u.keyButtonPointer.time = GetTimeInMillis ();
+
+ /* Update X's idea of what modifiers are set. */
+
+ if (xe.u.keyButtonPointer.state != 0xffff
+ && current_flags != xe.u.keyButtonPointer.state)
+ {
+ current_flags = xe.u.keyButtonPointer.state;
+ DarwinUpdateModifiers (xe, current_flags);
+ }
+ }
+
+ switch (xe.u.u.type)
+ {
+ case 0:
+ break;
+
+ case MotionNotify:
+ if (!quartzServerVisible)
+ {
+ xp_window_id wid;
+
+ /* Sigh. Need to check that we're really over one of
+ our windows. (We need to receive pointer events while
+ not in the foreground, and the only way to do that
+ right now is to ask for _all_ pointer events..) */
+
+ wid = 0;
+ xp_find_window (xe.u.keyButtonPointer.rootX,
+ xe.u.keyButtonPointer.rootY, 0, &wid);
+ if (wid == 0)
+ break;
+ }
+
+ /* Shift from global screen coordinates to coordinates
+ relative to the origin of the current screen. */
+
+ xe.u.keyButtonPointer.rootX -= darwinMainScreenX -
+ dixScreenOrigins[miPointerCurrentScreen()->myNum].x;
+ xe.u.keyButtonPointer.rootY -= darwinMainScreenY -
+ dixScreenOrigins[miPointerCurrentScreen()->myNum].y;
+
+ miPointerAbsoluteCursor (xe.u.keyButtonPointer.rootX,
+ xe.u.keyButtonPointer.rootY,
+ xe.u.keyButtonPointer.time);
+ break;
+
+ case ButtonPress:
+ case ButtonRelease:
+ darwinPointer->public.processInputProc (&xe, darwinPointer, 1);
+ break;
+
+ case KeyPress:
+ case KeyRelease:
+ DarwinPressKeycode (&xe, xe.u.u.type, xe.u.u.detail);
+ break;
+
+ case ClientMessage:
+ /* Update server's current time, since we may generate
+ events, and it's nice if the timestamps are correct. */
+ currentTime.milliseconds = GetTimeInMillis ();
+
+ switch (xe.u.clientMessage.u.l.type)
+ {
+ case kXdarwinQuit:
+ GiveUp (0);
+ break;
+
+ case kXquartzDeactivate:
+ DarwinReleaseKeys ();
+ /* fall through */
+
+ default:
+ if (xe.u.clientMessage.u.l.type >= kXquartzFirstEvent
+ && xe.u.clientMessage.u.l.type <= kXquartzLastEvent)
+ {
+ QuartzClientMessage (&xe);
+ }
+ else
+ {
+ ErrorF ("Unknown application defined event: %d.\n",
+ xe.u.clientMessage.u.l.longs0);
+ }
+ break;
+ }
+ break;
+
+ default:
+ ErrorF("Unknown event caught: %d\n", xe.u.u.type);
+ break;
+ }
+
+ /* Filter event for faked mouse button releases. */
+ if (fake_button != 0 && xe.u.u.type == ButtonRelease)
+ {
+ current_flags |= (real_state & fake_button_mask);
+ DarwinUpdateModifiers (xe, current_flags);
+
+ fake_button = 0;
+ fake_button_modifier = 0;
+ fake_button_mask = 0;
+ }
+ }
+
+ miPointerUpdate ();
+}
+
+void
+DarwinEnqueuePointerEvent (xEvent *xe)
+{
+ darwinPointer->public.processInputProc (xe, darwinPointer, 1);
+}
+
+/* Register the keyboard and mouse devices */
+void
+InitInput (int argc, char **argv)
+{
+ DarwinInputInit ();
+
+ darwinPointer = AddInputDevice(DarwinMouseProc, TRUE);
+ RegisterPointerDevice( darwinPointer );
+
+ darwinKeyboard = AddInputDevice(DarwinKeybdProc, TRUE);
+ RegisterKeyboardDevice( darwinKeyboard );
+}
+
+void
+DarwinAdjustScreenOrigins (ScreenInfo *pScreenInfo)
+{
+ int i, left, top;
+
+ /* Shift all screens so the X11 (0, 0) coordinate is at the top
+ left of the global screen coordinates.
+
+ Screens can be arranged so the top left isn't on any screen, so
+ instead use the top left of the leftmost screen as (0,0). This
+ may mean some screen space is in -y, but it's better that (0,0)
+ be onscreen, or else default xterms disappear. It's better that
+ -y be used than -x, because when popup menus are forced
+ "onscreen" by dumb window managers like twm, they'll shift the
+ menus down instead of left, which still looks funny but is an
+ easier target to hit. */
+
+ left = dixScreenOrigins[0].x;
+ top = dixScreenOrigins[0].y;
+
+ /* Find leftmost screen. If there's a tie, take the topmost of the two. */
+ for (i = 1; i < pScreenInfo->numScreens; i++) {
+ if (dixScreenOrigins[i].x < left ||
+ (dixScreenOrigins[i].x == left &&
+ dixScreenOrigins[i].y < top))
+ {
+ left = dixScreenOrigins[i].x;
+ top = dixScreenOrigins[i].y;
+ }
+ }
+
+ darwinMainScreenX = left;
+ darwinMainScreenY = top;
+
+ /* Shift all screens so that there is a screen whose top left
+ is at X11 (0,0) and at global screen coordinate
+ (darwinMainScreenX, darwinMainScreenY). */
+
+ if (darwinMainScreenX != 0 || darwinMainScreenY != 0) {
+ for (i = 0; i < pScreenInfo->numScreens; i++) {
+ dixScreenOrigins[i].x -= darwinMainScreenX;
+ dixScreenOrigins[i].y -= darwinMainScreenY;
+ ErrorF("Screen %d placed at X11 coordinate (%d,%d).\n",
+ i, dixScreenOrigins[i].x, dixScreenOrigins[i].y);
+ }
+ }
+}
+
+/* Initialize screenInfo for all actually accessible framebuffers.
+
+ The display mode dependent code gets called three times. The mode
+ specific InitOutput routines are expected to discover the number of
+ potentially useful screens and cache routes to them internally.
+ Inside DarwinAddScreen are two other mode specific calls. A mode
+ specific AddScreen routine is called for each screen to actually
+ initialize the screen with the ScreenPtr structure. After other
+ screen setup has been done, a mode specific SetupScreen function can
+ be called to finalize screen setup. */
+
+void
+InitOutput (ScreenInfo *pScreenInfo, int argc, char **argv)
+{
+ int i;
+ static unsigned long generation = 0;
+
+ pScreenInfo->imageByteOrder = IMAGE_BYTE_ORDER;
+ pScreenInfo->bitmapScanlineUnit = BITMAP_SCANLINE_UNIT;
+ pScreenInfo->bitmapScanlinePad = BITMAP_SCANLINE_PAD;
+ pScreenInfo->bitmapBitOrder = BITMAP_BIT_ORDER;
+
+ /* List how we want common pixmap formats to be padded */
+ pScreenInfo->numPixmapFormats = NUMFORMATS;
+ for (i = 0; i < NUMFORMATS; i++)
+ pScreenInfo->formats[i] = formats[i];
+
+ /* Allocate private storage for each screen's Darwin specific info */
+ if (generation != serverGeneration) {
+ darwinScreenIndex = AllocateScreenPrivateIndex();
+ generation = serverGeneration;
+ }
+
+ /* Discover screens and do mode specific initialization */
+ QuartzInitOutput(argc, argv);
+
+ for (i = 0; i < darwinScreensFound; i++)
+ AddScreen( DarwinAddScreen, argc, argv );
+
+ DarwinAdjustScreenOrigins (pScreenInfo);
+
+ PseudoramiXExtensionInit (argc, argv);
+ AppleDRIExtensionInit ();
+ AppleWMExtensionInit ();
+
+ DRIExtensionInit ();
+}
+
+void
+OsVendorFatalError (void)
+{
+ ErrorF( " OsVendorFatalError\n" );
+}
+
+void
+OsVendorInit (void)
+{
+ if (serverGeneration == 1)
+ DarwinPrintBanner();
+}
+
+/* Process device-dependent command line args. Returns 0 if argument is
+ not device dependent, otherwise Count of number of elements of argv
+ that are part of a device dependent commandline option. */
+int
+ddxProcessArgument (int argc, char *argv[], int i)
+{
+ int numDone;
+
+ if ((numDone = QuartzProcessArgument( argc, argv, i )))
+ return numDone;
+
+ if ( !strcmp( argv[i], "-fakebuttons" ) ) {
+ darwinFakeButtons = TRUE;
+ ErrorF( "Faking a three button mouse\n" );
+ return 1;
+ }
+
+ if ( !strcmp( argv[i], "-nofakebuttons" ) ) {
+ darwinFakeButtons = FALSE;
+ ErrorF( "Not faking a three button mouse\n" );
+ return 1;
+ }
+
+ if (!strcmp( argv[i], "-fakemouse2" ) ) {
+ if ( i == argc-1 ) {
+ FatalError( "-fakemouse2 must be followed by a modifer list\n" );
+ }
+ darwinFakeMouse2Mask = DarwinParseModifierList(argv[i+1]);
+ return 2;
+ }
+
+ if (!strcmp( argv[i], "-fakemouse3" ) ) {
+ if ( i == argc-1 ) {
+ FatalError( "-fakemouse3 must be followed by a modifer list\n" );
+ }
+ darwinFakeMouse3Mask = DarwinParseModifierList(argv[i+1]);
+ return 2;
+ }
+
+ if ( !strcmp( argv[i], "-keymap" ) ) {
+ if ( i == argc-1 ) {
+ FatalError( "-keymap must be followed by a filename\n" );
+ }
+ darwinKeymapFile = argv[i+1];
+ return 2;
+ }
+
+ if ( !strcmp( argv[i], "-nokeymap" ) ) {
+ darwinKeymapFile = NULL;
+ return 1;
+ }
+
+ if ( !strcmp( argv[i], "+synckeymap" ) ) {
+ darwinSyncKeymap = TRUE;
+ return 1;
+ }
+ if ( !strcmp( argv[i], "-synckeymap" ) ) {
+ darwinSyncKeymap = FALSE;
+ return 1;
+ }
+
+ if (strcmp (argv[i], "-swapAltMeta") == 0) {
+ darwinSwapAltMeta = TRUE;
+ return 1;
+ }
+
+ if (!strcmp( argv[i], "-showconfig" ) || !strcmp( argv[i], "-version" )) {
+ DarwinPrintBanner();
+ exit(0);
+ }
+
+ /* XDarwinStartup uses this argument to indicate the IOKit X server
+ should be started. Ignore it here. */
+ if ( !strcmp( argv[i], "-iokit" ) ) {
+ return 1;
+ }
+
+ return 0;
+}
+
+/* Print out correct use of device dependent commandline options.
+ Maybe the user now knows what really to do ... */
+void
+ddxUseMsg (void)
+{
+ ErrorF("\n");
+ ErrorF("\n");
+ ErrorF("Device Dependent Usage:\n");
+ ErrorF("\n");
+ ErrorF("-depth <depth> use <depth> bits per pixel. Options: 8, 15, 24\b\n");
+ ErrorF("-fakebuttons fake a 3 button mouse with Command and Option\n");
+ ErrorF("-nofakebuttons\n");
+ ErrorF("-fakemouse2 <keys> fake middle mouse button with modifier keys\n");
+ ErrorF("-fakemouse3 <keys> fake right mouse button with modifier keys\n");
+ ErrorF(" e.g.: -fakemouse2 \"option,shift\"\n");
+ ErrorF("-keymap <file> read the keymap from <file>\n");
+ ErrorF("-nokeymap\n");
+ ErrorF("+synckeymap synchronize X keymap with system keymap\n");
+ ErrorF("-synckeymap only set X keymap on server startup\n");
+ ErrorF("-swapAltMeta swap meaning of Alt and Meta modifiers\n");
+ ErrorF("-version show server version.\n");
+ ErrorF("\n");
+}
+
+/* Device dependent cleanup. Called by dix before normal server death. */
+void
+ddxGiveUp (void)
+{
+ ErrorF( "Quitting XDarwin...\n" );
+ QuartzGiveUp();
+}
+
+/* DDX - specific abort routine. Called by AbortServer(). The attempt is
+ made to restore all original setting of the displays. Also all devices
+ are closed. */
+void
+AbortDDX (void)
+{
+ ErrorF( " AbortDDX\n" );
+
+ /* This is needed for a abnormal server exit, since the normal exit stuff
+ MUST also be performed (i.e. the vt must be left in a defined state) */
+ ddxGiveUp();
+}
+
+extern void GlxExtensionInit();
+extern void GlxWrapInitVisuals(void *procPtr);
+void DarwinGlxExtensionInit (void) { GlxExtensionInit (); }
+void DarwinGlxWrapInitVisuals (void *ptr) { GlxWrapInitVisuals (ptr); }
+
+#ifdef DPMSExtension
+Bool
+DPMSSupported (void)
+{
+ return FALSE;
+}
+
+void
+DPMSSet (int level)
+{
+}
+
+int
+DPMSGet (int *level)
+{
+ return -1;
+}
+#endif
+
+#ifdef DDXTIME
+CARD32
+GetTimeInMillis (void)
+{
+ extern void Microseconds ();
+ UnsignedWide usec;
+
+ /* This doesn't involve trapping into the kernel, unlike gettimeofday. */
+ Microseconds (&usec);
+
+ /* Should be good enough? (-2% error) */
+ return (usec.hi << 22) | (usec.lo >> 10);
+}
+#endif
--- /dev/null
+/*
+ * Copyright (c) 2001 Torrey T. Lyons. All Rights Reserved.
+ * Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name(s) of the above copyright
+ * holders shall not be used in advertising or otherwise to promote the sale,
+ * use or other dealings in this Software without prior written authorization.
+ */
+/* $XFree86: xc/programs/Xserver/hw/darwin/darwin.h,v 1.11 2002/03/28 02:21:08 torrey Exp $ */
+
+#ifndef _DARWIN_H
+#define _DARWIN_H
+
+#include "inputstr.h"
+#include "screenint.h"
+#include "scrnintstr.h"
+#include "extensions/XKB.h"
+
+typedef struct {
+ void *framebuffer;
+ int x;
+ int y;
+ int width;
+ int height;
+ int pitch;
+ int bitsPerPixel;
+ int componentCount;
+ int bitsPerComponent;
+ int colorBitsPerPixel;
+ unsigned int redMask, greenMask, blueMask;
+} DarwinFramebufferRec, *DarwinFramebufferPtr;
+
+/* From darwinKeyboard.c */
+int DarwinModifierNXKeyToNXKeycode(int key, int side);
+void DarwinKeyboardInit(DeviceIntPtr pDev);
+void DarwinKeyboardReload (DeviceIntPtr pDev);
+
+/* from darwin-new-keymap.c */
+unsigned int DarwinSystemKeymapSeed (void);
+
+/* from darwin-input.c */
+void DarwinEnqueueEvent (const xEvent *e);
+Bool DarwinDequeueEvent (xEvent *e);
+void DarwinInputInit (void);
+void DarwinInputPreInit (void);
+int DarwinMouseProc(DeviceIntPtr pPointer, int what);
+int DarwinKeybdProc(DeviceIntPtr pDev, int onoff);
+
+#undef assert
+#define assert(x) { if ((x) == 0) \
+ FatalError("assert failed on line %d of %s!\n", __LINE__, __FILE__); }
+#define kern_assert(x) { if ((x) != KERN_SUCCESS) \
+ FatalError("assert failed on line %d of %s with kernel return 0x%x!\n", \
+ __LINE__, __FILE__, x); }
+#define SCREEN_PRIV(pScreen) \
+ ((DarwinFramebufferPtr)pScreen->devPrivates[darwinScreenIndex].ptr)
+
+#define MIN_KEYCODE XkbMinLegalKeyCode // unfortunately, this isn't 0...
+
+extern void DarwinEnqueuePointerEvent (xEvent *xe);
+extern void DarwinAdjustScreenOrigins (ScreenInfo *pScreenInfo);
+
+/* Global variables from darwin.c */
+extern int darwinScreenIndex; // index into pScreen.devPrivates
+extern int darwinScreensFound;
+
+/* User preferences used by generic Darwin X server code */
+extern Bool darwinSwapAltMeta;
+extern int darwinFakeButtons;
+extern char *darwinKeymapFile;
+extern Bool darwinSyncKeymap;
+
+/* location of X11's (0,0) point in global screen coordinates */
+extern int darwinMainScreenX;
+extern int darwinMainScreenY;
+
+/* Client message event type ranges. */
+enum {
+ kXdarwinFirstEvent = 1,
+ kXdarwinLastEvent = kXdarwinFirstEvent + 99,
+ kXquartzFirstEvent = kXdarwinLastEvent + 1,
+ kXquartzLastEvent = kXquartzFirstEvent + 99,
+};
+
+/* "Darwin" client message types */
+enum {
+ kXdarwinQuit = kXdarwinFirstEvent,
+};
+
+extern char *DarwinFindLibraryFile (const char *file, const char *pathext);
+extern void DarwinForeachLibraryFile (const char *dir,
+ void (*callback) (const char *dir,
+ const char *file,
+ void *data),
+ void *data);
+
+extern void DarwinSetFakeButtons (const char *mod2, const char *mod3);
+
+#endif /* _DARWIN_H */
--- /dev/null
+/* $XFree86: xc/programs/Xserver/GL/dri/dri.c,v 1.34 2001/12/10 19:07:19 dawes Exp $ */
+/**************************************************************************
+
+Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
+Copyright 2000 VA Linux Systems, Inc.
+Copyright (c) 2002 Apple Computer, Inc.
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/*
+ * Authors:
+ * Jens Owen <jens@valinux.com>
+ * Rickard E. (Rik) Faith <faith@valinux.com>
+ *
+ */
+
+#ifdef XFree86LOADER
+#include "xf86.h"
+#include "xf86_ansic.h"
+#else
+#include <sys/time.h>
+#include <unistd.h>
+#endif
+
+#define NEED_REPLIES
+#define NEED_EVENTS
+#include "X.h"
+#include "Xproto.h"
+#include "misc.h"
+#include "dixstruct.h"
+#include "extnsionst.h"
+#include "colormapst.h"
+#include "cursorstr.h"
+#include "scrnintstr.h"
+#include "windowstr.h"
+#include "servermd.h"
+#define _APPLEDRI_SERVER_
+#include "appledristr.h"
+#include "swaprep.h"
+#include "dri-surface.h"
+#include "dristruct.h"
+#include "mi.h"
+#include "mipointer.h"
+#include "rootless-common.h"
+#include "x-hash.h"
+#include "x-hook.h"
+
+#include <AvailabilityMacros.h>
+
+static int DRIScreenPrivIndex = -1;
+static int DRIWindowPrivIndex = -1;
+static int DRIPixmapPrivIndex = -1;
+static unsigned long DRIGeneration = 0;
+
+static RESTYPE DRIDrawablePrivResType;
+
+static x_hash_table *surface_hash; /* maps surface ids -> drawablePrivs */
+
+Bool
+DRIScreenInit(ScreenPtr pScreen)
+{
+ DRIScreenPrivPtr pDRIPriv;
+ int i;
+
+ if (DRIGeneration != serverGeneration) {
+ if ((DRIScreenPrivIndex = AllocateScreenPrivateIndex()) < 0)
+ return FALSE;
+ DRIGeneration = serverGeneration;
+ }
+
+ pDRIPriv = (DRIScreenPrivPtr) xcalloc(1, sizeof(DRIScreenPrivRec));
+ if (!pDRIPriv) {
+ pScreen->devPrivates[DRIScreenPrivIndex].ptr = NULL;
+ return FALSE;
+ }
+
+ pScreen->devPrivates[DRIScreenPrivIndex].ptr = (pointer) pDRIPriv;
+ pDRIPriv->directRenderingSupport = TRUE;
+ pDRIPriv->nrWindows = 0;
+
+ /* Initialize drawable tables */
+ for( i=0; i < DRI_MAX_DRAWABLES; i++) {
+ pDRIPriv->DRIDrawables[i] = NULL;
+ }
+
+ return TRUE;
+}
+
+Bool
+DRIFinishScreenInit(ScreenPtr pScreen)
+{
+ DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
+
+ /* Wrap DRI support */
+ pDRIPriv->wrap.ValidateTree = pScreen->ValidateTree;
+ pScreen->ValidateTree = DRIValidateTree;
+
+ pDRIPriv->wrap.PostValidateTree = pScreen->PostValidateTree;
+ pScreen->PostValidateTree = DRIPostValidateTree;
+
+ pDRIPriv->wrap.WindowExposures = pScreen->WindowExposures;
+ pScreen->WindowExposures = DRIWindowExposures;
+
+ pDRIPriv->wrap.CopyWindow = pScreen->CopyWindow;
+ pScreen->CopyWindow = DRICopyWindow;
+
+ pDRIPriv->wrap.ClipNotify = pScreen->ClipNotify;
+ pScreen->ClipNotify = DRIClipNotify;
+
+ ErrorF("[DRI] screen %d installation complete\n", pScreen->myNum);
+
+ return TRUE;
+}
+
+void
+DRICloseScreen(ScreenPtr pScreen)
+{
+ DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
+
+ if (pDRIPriv && pDRIPriv->directRenderingSupport) {
+ xfree(pDRIPriv);
+ pScreen->devPrivates[DRIScreenPrivIndex].ptr = NULL;
+ }
+}
+
+Bool
+DRIExtensionInit(void)
+{
+ int i;
+ ScreenPtr pScreen;
+
+ if (DRIScreenPrivIndex < 0) {
+ return FALSE;
+ }
+
+ /* Allocate a window private index with a zero sized private area for
+ * each window, then should a window become a DRI window, we'll hang
+ * a DRIWindowPrivateRec off of this private index.
+ */
+ if ((DRIWindowPrivIndex = AllocateWindowPrivateIndex()) < 0)
+ return FALSE;
+ if ((DRIPixmapPrivIndex = AllocatePixmapPrivateIndex()) < 0)
+ return FALSE;
+
+ DRIDrawablePrivResType = CreateNewResourceType(DRIDrawablePrivDelete);
+
+ for (i = 0; i < screenInfo.numScreens; i++)
+ {
+ pScreen = screenInfo.screens[i];
+ if (!AllocateWindowPrivate(pScreen, DRIWindowPrivIndex, 0))
+ return FALSE;
+ if (!AllocatePixmapPrivate(pScreen, DRIPixmapPrivIndex, 0))
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+void
+DRIReset(void)
+{
+ /*
+ * This stub routine is called when the X Server recycles, resources
+ * allocated by DRIExtensionInit need to be managed here.
+ *
+ * Currently this routine is a stub because all the interesting resources
+ * are managed via the screen init process.
+ */
+}
+
+Bool
+DRIQueryDirectRenderingCapable(ScreenPtr pScreen, Bool* isCapable)
+{
+ DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
+
+ if (pDRIPriv)
+ *isCapable = pDRIPriv->directRenderingSupport;
+ else
+ *isCapable = FALSE;
+
+ return TRUE;
+}
+
+Bool
+DRIAuthConnection(ScreenPtr pScreen, unsigned int magic)
+{
+#if 0
+ /* FIXME: something? */
+
+ DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
+
+ if (drmAuthMagic(pDRIPriv->drmFD, magic)) return FALSE;
+#endif
+ return TRUE;
+}
+
+static void
+DRIUpdateSurface (DRIDrawablePrivPtr pDRIDrawablePriv, DrawablePtr pDraw)
+{
+ WindowPtr pTopWin;
+ xp_window_changes wc;
+ unsigned int flags = 0;
+
+ if (pDRIDrawablePriv->sid == 0)
+ return;
+
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
+ wc.depth = (pDraw->bitsPerPixel == 32 ? XP_DEPTH_ARGB8888
+ : pDraw->bitsPerPixel == 16 ? XP_DEPTH_RGB555 : XP_DEPTH_NIL);
+ if (wc.depth != XP_DEPTH_NIL)
+ flags |= XP_DEPTH;
+#endif
+
+ if (pDraw->type == DRAWABLE_WINDOW) {
+ WindowPtr pWin = (WindowPtr) pDraw;
+
+ DRIStopDrawing (&pWin->drawable, FALSE);
+
+ pTopWin = TopLevelParent (pWin);
+
+ wc.x = pWin->drawable.x - (pTopWin->drawable.x - pTopWin->borderWidth);
+ wc.y = pWin->drawable.y - (pTopWin->drawable.y - pTopWin->borderWidth);
+ wc.width = pWin->drawable.width;
+ wc.height = pWin->drawable.height;
+ wc.bit_gravity = XP_GRAVITY_NONE;
+
+ wc.shape_nrects = REGION_NUM_RECTS (&pWin->clipList);
+ wc.shape_rects = REGION_RECTS (&pWin->clipList);
+ wc.shape_tx = - (pTopWin->drawable.x - pTopWin->borderWidth);
+ wc.shape_ty = - (pTopWin->drawable.y - pTopWin->borderWidth);
+
+ flags |= XP_BOUNDS | XP_SHAPE;
+
+ pDRIDrawablePriv->x = pWin->drawable.x - pTopWin->borderWidth;
+ pDRIDrawablePriv->y = pWin->drawable.y - pTopWin->borderWidth;
+
+ } else if (pDraw->type == DRAWABLE_PIXMAP) {
+ wc.x = 0;
+ wc.y = 0;
+ wc.width = pDraw->width;
+ wc.height = pDraw->height;
+ wc.bit_gravity = XP_GRAVITY_NONE;
+ flags |= XP_BOUNDS;
+ }
+
+ xp_configure_surface (pDRIDrawablePriv->sid, flags, &wc);
+}
+
+Bool
+DRICreateSurface (ScreenPtr pScreen, Drawable id,
+ DrawablePtr pDrawable, xp_client_id client_id,
+ xp_surface_id *surface_id, unsigned int ret_key[2],
+ void (*notify) (void *arg, void *data), void *notify_data)
+{
+ DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
+ DRIDrawablePrivPtr pDRIDrawablePriv;
+ WindowPtr pWin;
+ PixmapPtr pPix;
+ xp_window_id wid = 0;
+
+ if (pDrawable->type == DRAWABLE_WINDOW) {
+ pWin = (WindowPtr)pDrawable;
+ pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin);
+ if (pDRIDrawablePriv == NULL) {
+ WindowPtr pTopWin;
+ xp_error err;
+ xp_window_changes wc;
+
+ pTopWin = TopLevelParent (pWin);
+
+ /* allocate a DRI Window Private record */
+ if (!(pDRIDrawablePriv = xcalloc(1, sizeof(DRIDrawablePrivRec)))) {
+ return FALSE;
+ }
+
+ pDRIDrawablePriv->pDraw = pDrawable;
+ pDRIDrawablePriv->pScreen = pScreen;
+ pDRIDrawablePriv->refCount = 0;
+ pDRIDrawablePriv->drawableIndex = -1;
+ pDRIDrawablePriv->notifiers = NULL;
+
+ /* find the physical window */
+ wid = RootlessGetPhysicalWindow (pTopWin, TRUE);
+ if (wid == 0) {
+ xfree (pDRIDrawablePriv);
+ return FALSE;
+ }
+
+ /* allocate the physical surface */
+ err = xp_create_surface (wid, &pDRIDrawablePriv->sid);
+ if (err != Success) {
+ xfree (pDRIDrawablePriv);
+ return FALSE;
+ }
+
+ /* Make it visible */
+ wc.stack_mode = XP_MAPPED_ABOVE;
+ wc.sibling = 0;
+ err = xp_configure_surface (pDRIDrawablePriv->sid,
+ XP_STACKING, &wc);
+ if (err != Success)
+ {
+ xp_destroy_surface (pDRIDrawablePriv->sid);
+ xfree (pDRIDrawablePriv);
+ return FALSE;
+ }
+
+ /* save private off of preallocated index */
+ pWin->devPrivates[DRIWindowPrivIndex].ptr = (pointer)pDRIDrawablePriv;
+ }
+ }
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
+ else if (pDrawable->type == DRAWABLE_PIXMAP) {
+ pPix = (PixmapPtr)pDrawable;
+ pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_PIXMAP(pPix);
+ if (pDRIDrawablePriv == NULL) {
+ xp_error err;
+
+ /* allocate a DRI Window Private record */
+ if (!(pDRIDrawablePriv = xcalloc(1, sizeof(DRIDrawablePrivRec)))) {
+ return FALSE;
+ }
+
+ pDRIDrawablePriv->pDraw = pDrawable;
+ pDRIDrawablePriv->pScreen = pScreen;
+ pDRIDrawablePriv->refCount = 0;
+ pDRIDrawablePriv->drawableIndex = -1;
+ pDRIDrawablePriv->notifiers = NULL;
+
+ /* Passing a null window id to Xplugin in 10.3+ asks for
+ an accelerated offscreen surface. */
+
+ err = xp_create_surface (0, &pDRIDrawablePriv->sid);
+ if (err != Success) {
+ xfree (pDRIDrawablePriv);
+ return FALSE;
+ }
+
+ /* save private off of preallocated index */
+ pPix->devPrivates[DRIPixmapPrivIndex].ptr = (pointer)pDRIDrawablePriv;
+ }
+ }
+#endif
+ else { /* for GLX 1.3, a PBuffer */
+ /* NOT_DONE */
+ return FALSE;
+ }
+
+ /* Finish initialization of new surfaces */
+ if (pDRIDrawablePriv->refCount == 0) {
+ unsigned int key[2] = {0};
+ xp_error err;
+
+ /* try to give the client access to the surface
+ FIXME: how to export pixmaps? */
+ if (client_id != 0 && wid != 0)
+ {
+ err = xp_export_surface (wid, pDRIDrawablePriv->sid,
+ client_id, key);
+ if (err != Success) {
+ xp_destroy_surface (pDRIDrawablePriv->sid);
+ xfree (pDRIDrawablePriv);
+ return FALSE;
+ }
+ }
+
+ pDRIDrawablePriv->key[0] = key[0];
+ pDRIDrawablePriv->key[1] = key[1];
+
+ ++pDRIPriv->nrWindows;
+
+ /* and stash it by surface id */
+ if (surface_hash == NULL)
+ surface_hash = x_hash_table_new (NULL, NULL, NULL, NULL);
+ x_hash_table_insert (surface_hash,
+ (void *) pDRIDrawablePriv->sid, pDRIDrawablePriv);
+
+ /* track this in case this window is destroyed */
+ AddResource(id, DRIDrawablePrivResType, (pointer)pDrawable);
+
+ /* Initialize shape */
+ DRIUpdateSurface (pDRIDrawablePriv, pDrawable);
+ }
+
+ pDRIDrawablePriv->refCount++;
+
+ *surface_id = pDRIDrawablePriv->sid;
+
+ if (ret_key != NULL) {
+ ret_key[0] = pDRIDrawablePriv->key[0];
+ ret_key[1] = pDRIDrawablePriv->key[1];
+ }
+
+ if (notify != NULL) {
+ pDRIDrawablePriv->notifiers = x_hook_add (pDRIDrawablePriv->notifiers,
+ notify, notify_data);
+ }
+
+ return TRUE;
+}
+
+Bool
+DRIDestroySurface(ScreenPtr pScreen, Drawable id, DrawablePtr pDrawable,
+ void (*notify) (void *, void *), void *notify_data)
+{
+ DRIDrawablePrivPtr pDRIDrawablePriv;
+
+ if (pDrawable->type == DRAWABLE_WINDOW) {
+ pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW((WindowPtr)pDrawable);
+ } else if (pDrawable->type == DRAWABLE_PIXMAP) {
+ pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_PIXMAP((PixmapPtr)pDrawable);
+ } else {
+ return FALSE;
+ }
+
+ if (pDRIDrawablePriv != NULL) {
+ if (notify != NULL) {
+ pDRIDrawablePriv->notifiers = x_hook_remove (pDRIDrawablePriv->notifiers,
+ notify, notify_data);
+ }
+ if (--pDRIDrawablePriv->refCount <= 0) {
+ /* This calls back to DRIDrawablePrivDelete
+ which frees the private area */
+ FreeResourceByType(id, DRIDrawablePrivResType, FALSE);
+ }
+ }
+
+ return TRUE;
+}
+
+Bool
+DRIDrawablePrivDelete(pointer pResource, XID id)
+{
+ DrawablePtr pDrawable = (DrawablePtr)pResource;
+ DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pDrawable->pScreen);
+ DRIDrawablePrivPtr pDRIDrawablePriv = NULL;
+ WindowPtr pWin = NULL;
+ PixmapPtr pPix = NULL;
+
+ if (pDrawable->type == DRAWABLE_WINDOW) {
+ pWin = (WindowPtr)pDrawable;
+ pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin);
+ DRIStopDrawing (pDrawable, FALSE);
+ pDRIPriv->drawing = x_list_remove (pDRIPriv->drawing,
+ pDRIDrawablePriv);
+ } else if (pDrawable->type == DRAWABLE_PIXMAP) {
+ pPix = (PixmapPtr)pDrawable;
+ pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_PIXMAP(pPix);
+ }
+
+ if (pDRIDrawablePriv == NULL)
+ return FALSE;
+
+ if (pDRIDrawablePriv->drawableIndex != -1) {
+ /* release drawable table entry */
+ pDRIPriv->DRIDrawables[pDRIDrawablePriv->drawableIndex] = NULL;
+ }
+
+ if (pDRIDrawablePriv->sid != 0) {
+ xp_destroy_surface (pDRIDrawablePriv->sid);
+ x_hash_table_remove (surface_hash, (void *) pDRIDrawablePriv->sid);
+ }
+
+ if (pDRIDrawablePriv->notifiers != NULL)
+ x_hook_free (pDRIDrawablePriv->notifiers);
+
+ xfree(pDRIDrawablePriv);
+
+ if (pDrawable->type == DRAWABLE_WINDOW) {
+ pWin->devPrivates[DRIWindowPrivIndex].ptr = NULL;
+ } else if (pDrawable->type == DRAWABLE_PIXMAP) {
+ pPix->devPrivates[DRIPixmapPrivIndex].ptr = NULL;
+ }
+
+ --pDRIPriv->nrWindows;
+
+ return TRUE;
+}
+
+void
+DRIWindowExposures(WindowPtr pWin, RegionPtr prgn, RegionPtr bsreg)
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
+ DRIDrawablePrivPtr pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin);
+
+ if(pDRIDrawablePriv) {
+ /* FIXME: something? */
+ }
+
+ pScreen->WindowExposures = pDRIPriv->wrap.WindowExposures;
+
+ (*pScreen->WindowExposures)(pWin, prgn, bsreg);
+
+ pDRIPriv->wrap.WindowExposures = pScreen->WindowExposures;
+ pScreen->WindowExposures = DRIWindowExposures;
+
+}
+
+void
+DRICopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
+ DRIDrawablePrivPtr pDRIDrawablePriv;
+
+ if(pDRIPriv->nrWindows > 0) {
+ pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW (pWin);
+ if (pDRIDrawablePriv != NULL) {
+ DRIUpdateSurface (pDRIDrawablePriv, &pWin->drawable);
+ }
+ }
+
+ /* unwrap */
+ pScreen->CopyWindow = pDRIPriv->wrap.CopyWindow;
+
+ /* call lower layers */
+ (*pScreen->CopyWindow)(pWin, ptOldOrg, prgnSrc);
+
+ /* rewrap */
+ pDRIPriv->wrap.CopyWindow = pScreen->CopyWindow;
+ pScreen->CopyWindow = DRICopyWindow;
+}
+
+int
+DRIValidateTree(WindowPtr pParent, WindowPtr pChild, VTKind kind)
+{
+ ScreenPtr pScreen = pParent->drawable.pScreen;
+ DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
+ int returnValue;
+
+ /* unwrap */
+ pScreen->ValidateTree = pDRIPriv->wrap.ValidateTree;
+
+ /* call lower layers */
+ returnValue = (*pScreen->ValidateTree)(pParent, pChild, kind);
+
+ /* rewrap */
+ pDRIPriv->wrap.ValidateTree = pScreen->ValidateTree;
+ pScreen->ValidateTree = DRIValidateTree;
+
+ return returnValue;
+}
+
+void
+DRIPostValidateTree(WindowPtr pParent, WindowPtr pChild, VTKind kind)
+{
+ ScreenPtr pScreen;
+ DRIScreenPrivPtr pDRIPriv;
+
+ if (pParent) {
+ pScreen = pParent->drawable.pScreen;
+ } else {
+ pScreen = pChild->drawable.pScreen;
+ }
+ pDRIPriv = DRI_SCREEN_PRIV(pScreen);
+
+ if (pDRIPriv->wrap.PostValidateTree) {
+ /* unwrap */
+ pScreen->PostValidateTree = pDRIPriv->wrap.PostValidateTree;
+
+ /* call lower layers */
+ (*pScreen->PostValidateTree)(pParent, pChild, kind);
+
+ /* rewrap */
+ pDRIPriv->wrap.PostValidateTree = pScreen->PostValidateTree;
+ pScreen->PostValidateTree = DRIPostValidateTree;
+ }
+}
+
+void
+DRIClipNotify(WindowPtr pWin, int dx, int dy)
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
+ DRIDrawablePrivPtr pDRIDrawablePriv;
+
+ if ((pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin))) {
+ DRIUpdateSurface (pDRIDrawablePriv, &pWin->drawable);
+ }
+
+ if(pDRIPriv->wrap.ClipNotify) {
+ pScreen->ClipNotify = pDRIPriv->wrap.ClipNotify;
+
+ (*pScreen->ClipNotify)(pWin, dx, dy);
+
+ pDRIPriv->wrap.ClipNotify = pScreen->ClipNotify;
+ pScreen->ClipNotify = DRIClipNotify;
+ }
+}
+
+/* This lets get at the unwrapped functions so that they can correctly
+ * call the lowerlevel functions, and choose whether they will be
+ * called at every level of recursion (eg in validatetree).
+ */
+DRIWrappedFuncsRec *
+DRIGetWrappedFuncs(ScreenPtr pScreen)
+{
+ return &(DRI_SCREEN_PRIV(pScreen)->wrap);
+}
+
+void
+DRIQueryVersion(int *majorVersion,
+ int *minorVersion,
+ int *patchVersion)
+{
+ *majorVersion = APPLE_DRI_MAJOR_VERSION;
+ *minorVersion = APPLE_DRI_MINOR_VERSION;
+ *patchVersion = APPLE_DRI_PATCH_VERSION;
+}
+
+void
+DRISurfaceNotify (xp_surface_id id, int kind)
+{
+ DRIDrawablePrivPtr pDRIDrawablePriv = NULL;
+ DRISurfaceNotifyArg arg;
+
+ arg.id = id;
+ arg.kind = kind;
+
+ if (surface_hash != NULL)
+ {
+ pDRIDrawablePriv = x_hash_table_lookup (surface_hash,
+ (void *) id, NULL);
+ }
+
+ if (pDRIDrawablePriv == NULL)
+ return;
+
+ if (kind == AppleDRISurfaceNotifyDestroyed)
+ {
+ pDRIDrawablePriv->sid = 0;
+ x_hash_table_remove (surface_hash, (void *) id);
+ }
+
+ x_hook_run (pDRIDrawablePriv->notifiers, &arg);
+
+ if (kind == AppleDRISurfaceNotifyDestroyed)
+ {
+ /* Kill off the handle. */
+
+ FreeResourceByType (pDRIDrawablePriv->pDraw->id,
+ DRIDrawablePrivResType, FALSE);
+ }
+}
+
+\f
+/* Experimental support for X drawing directly into VRAM surfaces. */
+
+Bool
+DRIStartDrawing (DrawablePtr pDraw)
+{
+#if MAC_OS_X_VERSION_MAX_ALLOWED < 1030
+ return FALSE;
+#else
+ DRIDrawablePrivPtr priv = NULL;
+ DRIScreenPrivPtr pDRIPriv;
+
+ if (pDraw->type == DRAWABLE_WINDOW)
+ priv = DRI_DRAWABLE_PRIV_FROM_WINDOW ((WindowPtr)pDraw);
+#if 0
+ /* FIXME: support pixmaps */
+ else if (pDraw->type == DRAWABLE_PIXMAP)
+ priv = DRI_DRAWABLE_PRIV_FROM_PIXMAP ((PixmapPtr)pDraw);
+#endif
+
+ if (priv == NULL)
+ return FALSE;
+
+ pDRIPriv = DRI_SCREEN_PRIV(priv->pScreen);
+
+ if (!priv->is_drawing)
+ {
+ xp_error err;
+ xp_box r;
+
+ err = xp_lock_window (priv->sid, NULL, NULL,
+ &priv->data, &priv->rowbytes, &r);
+ if (err != Success)
+ return FALSE;
+
+ if (pDraw->type == DRAWABLE_WINDOW)
+ {
+ WindowPtr pWin = (WindowPtr) pDraw;
+ int bw = wBorderWidth (pWin);
+
+ priv->pixmap =
+ GetScratchPixmapHeader(pWin->drawable.pScreen, r.x2 - r.x1,
+ r.y2 - r.y1, pWin->drawable.depth,
+ pWin->drawable.bitsPerPixel,
+ priv->rowbytes, priv->data);
+ TranslatePixmapBase (priv->pixmap,
+ - (pWin->drawable.x - bw),
+ - (pWin->drawable.y - bw));
+ }
+
+ priv->is_drawing = TRUE;
+ pDRIPriv->drawing = x_list_prepend (pDRIPriv->drawing, priv);
+ }
+
+ if (pDraw->type == DRAWABLE_WINDOW)
+ {
+ WindowPtr pWin = (WindowPtr) pDraw;
+
+ priv->oldPixmap = pWin->drawable.pScreen->GetWindowPixmap (pWin);
+ pWin->drawable.pScreen->SetWindowPixmap (pWin, priv->pixmap);
+ }
+
+ return TRUE;
+#endif
+}
+
+Bool
+DRIStopDrawing (DrawablePtr pDraw, Bool flush)
+{
+#if MAC_OS_X_VERSION_MAX_ALLOWED < 1030
+ return FALSE;
+#else
+ DRIDrawablePrivPtr priv = NULL;
+ ScreenPtr pScreen;
+ DRIScreenPrivPtr pDRIPriv;
+
+ if (pDraw->type == DRAWABLE_WINDOW)
+ priv = DRI_DRAWABLE_PRIV_FROM_WINDOW ((WindowPtr)pDraw);
+ else if (pDraw->type == DRAWABLE_PIXMAP)
+ priv = DRI_DRAWABLE_PRIV_FROM_PIXMAP ((PixmapPtr)pDraw);
+
+ if (priv == NULL)
+ return FALSE;
+
+ pScreen = priv->pScreen;
+ pDRIPriv = DRI_SCREEN_PRIV(pScreen);
+
+ if (priv->is_drawing)
+ {
+ xp_unlock_window (priv->sid, flush);
+
+ if (pDraw->type == DRAWABLE_WINDOW)
+ {
+ FreeScratchPixmapHeader (priv->pixmap);
+ pScreen->SetWindowPixmap ((WindowPtr)pDraw, priv->oldPixmap);
+ }
+
+ priv->pixmap = NULL;
+
+ /* If we didn't flush don't forget that we still need to.. */
+ if (flush)
+ pDRIPriv->drawing = x_list_remove (pDRIPriv->drawing, priv);
+
+ priv->is_drawing = FALSE;
+ }
+ else if (flush)
+ {
+ xp_flush_window (priv->sid);
+ }
+
+ return TRUE;
+#endif /* 10.3 */
+}
+
+/* true iff two Boxes overlap */
+#define EXTENTCHECK(r1,r2) \
+ (!( ((r1)->x2 <= (r2)->x1) || \
+ ((r1)->x1 >= (r2)->x2) || \
+ ((r1)->y2 <= (r2)->y1) || \
+ ((r1)->y1 >= (r2)->y2) ) )
+
+Bool
+DRIDamageRegion (DrawablePtr pDraw, RegionPtr pRegion)
+{
+#if MAC_OS_X_VERSION_MAX_ALLOWED < 1030
+ return FALSE;
+#else
+ DRIDrawablePrivPtr priv = NULL;
+ RegionRec clipped;
+ BoxPtr b1, b2;
+
+ if (pDraw->type == DRAWABLE_WINDOW)
+ priv = DRI_DRAWABLE_PRIV_FROM_WINDOW ((WindowPtr)pDraw);
+
+ if (priv == NULL)
+ return FALSE;
+
+ /* adapted from RootlessDamageRegion () */
+
+ if (pDraw->type == DRAWABLE_WINDOW)
+ {
+ WindowPtr pWin = (WindowPtr) pDraw;
+
+ b1 = REGION_EXTENTS (pWin->drawable.pScreen, &pWin->borderClip);
+ b2 = REGION_EXTENTS (pWin->drawable.pScreen, pRegion);
+
+ if (EXTENTCHECK (b1, b2))
+ {
+ /* Regions may overlap. */
+
+ if (REGION_NUM_RECTS (pRegion) == 1)
+ {
+ int in;
+
+ /* Damaged region only has a single rect, so we can
+ just compare that against the region */
+
+ in = RECT_IN_REGION (pWin->drawable.pScreen, &pWin->borderClip,
+ REGION_RECTS (pRegion));
+ if (in == rgnIN)
+ {
+ /* clip totally contains pRegion */
+
+ xp_mark_window (priv->sid, REGION_NUM_RECTS (pRegion),
+ REGION_RECTS (pRegion),
+ -priv->x, -priv->y);
+
+ RootlessQueueRedisplay (pWin->drawable.pScreen);
+ goto out;
+ }
+ else if (in == rgnOUT)
+ {
+ /* clip doesn't contain pRegion */
+
+ goto out;
+ }
+ }
+
+ /* clip overlaps pRegion, need to intersect */
+
+ REGION_INIT (pWin->drawable.pScreen, &clipped, NullBox, 0);
+ REGION_INTERSECT (pWin->drawable.pScreen, &clipped,
+ &pWin->borderClip, pRegion);
+
+ xp_mark_window (priv->sid, REGION_NUM_RECTS (&clipped),
+ REGION_RECTS (&clipped), -priv->x, -priv->y);
+
+ REGION_UNINIT (pWin->drawable.pScreen, &clipped);
+
+ RootlessQueueRedisplay (pWin->drawable.pScreen);
+ }
+ }
+
+out:
+ return TRUE;
+#endif /* 10.3 */
+}
+
+void
+DRISynchronizeDrawable (DrawablePtr pDraw, Bool flush)
+{
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
+ ScreenPtr pScreen;
+ DRIScreenPrivPtr pDRIPriv;
+ DRIDrawablePrivPtr priv;
+ x_list *node, *copy;
+
+ pScreen = pDraw->pScreen;
+ pDRIPriv = DRI_SCREEN_PRIV(pScreen);
+
+ if (pDRIPriv == NULL || pDRIPriv->drawing == NULL)
+ return;
+
+ if (pDraw->type == DRAWABLE_WINDOW)
+ {
+ WindowPtr pWin = TopLevelParent ((WindowPtr) pDraw);
+
+ /* need to find _any_ window under pWin that is drawing. Scan the
+ list looking for candidates. */
+
+ copy = x_list_copy (pDRIPriv->drawing);
+
+ for (node = copy; node != NULL; node = node->next)
+ {
+ priv = node->data;
+
+ if (priv->pDraw->type == DRAWABLE_WINDOW
+ && TopLevelParent ((WindowPtr) priv->pDraw) == pWin)
+ {
+ DRIStopDrawing (priv->pDraw, flush);
+ }
+ }
+
+ x_list_free (copy);
+ }
+ else
+ {
+ DRIStopDrawing (pDraw, flush);
+ }
+#endif /* 10.3 */
+}
+
+void
+DRISynchronize (Bool flush)
+{
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
+ int i;
+ ScreenPtr pScreen;
+ DRIScreenPrivPtr pDRIPriv;
+ DRIDrawablePrivPtr priv;
+ x_list *node, *copy;
+
+ for (i = 0; i < screenInfo.numScreens; i++)
+ {
+ pScreen = screenInfo.screens[i];
+ pDRIPriv = DRI_SCREEN_PRIV(pScreen);
+
+ if (pDRIPriv == NULL || pDRIPriv->drawing == NULL)
+ continue;
+
+ copy = x_list_copy (pDRIPriv->drawing);
+
+ for (node = copy; node != NULL; node = node->next)
+ {
+ priv = node->data;
+
+ DRIStopDrawing (priv->pDraw, flush);
+ }
+
+ x_list_free (copy);
+ }
+#endif /* 10.3 */
+}
--- /dev/null
+/* $XFree86: xc/programs/Xserver/GL/dri/dri.h,v 1.18 2001/03/21 16:21:40 dawes Exp $ */
+/**************************************************************************
+
+Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
+Copyright (c) 2002 Apple Computer, Inc.
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/*
+ * Authors:
+ * Jens Owen <jens@precisioninsight.com>
+ *
+ */
+
+/* Prototypes for DRI functions */
+
+#ifndef _DRI_SURFACE_H_
+#define _DRI_SURFACE_H_
+
+#include "dri.h"
+#include "Xplugin.h"
+
+typedef void (*ClipNotifyPtr)( WindowPtr, int, int );
+
+
+/*
+ * These functions can be wrapped by the DRI. Each of these have
+ * generic default funcs (initialized in DRICreateInfoRec) and can be
+ * overridden by the driver in its [driver]DRIScreenInit function.
+ */
+typedef struct {
+ WindowExposuresProcPtr WindowExposures;
+ CopyWindowProcPtr CopyWindow;
+ ValidateTreeProcPtr ValidateTree;
+ PostValidateTreeProcPtr PostValidateTree;
+ ClipNotifyProcPtr ClipNotify;
+} DRIWrappedFuncsRec, *DRIWrappedFuncsPtr;
+
+typedef struct {
+ xp_surface_id id;
+ int kind;
+} DRISurfaceNotifyArg;
+
+extern void DRIClipNotify(WindowPtr pWin,
+ int dx,
+ int dy);
+
+extern void DRICloseScreen(ScreenPtr pScreen);
+
+extern void DRICopyWindow(WindowPtr pWin,
+ DDXPointRec ptOldOrg,
+ RegionPtr prgnSrc);
+
+extern Bool DRICreateSurface(ScreenPtr pScreen,
+ Drawable id,
+ DrawablePtr pDrawable,
+ xp_client_id client_id,
+ xp_surface_id *surface_id,
+ unsigned int key[2],
+ void (*notify) (void *arg, void *data),
+ void *notify_data);
+
+extern Bool DRIDestroySurface(ScreenPtr pScreen,
+ Drawable id,
+ DrawablePtr pDrawable,
+ void (*notify) (void *arg, void *data),
+ void *notify_data);
+
+extern Bool DRIDrawablePrivDelete(pointer pResource,
+ XID id);
+
+extern DRIWrappedFuncsRec *DRIGetWrappedFuncs(ScreenPtr pScreen);
+
+extern void DRIPostValidateTree(WindowPtr pParent,
+ WindowPtr pChild,
+ VTKind kind);
+
+extern int DRIValidateTree(WindowPtr pParent,
+ WindowPtr pChild,
+ VTKind kind);
+
+extern void DRIWindowExposures(WindowPtr pWin,
+ RegionPtr prgn,
+ RegionPtr bsreg);
+
+extern void DRISurfaceNotify (xp_surface_id id, int kind);
+
+extern Bool DRIStartDrawing (DrawablePtr pDraw);
+extern Bool DRIStopDrawing (DrawablePtr pDraw, Bool flush);
+extern Bool DRIDamageRegion (DrawablePtr pDraw, RegionPtr pRegion);
+extern void DRISynchronizeDrawable (DrawablePtr pDraw, Bool flush);
+extern void DRISynchronize (Bool flush);
+
+#endif
--- /dev/null
+/* $XFree86: xc/programs/Xserver/GL/dri/dri.h,v 1.18 2001/03/21 16:21:40 dawes Exp $ */
+/**************************************************************************
+
+Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
+Copyright (c) 2002 Apple Computer, Inc.
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/*
+ * Authors:
+ * Jens Owen <jens@precisioninsight.com>
+ *
+ */
+
+/* Prototypes for DRI functions */
+
+#ifndef _DRI_H_
+
+#include "Xdefs.h"
+#include "screenint.h"
+#define _APPLEDRI_SERVER_
+#include "appledri.h"
+
+extern Bool DRIAuthConnection(ScreenPtr pScreen, unsigned int magic);
+
+extern Bool DRIExtensionInit(void);
+
+extern Bool DRIFinishScreenInit(ScreenPtr pScreen);
+
+extern Bool DRIQueryDirectRenderingCapable(ScreenPtr pScreen,
+ Bool *isCapable);
+
+extern void DRIQueryVersion(int *majorVersion,
+ int *minorVersion,
+ int *patchVersion);
+
+extern void DRIReset(void);
+
+extern Bool DRIScreenInit(ScreenPtr pScreen);
+
+#define _DRI_H_
+
+#endif
--- /dev/null
+/* $XFree86: xc/programs/Xserver/GL/dri/dristruct.h,v 1.10 2001/03/21 16:21:40 dawes Exp $ */
+/**************************************************************************
+
+Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
+Copyright (c) 2002 Apple Computer, Inc.
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/*
+ * Authors:
+ * Jens Owen <jens@precisioninsight.com>
+ *
+ */
+
+#ifndef DRI_STRUCT_H
+#define DRI_STRUCT_H
+
+#include "dri-surface.h"
+#include "x-list.h"
+
+#define DRI_MAX_DRAWABLES 256
+
+#define DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin) \
+ ((DRIWindowPrivIndex < 0) ? \
+ NULL : \
+ ((DRIDrawablePrivPtr)((pWin)->devPrivates[DRIWindowPrivIndex].ptr)))
+
+#define DRI_DRAWABLE_PRIV_FROM_PIXMAP(pPix) \
+ ((DRIPixmapPrivIndex < 0) ? \
+ NULL : \
+ ((DRIDrawablePrivPtr)((pPix)->devPrivates[DRIPixmapPrivIndex].ptr)))
+
+typedef struct _DRIDrawablePrivRec
+{
+ xp_surface_id sid;
+ int drawableIndex;
+ DrawablePtr pDraw;
+ ScreenPtr pScreen;
+ int refCount;
+ unsigned int key[2];
+ x_list *notifiers; /* list of (FUN . DATA) */
+
+ int x, y; /* relative to physical window */
+
+ void *data;
+ unsigned int rowbytes;
+ PixmapPtr pixmap, oldPixmap;
+
+ unsigned int is_drawing :1;
+} DRIDrawablePrivRec, *DRIDrawablePrivPtr;
+
+#define DRI_SCREEN_PRIV(pScreen) \
+ ((DRIScreenPrivIndex < 0) ? \
+ NULL : \
+ ((DRIScreenPrivPtr)((pScreen)->devPrivates[DRIScreenPrivIndex].ptr)))
+
+#define DRI_SCREEN_PRIV_FROM_INDEX(screenIndex) ((DRIScreenPrivPtr) \
+ (screenInfo.screens[screenIndex]->devPrivates[DRIScreenPrivIndex].ptr))
+
+
+typedef struct _DRIScreenPrivRec
+{
+ Bool directRenderingSupport;
+ int nrWindows;
+ DRIWrappedFuncsRec wrap;
+ DrawablePtr DRIDrawables[DRI_MAX_DRAWABLES];
+ x_list *drawing; /* list of DRIDrawablePrivPtr */
+} DRIScreenPrivRec, *DRIScreenPrivPtr;
+
+#endif /* DRI_STRUCT_H */
--- /dev/null
+on open names
+ set fileNames to {}
+ repeat with i from 1 to count of names
+ set fileNames to fileNames & {quoted form of (POSIX path of (item i of names))}
+ end repeat
+
+ set fifoLocation to " >> ~/sinfg/fifo"
+
+ repeat with fileName in fileNames
+ set cmdLine to {"echo O " & fileName & fifoLocation}
+ do shell script cmdLine
+ end repeat
+end open
+
--- /dev/null
+/* $XFree86$
+ * This module converts keysym values into the corresponding ISO 10646
+ * (UCS, Unicode) values.
+ *
+ * The array keysymtab[] contains pairs of X11 keysym values for graphical
+ * characters and the corresponding Unicode value. The function
+ * keysym2ucs() maps a keysym onto a Unicode value using a binary search,
+ * therefore keysymtab[] must remain SORTED by keysym value.
+ *
+ * The keysym -> UTF-8 conversion will hopefully one day be provided
+ * by Xlib via XmbLookupString() and should ideally not have to be
+ * done in X applications. But we are not there yet.
+ *
+ * We allow to represent any UCS character in the range U-00000000 to
+ * U-00FFFFFF by a keysym value in the range 0x01000000 to 0x01ffffff.
+ * This admittedly does not cover the entire 31-bit space of UCS, but
+ * it does cover all of the characters up to U-10FFFF, which can be
+ * represented by UTF-16, and more, and it is very unlikely that higher
+ * UCS codes will ever be assigned by ISO. So to get Unicode character
+ * U+ABCD you can directly use keysym 0x0100abcd.
+ *
+ * NOTE: The comments in the table below contain the actual character
+ * encoded in UTF-8, so for viewing and editing best use an editor in
+ * UTF-8 mode.
+ *
+ * Author: Markus G. Kuhn <mkuhn@acm.org>, University of Cambridge, April 2001
+ *
+ * Special thanks to Richard Verhoeven <river@win.tue.nl> for preparing
+ * an initial draft of the mapping table.
+ *
+ * This software is in the public domain. Share and enjoy!
+ *
+ * AUTOMATICALLY GENERATED FILE, DO NOT EDIT !!! (unicode/convmap.pl)
+ */
+
+#include "keysym2ucs.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+struct codepair {
+ unsigned short keysym;
+ unsigned short ucs;
+};
+
+const static struct codepair keysymtab[] = {
+ { 0x01a1, 0x0104 },
+ { 0x01a2, 0x02d8 },
+ { 0x01a3, 0x0141 },
+ { 0x01a5, 0x013d },
+ { 0x01a6, 0x015a },
+ { 0x01a9, 0x0160 },
+ { 0x01aa, 0x015e },
+ { 0x01ab, 0x0164 },
+ { 0x01ac, 0x0179 },
+ { 0x01ae, 0x017d },
+ { 0x01af, 0x017b },
+ { 0x01b1, 0x0105 },
+ { 0x01b2, 0x02db },
+ { 0x01b3, 0x0142 },
+ { 0x01b5, 0x013e },
+ { 0x01b6, 0x015b },
+ { 0x01b7, 0x02c7 },
+ { 0x01b9, 0x0161 },
+ { 0x01ba, 0x015f },
+ { 0x01bb, 0x0165 },
+ { 0x01bc, 0x017a },
+ { 0x01bd, 0x02dd },
+ { 0x01be, 0x017e },
+ { 0x01bf, 0x017c },
+ { 0x01c0, 0x0154 },
+ { 0x01c3, 0x0102 },
+ { 0x01c5, 0x0139 },
+ { 0x01c6, 0x0106 },
+ { 0x01c8, 0x010c },
+ { 0x01ca, 0x0118 },
+ { 0x01cc, 0x011a },
+ { 0x01cf, 0x010e },
+ { 0x01d0, 0x0110 },
+ { 0x01d1, 0x0143 },
+ { 0x01d2, 0x0147 },
+ { 0x01d5, 0x0150 },
+ { 0x01d8, 0x0158 },
+ { 0x01d9, 0x016e },
+ { 0x01db, 0x0170 },
+ { 0x01de, 0x0162 },
+ { 0x01e0, 0x0155 },
+ { 0x01e3, 0x0103 },
+ { 0x01e5, 0x013a },
+ { 0x01e6, 0x0107 },
+ { 0x01e8, 0x010d },
+ { 0x01ea, 0x0119 },
+ { 0x01ec, 0x011b },
+ { 0x01ef, 0x010f },
+ { 0x01f0, 0x0111 },
+ { 0x01f1, 0x0144 },
+ { 0x01f2, 0x0148 },
+ { 0x01f5, 0x0151 },
+ { 0x01f8, 0x0159 },
+ { 0x01f9, 0x016f },
+ { 0x01fb, 0x0171 },
+ { 0x01fe, 0x0163 },
+ { 0x01ff, 0x02d9 },
+ { 0x02a1, 0x0126 },
+ { 0x02a6, 0x0124 },
+ { 0x02a9, 0x0130 },
+ { 0x02ab, 0x011e },
+ { 0x02ac, 0x0134 },
+ { 0x02b1, 0x0127 },
+ { 0x02b6, 0x0125 },
+ { 0x02b9, 0x0131 },
+ { 0x02bb, 0x011f },
+ { 0x02bc, 0x0135 },
+ { 0x02c5, 0x010a },
+ { 0x02c6, 0x0108 },
+ { 0x02d5, 0x0120 },
+ { 0x02d8, 0x011c },
+ { 0x02dd, 0x016c },
+ { 0x02de, 0x015c },
+ { 0x02e5, 0x010b },
+ { 0x02e6, 0x0109 },
+ { 0x02f5, 0x0121 },
+ { 0x02f8, 0x011d },
+ { 0x02fd, 0x016d },
+ { 0x02fe, 0x015d },
+ { 0x03a2, 0x0138 },
+ { 0x03a3, 0x0156 },
+ { 0x03a5, 0x0128 },
+ { 0x03a6, 0x013b },
+ { 0x03aa, 0x0112 },
+ { 0x03ab, 0x0122 },
+ { 0x03ac, 0x0166 },
+ { 0x03b3, 0x0157 },
+ { 0x03b5, 0x0129 },
+ { 0x03b6, 0x013c },
+ { 0x03ba, 0x0113 },
+ { 0x03bb, 0x0123 },
+ { 0x03bc, 0x0167 },
+ { 0x03bd, 0x014a },
+ { 0x03bf, 0x014b },
+ { 0x03c0, 0x0100 },
+ { 0x03c7, 0x012e },
+ { 0x03cc, 0x0116 },
+ { 0x03cf, 0x012a },
+ { 0x03d1, 0x0145 },
+ { 0x03d2, 0x014c },
+ { 0x03d3, 0x0136 },
+ { 0x03d9, 0x0172 },
+ { 0x03dd, 0x0168 },
+ { 0x03de, 0x016a },
+ { 0x03e0, 0x0101 },
+ { 0x03e7, 0x012f },
+ { 0x03ec, 0x0117 },
+ { 0x03ef, 0x012b },
+ { 0x03f1, 0x0146 },
+ { 0x03f2, 0x014d },
+ { 0x03f3, 0x0137 },
+ { 0x03f9, 0x0173 },
+ { 0x03fd, 0x0169 },
+ { 0x03fe, 0x016b },
+ { 0x047e, 0x203e },
+ { 0x04a1, 0x3002 },
+ { 0x04a2, 0x300c },
+ { 0x04a3, 0x300d },
+ { 0x04a4, 0x3001 },
+ { 0x04a5, 0x30fb },
+ { 0x04a6, 0x30f2 },
+ { 0x04a7, 0x30a1 },
+ { 0x04a8, 0x30a3 },
+ { 0x04a9, 0x30a5 },
+ { 0x04aa, 0x30a7 },
+ { 0x04ab, 0x30a9 },
+ { 0x04ac, 0x30e3 },
+ { 0x04ad, 0x30e5 },
+ { 0x04ae, 0x30e7 },
+ { 0x04af, 0x30c3 },
+ { 0x04b0, 0x30fc },
+ { 0x04b1, 0x30a2 },
+ { 0x04b2, 0x30a4 },
+ { 0x04b3, 0x30a6 },
+ { 0x04b4, 0x30a8 },
+ { 0x04b5, 0x30aa },
+ { 0x04b6, 0x30ab },
+ { 0x04b7, 0x30ad },
+ { 0x04b8, 0x30af },
+ { 0x04b9, 0x30b1 },
+ { 0x04ba, 0x30b3 },
+ { 0x04bb, 0x30b5 },
+ { 0x04bc, 0x30b7 },
+ { 0x04bd, 0x30b9 },
+ { 0x04be, 0x30bb },
+ { 0x04bf, 0x30bd },
+ { 0x04c0, 0x30bf },
+ { 0x04c1, 0x30c1 },
+ { 0x04c2, 0x30c4 },
+ { 0x04c3, 0x30c6 },
+ { 0x04c4, 0x30c8 },
+ { 0x04c5, 0x30ca },
+ { 0x04c6, 0x30cb },
+ { 0x04c7, 0x30cc },
+ { 0x04c8, 0x30cd },
+ { 0x04c9, 0x30ce },
+ { 0x04ca, 0x30cf },
+ { 0x04cb, 0x30d2 },
+ { 0x04cc, 0x30d5 },
+ { 0x04cd, 0x30d8 },
+ { 0x04ce, 0x30db },
+ { 0x04cf, 0x30de },
+ { 0x04d0, 0x30df },
+ { 0x04d1, 0x30e0 },
+ { 0x04d2, 0x30e1 },
+ { 0x04d3, 0x30e2 },
+ { 0x04d4, 0x30e4 },
+ { 0x04d5, 0x30e6 },
+ { 0x04d6, 0x30e8 },
+ { 0x04d7, 0x30e9 },
+ { 0x04d8, 0x30ea },
+ { 0x04d9, 0x30eb },
+ { 0x04da, 0x30ec },
+ { 0x04db, 0x30ed },
+ { 0x04dc, 0x30ef },
+ { 0x04dd, 0x30f3 },
+ { 0x04de, 0x309b },
+ { 0x04df, 0x309c },
+ { 0x05ac, 0x060c },
+ { 0x05bb, 0x061b },
+ { 0x05bf, 0x061f },
+ { 0x05c1, 0x0621 },
+ { 0x05c2, 0x0622 },
+ { 0x05c3, 0x0623 },
+ { 0x05c4, 0x0624 },
+ { 0x05c5, 0x0625 },
+ { 0x05c6, 0x0626 },
+ { 0x05c7, 0x0627 },
+ { 0x05c8, 0x0628 },
+ { 0x05c9, 0x0629 },
+ { 0x05ca, 0x062a },
+ { 0x05cb, 0x062b },
+ { 0x05cc, 0x062c },
+ { 0x05cd, 0x062d },
+ { 0x05ce, 0x062e },
+ { 0x05cf, 0x062f },
+ { 0x05d0, 0x0630 },
+ { 0x05d1, 0x0631 },
+ { 0x05d2, 0x0632 },
+ { 0x05d3, 0x0633 },
+ { 0x05d4, 0x0634 },
+ { 0x05d5, 0x0635 },
+ { 0x05d6, 0x0636 },
+ { 0x05d7, 0x0637 },
+ { 0x05d8, 0x0638 },
+ { 0x05d9, 0x0639 },
+ { 0x05da, 0x063a },
+ { 0x05e0, 0x0640 },
+ { 0x05e1, 0x0641 },
+ { 0x05e2, 0x0642 },
+ { 0x05e3, 0x0643 },
+ { 0x05e4, 0x0644 },
+ { 0x05e5, 0x0645 },
+ { 0x05e6, 0x0646 },
+ { 0x05e7, 0x0647 },
+ { 0x05e8, 0x0648 },
+ { 0x05e9, 0x0649 },
+ { 0x05ea, 0x064a },
+ { 0x05eb, 0x064b },
+ { 0x05ec, 0x064c },
+ { 0x05ed, 0x064d },
+ { 0x05ee, 0x064e },
+ { 0x05ef, 0x064f },
+ { 0x05f0, 0x0650 },
+ { 0x05f1, 0x0651 },
+ { 0x05f2, 0x0652 },
+ { 0x06a1, 0x0452 },
+ { 0x06a2, 0x0453 },
+ { 0x06a3, 0x0451 },
+ { 0x06a4, 0x0454 },
+ { 0x06a5, 0x0455 },
+ { 0x06a6, 0x0456 },
+ { 0x06a7, 0x0457 },
+ { 0x06a8, 0x0458 },
+ { 0x06a9, 0x0459 },
+ { 0x06aa, 0x045a },
+ { 0x06ab, 0x045b },
+ { 0x06ac, 0x045c },
+ { 0x06ae, 0x045e },
+ { 0x06af, 0x045f },
+ { 0x06b0, 0x2116 },
+ { 0x06b1, 0x0402 },
+ { 0x06b2, 0x0403 },
+ { 0x06b3, 0x0401 },
+ { 0x06b4, 0x0404 },
+ { 0x06b5, 0x0405 },
+ { 0x06b6, 0x0406 },
+ { 0x06b7, 0x0407 },
+ { 0x06b8, 0x0408 },
+ { 0x06b9, 0x0409 },
+ { 0x06ba, 0x040a },
+ { 0x06bb, 0x040b },
+ { 0x06bc, 0x040c },
+ { 0x06be, 0x040e },
+ { 0x06bf, 0x040f },
+ { 0x06c0, 0x044e },
+ { 0x06c1, 0x0430 },
+ { 0x06c2, 0x0431 },
+ { 0x06c3, 0x0446 },
+ { 0x06c4, 0x0434 },
+ { 0x06c5, 0x0435 },
+ { 0x06c6, 0x0444 },
+ { 0x06c7, 0x0433 },
+ { 0x06c8, 0x0445 },
+ { 0x06c9, 0x0438 },
+ { 0x06ca, 0x0439 },
+ { 0x06cb, 0x043a },
+ { 0x06cc, 0x043b },
+ { 0x06cd, 0x043c },
+ { 0x06ce, 0x043d },
+ { 0x06cf, 0x043e },
+ { 0x06d0, 0x043f },
+ { 0x06d1, 0x044f },
+ { 0x06d2, 0x0440 },
+ { 0x06d3, 0x0441 },
+ { 0x06d4, 0x0442 },
+ { 0x06d5, 0x0443 },
+ { 0x06d6, 0x0436 },
+ { 0x06d7, 0x0432 },
+ { 0x06d8, 0x044c },
+ { 0x06d9, 0x044b },
+ { 0x06da, 0x0437 },
+ { 0x06db, 0x0448 },
+ { 0x06dc, 0x044d },
+ { 0x06dd, 0x0449 },
+ { 0x06de, 0x0447 },
+ { 0x06df, 0x044a },
+ { 0x06e0, 0x042e },
+ { 0x06e1, 0x0410 },
+ { 0x06e2, 0x0411 },
+ { 0x06e3, 0x0426 },
+ { 0x06e4, 0x0414 },
+ { 0x06e5, 0x0415 },
+ { 0x06e6, 0x0424 },
+ { 0x06e7, 0x0413 },
+ { 0x06e8, 0x0425 },
+ { 0x06e9, 0x0418 },
+ { 0x06ea, 0x0419 },
+ { 0x06eb, 0x041a },
+ { 0x06ec, 0x041b },
+ { 0x06ed, 0x041c },
+ { 0x06ee, 0x041d },
+ { 0x06ef, 0x041e },
+ { 0x06f0, 0x041f },
+ { 0x06f1, 0x042f },
+ { 0x06f2, 0x0420 },
+ { 0x06f3, 0x0421 },
+ { 0x06f4, 0x0422 },
+ { 0x06f5, 0x0423 },
+ { 0x06f6, 0x0416 },
+ { 0x06f7, 0x0412 },
+ { 0x06f8, 0x042c },
+ { 0x06f9, 0x042b },
+ { 0x06fa, 0x0417 },
+ { 0x06fb, 0x0428 },
+ { 0x06fc, 0x042d },
+ { 0x06fd, 0x0429 },
+ { 0x06fe, 0x0427 },
+ { 0x06ff, 0x042a },
+ { 0x07a1, 0x0386 },
+ { 0x07a2, 0x0388 },
+ { 0x07a3, 0x0389 },
+ { 0x07a4, 0x038a },
+ { 0x07a5, 0x03aa },
+ { 0x07a7, 0x038c },
+ { 0x07a8, 0x038e },
+ { 0x07a9, 0x03ab },
+ { 0x07ab, 0x038f },
+ { 0x07ae, 0x0385 },
+ { 0x07af, 0x2015 },
+ { 0x07b1, 0x03ac },
+ { 0x07b2, 0x03ad },
+ { 0x07b3, 0x03ae },
+ { 0x07b4, 0x03af },
+ { 0x07b5, 0x03ca },
+ { 0x07b6, 0x0390 },
+ { 0x07b7, 0x03cc },
+ { 0x07b8, 0x03cd },
+ { 0x07b9, 0x03cb },
+ { 0x07ba, 0x03b0 },
+ { 0x07bb, 0x03ce },
+ { 0x07c1, 0x0391 },
+ { 0x07c2, 0x0392 },
+ { 0x07c3, 0x0393 },
+ { 0x07c4, 0x0394 },
+ { 0x07c5, 0x0395 },
+ { 0x07c6, 0x0396 },
+ { 0x07c7, 0x0397 },
+ { 0x07c8, 0x0398 },
+ { 0x07c9, 0x0399 },
+ { 0x07ca, 0x039a },
+ { 0x07cb, 0x039b },
+ { 0x07cc, 0x039c },
+ { 0x07cd, 0x039d },
+ { 0x07ce, 0x039e },
+ { 0x07cf, 0x039f },
+ { 0x07d0, 0x03a0 },
+ { 0x07d1, 0x03a1 },
+ { 0x07d2, 0x03a3 },
+ { 0x07d4, 0x03a4 },
+ { 0x07d5, 0x03a5 },
+ { 0x07d6, 0x03a6 },
+ { 0x07d7, 0x03a7 },
+ { 0x07d8, 0x03a8 },
+ { 0x07d9, 0x03a9 },
+ { 0x07e1, 0x03b1 },
+ { 0x07e2, 0x03b2 },
+ { 0x07e3, 0x03b3 },
+ { 0x07e4, 0x03b4 },
+ { 0x07e5, 0x03b5 },
+ { 0x07e6, 0x03b6 },
+ { 0x07e7, 0x03b7 },
+ { 0x07e8, 0x03b8 },
+ { 0x07e9, 0x03b9 },
+ { 0x07ea, 0x03ba },
+ { 0x07eb, 0x03bb },
+ { 0x07ec, 0x03bc },
+ { 0x07ed, 0x03bd },
+ { 0x07ee, 0x03be },
+ { 0x07ef, 0x03bf },
+ { 0x07f0, 0x03c0 },
+ { 0x07f1, 0x03c1 },
+ { 0x07f2, 0x03c3 },
+ { 0x07f3, 0x03c2 },
+ { 0x07f4, 0x03c4 },
+ { 0x07f5, 0x03c5 },
+ { 0x07f6, 0x03c6 },
+ { 0x07f7, 0x03c7 },
+ { 0x07f8, 0x03c8 },
+ { 0x07f9, 0x03c9 },
+ { 0x08a1, 0x23b7 },
+ { 0x08a2, 0x250c },
+ { 0x08a3, 0x2500 },
+ { 0x08a4, 0x2320 },
+ { 0x08a5, 0x2321 },
+ { 0x08a6, 0x2502 },
+ { 0x08a7, 0x23a1 },
+ { 0x08a8, 0x23a3 },
+ { 0x08a9, 0x23a4 },
+ { 0x08aa, 0x23a6 },
+ { 0x08ab, 0x239b },
+ { 0x08ac, 0x239d },
+ { 0x08ad, 0x239e },
+ { 0x08ae, 0x23a0 },
+ { 0x08af, 0x23a8 },
+ { 0x08b0, 0x23ac },
+ { 0x08bc, 0x2264 },
+ { 0x08bd, 0x2260 },
+ { 0x08be, 0x2265 },
+ { 0x08bf, 0x222b },
+ { 0x08c0, 0x2234 },
+ { 0x08c1, 0x221d },
+ { 0x08c2, 0x221e },
+ { 0x08c5, 0x2207 },
+ { 0x08c8, 0x223c },
+ { 0x08c9, 0x2243 },
+ { 0x08cd, 0x21d4 },
+ { 0x08ce, 0x21d2 },
+ { 0x08cf, 0x2261 },
+ { 0x08d6, 0x221a },
+ { 0x08da, 0x2282 },
+ { 0x08db, 0x2283 },
+ { 0x08dc, 0x2229 },
+ { 0x08dd, 0x222a },
+ { 0x08de, 0x2227 },
+ { 0x08df, 0x2228 },
+ { 0x08ef, 0x2202 },
+ { 0x08f6, 0x0192 },
+ { 0x08fb, 0x2190 },
+ { 0x08fc, 0x2191 },
+ { 0x08fd, 0x2192 },
+ { 0x08fe, 0x2193 },
+ { 0x09e0, 0x25c6 },
+ { 0x09e1, 0x2592 },
+ { 0x09e2, 0x2409 },
+ { 0x09e3, 0x240c },
+ { 0x09e4, 0x240d },
+ { 0x09e5, 0x240a },
+ { 0x09e8, 0x2424 },
+ { 0x09e9, 0x240b },
+ { 0x09ea, 0x2518 },
+ { 0x09eb, 0x2510 },
+ { 0x09ec, 0x250c },
+ { 0x09ed, 0x2514 },
+ { 0x09ee, 0x253c },
+ { 0x09ef, 0x23ba },
+ { 0x09f0, 0x23bb },
+ { 0x09f1, 0x2500 },
+ { 0x09f2, 0x23bc },
+ { 0x09f3, 0x23bd },
+ { 0x09f4, 0x251c },
+ { 0x09f5, 0x2524 },
+ { 0x09f6, 0x2534 },
+ { 0x09f7, 0x252c },
+ { 0x09f8, 0x2502 },
+ { 0x0aa1, 0x2003 },
+ { 0x0aa2, 0x2002 },
+ { 0x0aa3, 0x2004 },
+ { 0x0aa4, 0x2005 },
+ { 0x0aa5, 0x2007 },
+ { 0x0aa6, 0x2008 },
+ { 0x0aa7, 0x2009 },
+ { 0x0aa8, 0x200a },
+ { 0x0aa9, 0x2014 },
+ { 0x0aaa, 0x2013 },
+ { 0x0aae, 0x2026 },
+ { 0x0aaf, 0x2025 },
+ { 0x0ab0, 0x2153 },
+ { 0x0ab1, 0x2154 },
+ { 0x0ab2, 0x2155 },
+ { 0x0ab3, 0x2156 },
+ { 0x0ab4, 0x2157 },
+ { 0x0ab5, 0x2158 },
+ { 0x0ab6, 0x2159 },
+ { 0x0ab7, 0x215a },
+ { 0x0ab8, 0x2105 },
+ { 0x0abb, 0x2012 },
+ { 0x0abc, 0x2329 },
+ { 0x0abe, 0x232a },
+ { 0x0ac3, 0x215b },
+ { 0x0ac4, 0x215c },
+ { 0x0ac5, 0x215d },
+ { 0x0ac6, 0x215e },
+ { 0x0ac9, 0x2122 },
+ { 0x0aca, 0x2613 },
+ { 0x0acc, 0x25c1 },
+ { 0x0acd, 0x25b7 },
+ { 0x0ace, 0x25cb },
+ { 0x0acf, 0x25af },
+ { 0x0ad0, 0x2018 },
+ { 0x0ad1, 0x2019 },
+ { 0x0ad2, 0x201c },
+ { 0x0ad3, 0x201d },
+ { 0x0ad4, 0x211e },
+ { 0x0ad6, 0x2032 },
+ { 0x0ad7, 0x2033 },
+ { 0x0ad9, 0x271d },
+ { 0x0adb, 0x25ac },
+ { 0x0adc, 0x25c0 },
+ { 0x0add, 0x25b6 },
+ { 0x0ade, 0x25cf },
+ { 0x0adf, 0x25ae },
+ { 0x0ae0, 0x25e6 },
+ { 0x0ae1, 0x25ab },
+ { 0x0ae2, 0x25ad },
+ { 0x0ae3, 0x25b3 },
+ { 0x0ae4, 0x25bd },
+ { 0x0ae5, 0x2606 },
+ { 0x0ae6, 0x2022 },
+ { 0x0ae7, 0x25aa },
+ { 0x0ae8, 0x25b2 },
+ { 0x0ae9, 0x25bc },
+ { 0x0aea, 0x261c },
+ { 0x0aeb, 0x261e },
+ { 0x0aec, 0x2663 },
+ { 0x0aed, 0x2666 },
+ { 0x0aee, 0x2665 },
+ { 0x0af0, 0x2720 },
+ { 0x0af1, 0x2020 },
+ { 0x0af2, 0x2021 },
+ { 0x0af3, 0x2713 },
+ { 0x0af4, 0x2717 },
+ { 0x0af5, 0x266f },
+ { 0x0af6, 0x266d },
+ { 0x0af7, 0x2642 },
+ { 0x0af8, 0x2640 },
+ { 0x0af9, 0x260e },
+ { 0x0afa, 0x2315 },
+ { 0x0afb, 0x2117 },
+ { 0x0afc, 0x2038 },
+ { 0x0afd, 0x201a },
+ { 0x0afe, 0x201e },
+ { 0x0ba3, 0x003c },
+ { 0x0ba6, 0x003e },
+ { 0x0ba8, 0x2228 },
+ { 0x0ba9, 0x2227 },
+ { 0x0bc0, 0x00af },
+ { 0x0bc2, 0x22a5 },
+ { 0x0bc3, 0x2229 },
+ { 0x0bc4, 0x230a },
+ { 0x0bc6, 0x005f },
+ { 0x0bca, 0x2218 },
+ { 0x0bcc, 0x2395 },
+ { 0x0bce, 0x22a4 },
+ { 0x0bcf, 0x25cb },
+ { 0x0bd3, 0x2308 },
+ { 0x0bd6, 0x222a },
+ { 0x0bd8, 0x2283 },
+ { 0x0bda, 0x2282 },
+ { 0x0bdc, 0x22a2 },
+ { 0x0bfc, 0x22a3 },
+ { 0x0cdf, 0x2017 },
+ { 0x0ce0, 0x05d0 },
+ { 0x0ce1, 0x05d1 },
+ { 0x0ce2, 0x05d2 },
+ { 0x0ce3, 0x05d3 },
+ { 0x0ce4, 0x05d4 },
+ { 0x0ce5, 0x05d5 },
+ { 0x0ce6, 0x05d6 },
+ { 0x0ce7, 0x05d7 },
+ { 0x0ce8, 0x05d8 },
+ { 0x0ce9, 0x05d9 },
+ { 0x0cea, 0x05da },
+ { 0x0ceb, 0x05db },
+ { 0x0cec, 0x05dc },
+ { 0x0ced, 0x05dd },
+ { 0x0cee, 0x05de },
+ { 0x0cef, 0x05df },
+ { 0x0cf0, 0x05e0 },
+ { 0x0cf1, 0x05e1 },
+ { 0x0cf2, 0x05e2 },
+ { 0x0cf3, 0x05e3 },
+ { 0x0cf4, 0x05e4 },
+ { 0x0cf5, 0x05e5 },
+ { 0x0cf6, 0x05e6 },
+ { 0x0cf7, 0x05e7 },
+ { 0x0cf8, 0x05e8 },
+ { 0x0cf9, 0x05e9 },
+ { 0x0cfa, 0x05ea },
+ { 0x0da1, 0x0e01 },
+ { 0x0da2, 0x0e02 },
+ { 0x0da3, 0x0e03 },
+ { 0x0da4, 0x0e04 },
+ { 0x0da5, 0x0e05 },
+ { 0x0da6, 0x0e06 },
+ { 0x0da7, 0x0e07 },
+ { 0x0da8, 0x0e08 },
+ { 0x0da9, 0x0e09 },
+ { 0x0daa, 0x0e0a },
+ { 0x0dab, 0x0e0b },
+ { 0x0dac, 0x0e0c },
+ { 0x0dad, 0x0e0d },
+ { 0x0dae, 0x0e0e },
+ { 0x0daf, 0x0e0f },
+ { 0x0db0, 0x0e10 },
+ { 0x0db1, 0x0e11 },
+ { 0x0db2, 0x0e12 },
+ { 0x0db3, 0x0e13 },
+ { 0x0db4, 0x0e14 },
+ { 0x0db5, 0x0e15 },
+ { 0x0db6, 0x0e16 },
+ { 0x0db7, 0x0e17 },
+ { 0x0db8, 0x0e18 },
+ { 0x0db9, 0x0e19 },
+ { 0x0dba, 0x0e1a },
+ { 0x0dbb, 0x0e1b },
+ { 0x0dbc, 0x0e1c },
+ { 0x0dbd, 0x0e1d },
+ { 0x0dbe, 0x0e1e },
+ { 0x0dbf, 0x0e1f },
+ { 0x0dc0, 0x0e20 },
+ { 0x0dc1, 0x0e21 },
+ { 0x0dc2, 0x0e22 },
+ { 0x0dc3, 0x0e23 },
+ { 0x0dc4, 0x0e24 },
+ { 0x0dc5, 0x0e25 },
+ { 0x0dc6, 0x0e26 },
+ { 0x0dc7, 0x0e27 },
+ { 0x0dc8, 0x0e28 },
+ { 0x0dc9, 0x0e29 },
+ { 0x0dca, 0x0e2a },
+ { 0x0dcb, 0x0e2b },
+ { 0x0dcc, 0x0e2c },
+ { 0x0dcd, 0x0e2d },
+ { 0x0dce, 0x0e2e },
+ { 0x0dcf, 0x0e2f },
+ { 0x0dd0, 0x0e30 },
+ { 0x0dd1, 0x0e31 },
+ { 0x0dd2, 0x0e32 },
+ { 0x0dd3, 0x0e33 },
+ { 0x0dd4, 0x0e34 },
+ { 0x0dd5, 0x0e35 },
+ { 0x0dd6, 0x0e36 },
+ { 0x0dd7, 0x0e37 },
+ { 0x0dd8, 0x0e38 },
+ { 0x0dd9, 0x0e39 },
+ { 0x0dda, 0x0e3a },
+ { 0x0ddf, 0x0e3f },
+ { 0x0de0, 0x0e40 },
+ { 0x0de1, 0x0e41 },
+ { 0x0de2, 0x0e42 },
+ { 0x0de3, 0x0e43 },
+ { 0x0de4, 0x0e44 },
+ { 0x0de5, 0x0e45 },
+ { 0x0de6, 0x0e46 },
+ { 0x0de7, 0x0e47 },
+ { 0x0de8, 0x0e48 },
+ { 0x0de9, 0x0e49 },
+ { 0x0dea, 0x0e4a },
+ { 0x0deb, 0x0e4b },
+ { 0x0dec, 0x0e4c },
+ { 0x0ded, 0x0e4d },
+ { 0x0df0, 0x0e50 },
+ { 0x0df1, 0x0e51 },
+ { 0x0df2, 0x0e52 },
+ { 0x0df3, 0x0e53 },
+ { 0x0df4, 0x0e54 },
+ { 0x0df5, 0x0e55 },
+ { 0x0df6, 0x0e56 },
+ { 0x0df7, 0x0e57 },
+ { 0x0df8, 0x0e58 },
+ { 0x0df9, 0x0e59 },
+ { 0x0ea1, 0x3131 },
+ { 0x0ea2, 0x3132 },
+ { 0x0ea3, 0x3133 },
+ { 0x0ea4, 0x3134 },
+ { 0x0ea5, 0x3135 },
+ { 0x0ea6, 0x3136 },
+ { 0x0ea7, 0x3137 },
+ { 0x0ea8, 0x3138 },
+ { 0x0ea9, 0x3139 },
+ { 0x0eaa, 0x313a },
+ { 0x0eab, 0x313b },
+ { 0x0eac, 0x313c },
+ { 0x0ead, 0x313d },
+ { 0x0eae, 0x313e },
+ { 0x0eaf, 0x313f },
+ { 0x0eb0, 0x3140 },
+ { 0x0eb1, 0x3141 },
+ { 0x0eb2, 0x3142 },
+ { 0x0eb3, 0x3143 },
+ { 0x0eb4, 0x3144 },
+ { 0x0eb5, 0x3145 },
+ { 0x0eb6, 0x3146 },
+ { 0x0eb7, 0x3147 },
+ { 0x0eb8, 0x3148 },
+ { 0x0eb9, 0x3149 },
+ { 0x0eba, 0x314a },
+ { 0x0ebb, 0x314b },
+ { 0x0ebc, 0x314c },
+ { 0x0ebd, 0x314d },
+ { 0x0ebe, 0x314e },
+ { 0x0ebf, 0x314f },
+ { 0x0ec0, 0x3150 },
+ { 0x0ec1, 0x3151 },
+ { 0x0ec2, 0x3152 },
+ { 0x0ec3, 0x3153 },
+ { 0x0ec4, 0x3154 },
+ { 0x0ec5, 0x3155 },
+ { 0x0ec6, 0x3156 },
+ { 0x0ec7, 0x3157 },
+ { 0x0ec8, 0x3158 },
+ { 0x0ec9, 0x3159 },
+ { 0x0eca, 0x315a },
+ { 0x0ecb, 0x315b },
+ { 0x0ecc, 0x315c },
+ { 0x0ecd, 0x315d },
+ { 0x0ece, 0x315e },
+ { 0x0ecf, 0x315f },
+ { 0x0ed0, 0x3160 },
+ { 0x0ed1, 0x3161 },
+ { 0x0ed2, 0x3162 },
+ { 0x0ed3, 0x3163 },
+ { 0x0ed4, 0x11a8 },
+ { 0x0ed5, 0x11a9 },
+ { 0x0ed6, 0x11aa },
+ { 0x0ed7, 0x11ab },
+ { 0x0ed8, 0x11ac },
+ { 0x0ed9, 0x11ad },
+ { 0x0eda, 0x11ae },
+ { 0x0edb, 0x11af },
+ { 0x0edc, 0x11b0 },
+ { 0x0edd, 0x11b1 },
+ { 0x0ede, 0x11b2 },
+ { 0x0edf, 0x11b3 },
+ { 0x0ee0, 0x11b4 },
+ { 0x0ee1, 0x11b5 },
+ { 0x0ee2, 0x11b6 },
+ { 0x0ee3, 0x11b7 },
+ { 0x0ee4, 0x11b8 },
+ { 0x0ee5, 0x11b9 },
+ { 0x0ee6, 0x11ba },
+ { 0x0ee7, 0x11bb },
+ { 0x0ee8, 0x11bc },
+ { 0x0ee9, 0x11bd },
+ { 0x0eea, 0x11be },
+ { 0x0eeb, 0x11bf },
+ { 0x0eec, 0x11c0 },
+ { 0x0eed, 0x11c1 },
+ { 0x0eee, 0x11c2 },
+ { 0x0eef, 0x316d },
+ { 0x0ef0, 0x3171 },
+ { 0x0ef1, 0x3178 },
+ { 0x0ef2, 0x317f },
+ { 0x0ef3, 0x3181 },
+ { 0x0ef4, 0x3184 },
+ { 0x0ef5, 0x3186 },
+ { 0x0ef6, 0x318d },
+ { 0x0ef7, 0x318e },
+ { 0x0ef8, 0x11eb },
+ { 0x0ef9, 0x11f0 },
+ { 0x0efa, 0x11f9 },
+ { 0x0eff, 0x20a9 },
+#if 0
+ /* FIXME: there is no keysym 0x13a4? But 0x20ac is EuroSign in both
+ keysym and Unicode */
+ { 0x13a4, 0x20ac },
+#endif
+ { 0x13bc, 0x0152 },
+ { 0x13bd, 0x0153 },
+ { 0x13be, 0x0178 },
+ { 0x20ac, 0x20ac },
+
+ /* Special function keys. */
+
+ { 0xff08, 0x0008 }, /* XK_BackSpace */
+ { 0xff09, 0x0009 }, /* XK_Tab */
+ { 0xff0a, 0x000a }, /* XK_Linefeed */
+ { 0xff0d, 0x000d }, /* XK_Return */
+ { 0xff13, 0x0013 }, /* XK_Pause */
+ { 0xff1b, 0x001b }, /* XK_Escape */
+ { 0xff50, 0x0001 }, /* XK_Home */
+ { 0xff51, 0x001c }, /* XK_Left */
+ { 0xff52, 0x001e }, /* XK_Up */
+ { 0xff53, 0x001d }, /* XK_Right */
+ { 0xff54, 0x001f }, /* XK_Down */
+ { 0xff55, 0x000b }, /* XK_Prior */
+ { 0xff56, 0x000c }, /* XK_Next */
+ { 0xff57, 0x0004 }, /* XK_End */
+ { 0xff6a, 0x0005 }, /* XK_Help */
+ { 0xffff, 0x007f }, /* XK_Delete */
+};
+
+long keysym2ucs(int keysym)
+{
+ int min = 0;
+ int max = sizeof(keysymtab) / sizeof(struct codepair) - 1;
+ int mid;
+
+ /* first check for Latin-1 characters (1:1 mapping) */
+ if ((keysym >= 0x0020 && keysym <= 0x007e) ||
+ (keysym >= 0x00a0 && keysym <= 0x00ff))
+ return keysym;
+
+ /* also check for directly encoded 24-bit UCS characters */
+ if ((keysym & 0xff000000) == 0x01000000)
+ return keysym & 0x00ffffff;
+
+ /* binary search in table */
+ while (max >= min) {
+ mid = (min + max) / 2;
+ if (keysymtab[mid].keysym < keysym)
+ min = mid + 1;
+ else if (keysymtab[mid].keysym > keysym)
+ max = mid - 1;
+ else {
+ /* found it */
+ return keysymtab[mid].ucs;
+ }
+ }
+
+ /* no matching Unicode value found */
+ return -1;
+}
+
+static int reverse_compare (const void *a, const void *b)
+{
+ const struct codepair *ca = a, *cb = b;
+
+ return ca->ucs - cb->ucs;
+}
+
+int ucs2keysym(long ucs)
+{
+ static struct codepair *reverse_keysymtab;
+
+ int min = 0;
+ int max = sizeof(keysymtab) / sizeof(struct codepair) - 1;
+ int mid;
+
+ if (reverse_keysymtab == NULL)
+ {
+ reverse_keysymtab = malloc (sizeof (keysymtab));
+ memcpy (reverse_keysymtab, keysymtab, sizeof (keysymtab));
+
+ qsort (reverse_keysymtab,
+ sizeof (keysymtab) / sizeof (struct codepair),
+ sizeof (struct codepair),
+ reverse_compare);
+ }
+
+ /* first check for Latin-1 characters (1:1 mapping) */
+ if ((ucs >= 0x0020 && ucs <= 0x007e) ||
+ (ucs >= 0x00a0 && ucs <= 0x00ff))
+ return ucs;
+
+ /* binary search in table */
+ while (max >= min) {
+ mid = (min + max) / 2;
+ if (reverse_keysymtab[mid].ucs < ucs)
+ min = mid + 1;
+ else if (reverse_keysymtab[mid].ucs > ucs)
+ max = mid - 1;
+ else {
+ /* found it */
+ return reverse_keysymtab[mid].keysym;
+ }
+ }
+
+ /* finally, assume a directly encoded 24-bit UCS character */
+ return ucs | 0x01000000;
+}
--- /dev/null
+/* $XFree86$
+ * This module converts keysym values into the corresponding ISO 10646
+ * (UCS, Unicode) values.
+ *
+ * The array keysymtab[] contains pairs of X11 keysym values for graphical
+ * characters and the corresponding Unicode value. The function
+ * keysym2ucs() maps a keysym onto a Unicode value using a binary search,
+ * therefore keysymtab[] must remain SORTED by keysym value.
+ *
+ * The keysym -> UTF-8 conversion will hopefully one day be provided
+ * by Xlib via XmbLookupString() and should ideally not have to be
+ * done in X applications. But we are not there yet.
+ *
+ * We allow to represent any UCS character in the range U-00000000 to
+ * U-00FFFFFF by a keysym value in the range 0x01000000 to 0x01ffffff.
+ * This admittedly does not cover the entire 31-bit space of UCS, but
+ * it does cover all of the characters up to U-10FFFF, which can be
+ * represented by UTF-16, and more, and it is very unlikely that higher
+ * UCS codes will ever be assigned by ISO. So to get Unicode character
+ * U+ABCD you can directly use keysym 0x0100abcd.
+ *
+ * Author: Markus G. Kuhn <mkuhn@acm.org>, University of Cambridge, April 2001
+ *
+ * Special thanks to Richard Verhoeven <river@win.tue.nl> for preparing
+ * an initial draft of the mapping table.
+ *
+ * This software is in the public domain. Share and enjoy!
+ */
+
+#ifndef KEYSYM2UCS_H
+#define KEYSYM2UCS_H 1
+
+extern long keysym2ucs(int keysym);
+extern int ucs2keysym(long ucs);
+
+#endif /* KEYSYM2UCS_H */
--- /dev/null
+/*
+ * Minimal implementation of PanoramiX/Xinerama
+ *
+ * This is used in rootless mode where the underlying window server
+ * already provides an abstracted view of multiple screens as one
+ * large screen area.
+ *
+ * This code is largely based on panoramiX.c, which contains the
+ * following copyright notice:
+ */
+/*****************************************************************
+Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts.
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING,
+BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of Digital Equipment Corporation
+shall not be used in advertising or otherwise to promote the sale, use or other
+dealings in this Software without prior written authorization from Digital
+Equipment Corporation.
+******************************************************************/
+/* $XFree86: xc/programs/Xserver/hw/darwin/quartz/pseudoramiX.c,v 1.1 2002/03/28 02:21:18 torrey Exp $ */
+
+#include "pseudoramiX.h"
+
+#include "extnsionst.h"
+#include "dixstruct.h"
+#include "window.h"
+#include "panoramiXproto.h"
+#include "globals.h"
+
+extern int ProcPanoramiXQueryVersion (ClientPtr client);
+
+static void PseudoramiXResetProc(ExtensionEntry *extEntry);
+
+static int ProcPseudoramiXQueryVersion(ClientPtr client);
+static int ProcPseudoramiXGetState(ClientPtr client);
+static int ProcPseudoramiXGetScreenCount(ClientPtr client);
+static int ProcPseudoramiXGetScreenSize(ClientPtr client);
+static int ProcPseudoramiXIsActive(ClientPtr client);
+static int ProcPseudoramiXQueryScreens(ClientPtr client);
+static int ProcPseudoramiXDispatch(ClientPtr client);
+
+static int SProcPseudoramiXQueryVersion(ClientPtr client);
+static int SProcPseudoramiXGetState(ClientPtr client);
+static int SProcPseudoramiXGetScreenCount(ClientPtr client);
+static int SProcPseudoramiXGetScreenSize(ClientPtr client);
+static int SProcPseudoramiXIsActive(ClientPtr client);
+static int SProcPseudoramiXQueryScreens(ClientPtr client);
+static int SProcPseudoramiXDispatch(ClientPtr client);
+
+
+typedef struct {
+ int x;
+ int y;
+ int w;
+ int h;
+} PseudoramiXScreenRec;
+
+static PseudoramiXScreenRec *pseudoramiXScreens = NULL;
+static int pseudoramiXScreensAllocated = 0;
+static int pseudoramiXNumScreens = 0;
+static int pseudoramiXGeneration = -1;
+
+
+// Add a PseudoramiX screen.
+// The rest of the X server will know nothing about this screen.
+// Can be called before or after extension init.
+// Screens must be re-added once per generation.
+void
+PseudoramiXAddScreen(int x, int y, int w, int h)
+{
+ PseudoramiXScreenRec *s;
+
+ if (noPseudoramiXExtension) return;
+
+ if (pseudoramiXNumScreens == pseudoramiXScreensAllocated) {
+ pseudoramiXScreensAllocated += pseudoramiXScreensAllocated + 1;
+ pseudoramiXScreens = xrealloc(pseudoramiXScreens,
+ pseudoramiXScreensAllocated *
+ sizeof(PseudoramiXScreenRec));
+ }
+
+ s = &pseudoramiXScreens[pseudoramiXNumScreens++];
+ s->x = x;
+ s->y = y;
+ s->w = w;
+ s->h = h;
+}
+
+
+// Initialize PseudoramiX.
+// Copied from PanoramiXExtensionInit
+void PseudoramiXExtensionInit(int argc, char *argv[])
+{
+ Bool success = FALSE;
+ ExtensionEntry *extEntry;
+
+ if (noPseudoramiXExtension) return;
+
+#if 0
+ if (pseudoramiXNumScreens == 1) {
+ // Only one screen - disable Xinerama extension.
+ noPseudoramiXExtension = TRUE;
+ return;
+ }
+#endif
+
+ // The server must not run the PanoramiX operations.
+ noPanoramiXExtension = TRUE;
+
+ if (pseudoramiXGeneration != serverGeneration) {
+ extEntry = AddExtension(PANORAMIX_PROTOCOL_NAME, 0, 0,
+ ProcPseudoramiXDispatch,
+ SProcPseudoramiXDispatch,
+ PseudoramiXResetProc,
+ StandardMinorOpcode);
+ if (!extEntry) {
+ ErrorF("PseudoramiXExtensionInit(): AddExtension failed\n");
+ } else {
+ pseudoramiXGeneration = serverGeneration;
+ success = TRUE;
+ }
+ }
+
+ if (!success) {
+ ErrorF("%s Extension (PseudoramiX) failed to initialize\n",
+ PANORAMIX_PROTOCOL_NAME);
+ return;
+ }
+}
+
+
+static void PseudoramiXResetProc(ExtensionEntry *extEntry)
+{
+ pseudoramiXNumScreens = 0;
+}
+
+void PseudoramiXResetScreens (void)
+{
+ pseudoramiXNumScreens = 0;
+}
+
+// was PanoramiX
+static int ProcPseudoramiXQueryVersion(ClientPtr client)
+{
+ return ProcPanoramiXQueryVersion(client);
+}
+
+
+// was PanoramiX
+static int ProcPseudoramiXGetState(ClientPtr client)
+{
+ REQUEST(xPanoramiXGetStateReq);
+ WindowPtr pWin;
+ xPanoramiXGetStateReply rep;
+ register int n;
+
+ REQUEST_SIZE_MATCH(xPanoramiXGetStateReq);
+ pWin = LookupWindow (stuff->window, client);
+ if (!pWin)
+ return BadWindow;
+ rep.type = X_Reply;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+ rep.state = !noPseudoramiXExtension;
+ if (client->swapped) {
+ swaps (&rep.sequenceNumber, n);
+ swapl (&rep.length, n);
+ swaps (&rep.state, n);
+ }
+ WriteToClient (client, sizeof (xPanoramiXGetStateReply), (char *) &rep);
+ return client->noClientException;
+}
+
+
+// was PanoramiX
+static int ProcPseudoramiXGetScreenCount(ClientPtr client)
+{
+ REQUEST(xPanoramiXGetScreenCountReq);
+ WindowPtr pWin;
+ xPanoramiXGetScreenCountReply rep;
+ register int n;
+
+ REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq);
+ pWin = LookupWindow (stuff->window, client);
+ if (!pWin)
+ return BadWindow;
+ rep.type = X_Reply;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+ rep.ScreenCount = pseudoramiXNumScreens;
+ if (client->swapped) {
+ swaps (&rep.sequenceNumber, n);
+ swapl (&rep.length, n);
+ swaps (&rep.ScreenCount, n);
+ }
+ WriteToClient (client, sizeof(xPanoramiXGetScreenCountReply), (char *)&rep);
+ return client->noClientException;
+}
+
+
+// was PanoramiX
+static int ProcPseudoramiXGetScreenSize(ClientPtr client)
+{
+ REQUEST(xPanoramiXGetScreenSizeReq);
+ WindowPtr pWin;
+ xPanoramiXGetScreenSizeReply rep;
+ register int n;
+
+ REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq);
+ pWin = LookupWindow (stuff->window, client);
+ if (!pWin)
+ return BadWindow;
+ rep.type = X_Reply;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+ /* screen dimensions */
+ rep.width = pseudoramiXScreens[stuff->screen].w;
+ // was panoramiXdataPtr[stuff->screen].width;
+ rep.height = pseudoramiXScreens[stuff->screen].h;
+ // was panoramiXdataPtr[stuff->screen].height;
+ if (client->swapped) {
+ swaps (&rep.sequenceNumber, n);
+ swapl (&rep.length, n);
+ swaps (&rep.width, n);
+ swaps (&rep.height, n);
+ }
+ WriteToClient (client, sizeof(xPanoramiXGetScreenSizeReply), (char *)&rep);
+ return client->noClientException;
+}
+
+
+// was Xinerama
+static int ProcPseudoramiXIsActive(ClientPtr client)
+{
+ /* REQUEST(xXineramaIsActiveReq); */
+ xXineramaIsActiveReply rep;
+
+ REQUEST_SIZE_MATCH(xXineramaIsActiveReq);
+
+ rep.type = X_Reply;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+ rep.state = !noPseudoramiXExtension;
+ if (client->swapped) {
+ register int n;
+ swaps (&rep.sequenceNumber, n);
+ swapl (&rep.length, n);
+ swapl (&rep.state, n);
+ }
+ WriteToClient (client, sizeof (xXineramaIsActiveReply), (char *) &rep);
+ return client->noClientException;
+}
+
+
+// was Xinerama
+static int ProcPseudoramiXQueryScreens(ClientPtr client)
+{
+ /* REQUEST(xXineramaQueryScreensReq); */
+ xXineramaQueryScreensReply rep;
+
+ REQUEST_SIZE_MATCH(xXineramaQueryScreensReq);
+
+ rep.type = X_Reply;
+ rep.sequenceNumber = client->sequence;
+ rep.number = noPseudoramiXExtension ? 0 : pseudoramiXNumScreens;
+ rep.length = rep.number * sz_XineramaScreenInfo >> 2;
+ if (client->swapped) {
+ register int n;
+ swaps (&rep.sequenceNumber, n);
+ swapl (&rep.length, n);
+ swapl (&rep.number, n);
+ }
+ WriteToClient (client, sizeof (xXineramaQueryScreensReply), (char *) &rep);
+
+ if (!noPseudoramiXExtension) {
+ xXineramaScreenInfo scratch;
+ int i;
+
+ for(i = 0; i < pseudoramiXNumScreens; i++) {
+ scratch.x_org = pseudoramiXScreens[i].x;
+ scratch.y_org = pseudoramiXScreens[i].y;
+ scratch.width = pseudoramiXScreens[i].w;
+ scratch.height = pseudoramiXScreens[i].h;
+
+ if(client->swapped) {
+ register int n;
+ swaps (&scratch.x_org, n);
+ swaps (&scratch.y_org, n);
+ swaps (&scratch.width, n);
+ swaps (&scratch.height, n);
+ }
+ WriteToClient (client, sz_XineramaScreenInfo, (char *) &scratch);
+ }
+ }
+
+ return client->noClientException;
+}
+
+
+// was PanoramiX
+static int ProcPseudoramiXDispatch (ClientPtr client)
+{ REQUEST(xReq);
+ switch (stuff->data)
+ {
+ case X_PanoramiXQueryVersion:
+ return ProcPseudoramiXQueryVersion(client);
+ case X_PanoramiXGetState:
+ return ProcPseudoramiXGetState(client);
+ case X_PanoramiXGetScreenCount:
+ return ProcPseudoramiXGetScreenCount(client);
+ case X_PanoramiXGetScreenSize:
+ return ProcPseudoramiXGetScreenSize(client);
+ case X_XineramaIsActive:
+ return ProcPseudoramiXIsActive(client);
+ case X_XineramaQueryScreens:
+ return ProcPseudoramiXQueryScreens(client);
+ }
+ return BadRequest;
+}
+
+
+
+static int
+SProcPseudoramiXQueryVersion (ClientPtr client)
+{
+ REQUEST(xPanoramiXQueryVersionReq);
+ register int n;
+
+ swaps(&stuff->length,n);
+ REQUEST_SIZE_MATCH (xPanoramiXQueryVersionReq);
+ return ProcPseudoramiXQueryVersion(client);
+}
+
+static int
+SProcPseudoramiXGetState(ClientPtr client)
+{
+ REQUEST(xPanoramiXGetStateReq);
+ register int n;
+
+ swaps (&stuff->length, n);
+ REQUEST_SIZE_MATCH(xPanoramiXGetStateReq);
+ return ProcPseudoramiXGetState(client);
+}
+
+static int
+SProcPseudoramiXGetScreenCount(ClientPtr client)
+{
+ REQUEST(xPanoramiXGetScreenCountReq);
+ register int n;
+
+ swaps (&stuff->length, n);
+ REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq);
+ return ProcPseudoramiXGetScreenCount(client);
+}
+
+static int
+SProcPseudoramiXGetScreenSize(ClientPtr client)
+{
+ REQUEST(xPanoramiXGetScreenSizeReq);
+ register int n;
+
+ swaps (&stuff->length, n);
+ REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq);
+ return ProcPseudoramiXGetScreenSize(client);
+}
+
+
+static int
+SProcPseudoramiXIsActive(ClientPtr client)
+{
+ REQUEST(xXineramaIsActiveReq);
+ register int n;
+
+ swaps (&stuff->length, n);
+ REQUEST_SIZE_MATCH(xXineramaIsActiveReq);
+ return ProcPseudoramiXIsActive(client);
+}
+
+
+static int
+SProcPseudoramiXQueryScreens(ClientPtr client)
+{
+ REQUEST(xXineramaQueryScreensReq);
+ register int n;
+
+ swaps (&stuff->length, n);
+ REQUEST_SIZE_MATCH(xXineramaQueryScreensReq);
+ return ProcPseudoramiXQueryScreens(client);
+}
+
+
+static int
+SProcPseudoramiXDispatch (ClientPtr client)
+{ REQUEST(xReq);
+ switch (stuff->data)
+ {
+ case X_PanoramiXQueryVersion:
+ return SProcPseudoramiXQueryVersion(client);
+ case X_PanoramiXGetState:
+ return SProcPseudoramiXGetState(client);
+ case X_PanoramiXGetScreenCount:
+ return SProcPseudoramiXGetScreenCount(client);
+ case X_PanoramiXGetScreenSize:
+ return SProcPseudoramiXGetScreenSize(client);
+ case X_XineramaIsActive:
+ return SProcPseudoramiXIsActive(client);
+ case X_XineramaQueryScreens:
+ return SProcPseudoramiXQueryScreens(client);
+ }
+ return BadRequest;
+}
--- /dev/null
+/*
+ * Minimal implementation of PanoramiX/Xinerama
+ */
+/* $XFree86: xc/programs/Xserver/hw/darwin/quartz/pseudoramiX.h,v 1.1 2002/03/28 02:21:18 torrey Exp $ */
+
+extern int noPseudoramiXExtension;
+
+void PseudoramiXAddScreen(int x, int y, int w, int h);
+void PseudoramiXExtensionInit(int argc, char *argv[]);
+void PseudoramiXResetScreens (void);
--- /dev/null
+//
+// QuartzAudio.m
+//
+// X Window bell support using CoreAudio or AppKit.
+// Greg Parker gparker@cs.stanford.edu 19 Feb 2001
+//
+// Info about sine wave sound playback:
+// CoreAudio code derived from macosx-dev posting by Tim Wood
+// http://www.omnigroup.com/mailman/archive/macosx-dev/2000-May/002004.html
+// Smoothing transitions between sounds
+// http://www.wam.umd.edu/~mphoenix/dss/dss.html
+//
+/*
+ * Copyright (c) 2001 Greg Parker. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name(s) of the above copyright
+ * holders shall not be used in advertising or otherwise to promote the sale,
+ * use or other dealings in this Software without prior written authorization.
+ */
+/* $XFree86: xc/programs/Xserver/hw/darwin/quartz/quartzAudio.c,v 1.1 2002/03/28 02:21:18 torrey Exp $ */
+
+#include "quartz.h"
+#include "quartz-audio.h"
+
+#include <CoreAudio/CoreAudio.h>
+#include <pthread.h>
+
+#include "inputstr.h"
+#include "extensions/XI.h"
+
+void NSBeep();
+
+typedef struct QuartzAudioRec {
+ double frequency;
+ double amplitude;
+
+ UInt32 curFrame;
+ UInt32 remainingFrames;
+ UInt32 totalFrames;
+ UInt32 bytesPerFrame;
+ double sampleRate;
+ UInt32 fadeLength;
+
+ UInt32 bufferByteCount;
+ Boolean playing;
+ pthread_mutex_t lock;
+
+ // used to fade out interrupted sound and avoid 'pop'
+ double prevFrequency;
+ double prevAmplitude;
+ UInt32 prevFrame;
+} QuartzAudioRec;
+
+static AudioDeviceID quartzAudioDevice = kAudioDeviceUnknown;
+static QuartzAudioRec data;
+
+
+/*
+ * QuartzAudioEnvelope
+ * Fade sound in and out to avoid pop.
+ * Sounds with shorter duration will never reach full amplitude. Deal.
+ */
+static double QuartzAudioEnvelope(
+ UInt32 curFrame,
+ UInt32 totalFrames,
+ UInt32 fadeLength )
+{
+ double fadeFrames = min(fadeLength, totalFrames / 2);
+ if (fadeFrames < 1) return 0;
+
+ if (curFrame < fadeFrames) {
+ return curFrame / fadeFrames;
+ } else if (curFrame > totalFrames - fadeFrames) {
+ return (totalFrames-curFrame) / fadeFrames;
+ } else {
+ return 1.0;
+ }
+}
+
+
+/*
+ * QuartzFillBuffer
+ * Fill this buffer with data and update the data position.
+ * FIXME: this is ugly
+ */
+static void QuartzFillBuffer(
+ AudioBuffer *audiobuffer,
+ QuartzAudioRec *data )
+{
+ float *buffer, *b;
+ unsigned int frame, frameCount;
+ unsigned int bufferFrameCount;
+ float multiplier, v;
+ int i;
+
+ buffer = (float *)audiobuffer->mData;
+ bufferFrameCount = audiobuffer->mDataByteSize / data->bytesPerFrame;
+
+ frameCount = min(bufferFrameCount, data->remainingFrames);
+
+ // Fade out previous sine wave, if any.
+ b = buffer;
+ if (data->prevFrame) {
+ multiplier = 2*M_PI*(data->prevFrequency/data->sampleRate);
+ for (frame = 0; frame < data->fadeLength; frame++) {
+ v = data->prevAmplitude *
+ QuartzAudioEnvelope(frame+data->fadeLength,
+ 2*data->fadeLength,
+ data->fadeLength) *
+ sin(multiplier * (data->prevFrame+frame));
+ for (i = 0; i < audiobuffer->mNumberChannels; i++) {
+ *b++ = v;
+ }
+ }
+ // no more prev fade
+ data->prevFrame = 0;
+
+ // adjust for space eaten by prev fade
+ buffer += audiobuffer->mNumberChannels*frame;
+ bufferFrameCount -= frame;
+ frameCount = min(bufferFrameCount, data->remainingFrames);
+ }
+
+ // Write a sine wave with the specified frequency and amplitude
+ multiplier = 2*M_PI*(data->frequency/data->sampleRate);
+ for (frame = 0; frame < frameCount; frame++) {
+ v = data->amplitude *
+ QuartzAudioEnvelope(data->curFrame+frame, data->totalFrames,
+ data->fadeLength) *
+ sin(multiplier * (data->curFrame+frame));
+ for (i = 0; i < audiobuffer->mNumberChannels; i++) {
+ *b++ = v;
+ }
+ }
+
+ // Zero out the rest of the buffer, if any
+ memset(b, 0, sizeof(float) * audiobuffer->mNumberChannels *
+ (bufferFrameCount-frame));
+
+ data->curFrame += frameCount;
+ data->remainingFrames -= frameCount;
+ if (data->remainingFrames == 0) {
+ data->playing = FALSE;
+ data->curFrame = 0;
+ }
+}
+
+
+/*
+ * QuartzAudioIOProc
+ * Callback function for audio playback.
+ * FIXME: use inOutputTime to correct for skipping
+ */
+static OSStatus
+QuartzAudioIOProc(
+ AudioDeviceID inDevice,
+ const AudioTimeStamp *inNow,
+ const AudioBufferList *inInputData,
+ const AudioTimeStamp *inInputTime,
+ AudioBufferList *outOutputData,
+ const AudioTimeStamp *inOutputTime,
+ void *inClientData )
+{
+ QuartzAudioRec *data = (QuartzAudioRec *)inClientData;
+ int i;
+ Boolean wasPlaying;
+
+ pthread_mutex_lock(&data->lock);
+ wasPlaying = data->playing;
+ for (i = 0; i < outOutputData->mNumberBuffers; i++) {
+ if (data->playing) {
+ QuartzFillBuffer(outOutputData->mBuffers+i, data);
+ }
+ else {
+ memset(outOutputData->mBuffers[i].mData, 0,
+ outOutputData->mBuffers[i].mDataByteSize);
+ }
+ }
+ if (wasPlaying && !data->playing) {
+ OSStatus err;
+ err = AudioDeviceStop(inDevice, QuartzAudioIOProc);
+ }
+ pthread_mutex_unlock(&data->lock);
+ return 0;
+}
+
+
+/*
+ * QuartzCoreAudioBell
+ * Play a tone using the CoreAudio API
+ */
+static void QuartzCoreAudioBell(
+ int volume, // volume is % of max
+ int pitch, // pitch is Hz
+ int duration ) // duration is milliseconds
+{
+ if (quartzAudioDevice == kAudioDeviceUnknown) return;
+
+ pthread_mutex_lock(&data.lock);
+
+ // fade previous sound, if any
+ data.prevFrequency = data.frequency;
+ data.prevAmplitude = data.amplitude;
+ data.prevFrame = data.curFrame;
+
+ // set new sound
+ data.frequency = pitch;
+ data.amplitude = volume / 100.0;
+ data.curFrame = 0;
+ data.totalFrames = (int)(data.sampleRate * duration / 1000.0);
+ data.remainingFrames = data.totalFrames;
+
+ if (! data.playing) {
+ OSStatus status;
+ status = AudioDeviceStart(quartzAudioDevice, QuartzAudioIOProc);
+ if (status) {
+ ErrorF("QuartzAudioBell: AudioDeviceStart returned %d\n", status);
+ } else {
+ data.playing = TRUE;
+ }
+ }
+ pthread_mutex_unlock(&data.lock);
+}
+
+
+/*
+ * QuartzBell
+ * Ring the bell
+ */
+void QuartzBell(
+ int volume, // volume in percent of max
+ DeviceIntPtr pDevice,
+ pointer ctrl,
+ int class )
+{
+ int pitch; // pitch in Hz
+ int duration; // duration in milliseconds
+
+ if (class == BellFeedbackClass) {
+ pitch = ((BellCtrl*)ctrl)->pitch;
+ duration = ((BellCtrl*)ctrl)->duration;
+ } else if (class == KbdFeedbackClass) {
+ pitch = ((KeybdCtrl*)ctrl)->bell_pitch;
+ duration = ((KeybdCtrl*)ctrl)->bell_duration;
+ } else {
+ ErrorF("QuartzBell: bad bell class %d\n", class);
+ return;
+ }
+
+ if (quartzUseSysBeep) {
+ if (volume)
+ NSBeep();
+ } else {
+ QuartzCoreAudioBell(volume, pitch, duration);
+ }
+}
+
+
+/*
+ * QuartzAudioInit
+ * Prepare to play the bell with the CoreAudio API
+ */
+void QuartzAudioInit(void)
+{
+ UInt32 propertySize;
+ OSStatus status;
+ AudioDeviceID outputDevice;
+ AudioStreamBasicDescription outputStreamDescription;
+ double sampleRate;
+
+ // Get the default output device
+ propertySize = sizeof(outputDevice);
+ status = AudioHardwareGetProperty(
+ kAudioHardwarePropertyDefaultOutputDevice,
+ &propertySize, &outputDevice);
+ if (status) {
+ ErrorF("QuartzAudioInit: AudioHardwareGetProperty returned %d\n",
+ status);
+ return;
+ }
+ if (outputDevice == kAudioDeviceUnknown) {
+ ErrorF("QuartzAudioInit: No audio output devices available.\n");
+ return;
+ }
+
+ // Get the basic device description
+ propertySize = sizeof(outputStreamDescription);
+ status = AudioDeviceGetProperty(outputDevice, 0, FALSE,
+ kAudioDevicePropertyStreamFormat,
+ &propertySize, &outputStreamDescription);
+ if (status) {
+ ErrorF("QuartzAudioInit: GetProperty(stream format) returned %d\n",
+ status);
+ return;
+ }
+ sampleRate = outputStreamDescription.mSampleRate;
+
+ // Fill in the playback data
+ data.frequency = 0;
+ data.amplitude = 0;
+ data.curFrame = 0;
+ data.remainingFrames = 0;
+ data.bytesPerFrame = outputStreamDescription.mBytesPerFrame;
+ data.sampleRate = sampleRate;
+ // data.bufferByteCount = bufferByteCount;
+ data.playing = FALSE;
+ data.prevAmplitude = 0;
+ data.prevFrame = 0;
+ data.prevFrequency = 0;
+ data.fadeLength = data.sampleRate / 200;
+ pthread_mutex_init(&data.lock, NULL); // fixme error check
+
+ // fixme assert fadeLength<framesPerBuffer
+
+ // Prepare for playback
+ status = AudioDeviceAddIOProc(outputDevice, QuartzAudioIOProc, &data);
+ if (status) {
+ ErrorF("QuartzAudioInit: AddIOProc returned %d\n", status);
+ return;
+ }
+
+ // success!
+ quartzAudioDevice = outputDevice;
+}
--- /dev/null
+//
+// QuartzAudio.h
+//
+// X Window bell support using CoreAudio or AppKit.
+// Greg Parker gparker@cs.stanford.edu 19 Feb 2001
+/*
+ * Copyright (c) 2001 Greg Parker. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name(s) of the above copyright
+ * holders shall not be used in advertising or otherwise to promote the sale,
+ * use or other dealings in this Software without prior written authorization.
+ */
+/* $XFree86: xc/programs/Xserver/hw/darwin/quartz/quartzAudio.h,v 1.1 2002/03/28 02:21:19 torrey Exp $ */
+
+#ifndef _QUARTZAUDIO_H
+#define _QUARTZAUDIO_H
+
+#include "input.h"
+
+void QuartzAudioInit(void);
+void QuartzBell(int volume, DeviceIntPtr pDevice, pointer ctrl, int class);
+
+#endif
--- /dev/null
+/**************************************************************
+ *
+ * Support for using the Quartz Window Manager cursor
+ *
+ **************************************************************/
+/*
+ * Copyright (c) 2001 Torrey T. Lyons and Greg Parker.
+ * Copyright (c) 2002 Apple Computer, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name(s) of the above copyright
+ * holders shall not be used in advertising or otherwise to promote the sale,
+ * use or other dealings in this Software without prior written authorization.
+ */
+/* $XFree86: xc/programs/Xserver/hw/darwin/bundle/quartzCursor.c,v 1.15 2001/12/22 05:28:35 torrey Exp $ */
+
+#include "quartz.h"
+#include "quartz-cursor.h"
+#include "Xplugin.h"
+
+#include "mi.h"
+#include "scrnintstr.h"
+#include "cursorstr.h"
+#include "mipointrst.h"
+#include "windowstr.h"
+#include "globals.h"
+#include "servermd.h"
+#include "dixevents.h"
+
+#include <CoreGraphics/CoreGraphics.h>
+
+typedef struct {
+ int CursorVisible;
+ QueryBestSizeProcPtr QueryBestSize;
+ miPointerSpriteFuncPtr spriteFuncs;
+} QuartzCursorScreenRec, *QuartzCursorScreenPtr;
+
+static int darwinCursorScreenIndex = -1;
+static unsigned long darwinCursorGeneration = 0;
+
+static Bool movedCursor = FALSE;
+
+#define CURSOR_PRIV(pScreen) \
+ ((QuartzCursorScreenPtr)pScreen->devPrivates[darwinCursorScreenIndex].ptr)
+
+static Bool
+load_cursor (CursorPtr src, int screen)
+{
+ uint32_t *data;
+ uint32_t rowbytes;
+ int width, height;
+ int hot_x, hot_y;
+
+ uint32_t fg_color, bg_color;
+ uint8_t *srow, *sptr;
+ uint8_t *mrow, *mptr;
+ uint32_t *drow, *dptr;
+ unsigned xcount, ycount;
+
+ xp_error err;
+
+ width = src->bits->width;
+ height = src->bits->height;
+ hot_x = src->bits->xhot;
+ hot_y = src->bits->yhot;
+
+#ifdef ARGB_CURSOR
+ if (src->bits->argb != NULL)
+ {
+ rowbytes = src->bits->width * sizeof (CARD32);
+ data = (uint32_t *) src->bits->argb;
+ }
+ else
+#endif
+ {
+ fg_color = 0xFF00 | (src->foreRed >> 8);
+ fg_color <<= 16;
+ fg_color |= src->foreGreen & 0xFF00;
+ fg_color |= src->foreBlue >> 8;
+
+ bg_color = 0xFF00 | (src->backRed >> 8);
+ bg_color <<= 16;
+ bg_color |= src->backGreen & 0xFF00;
+ bg_color |= src->backBlue >> 8;
+
+ fg_color = htonl (fg_color);
+ bg_color = htonl (bg_color);
+
+ /* round up to 8 pixel boundary so we can convert whole bytes */
+ rowbytes = ((src->bits->width * 4) + 31) & ~31;
+ data = alloca (rowbytes * src->bits->height);
+
+ if (!src->bits->emptyMask)
+ {
+ ycount = src->bits->height;
+ srow = src->bits->source; mrow = src->bits->mask;
+ drow = data;
+
+ while (ycount-- > 0)
+ {
+ xcount = (src->bits->width + 7) / 8;
+ sptr = srow; mptr = mrow;
+ dptr = drow;
+
+ while (xcount-- > 0)
+ {
+ uint8_t s, m;
+ int i;
+
+ s = *sptr++; m = *mptr++;
+ for (i = 0; i < 8; i++)
+ {
+#if BITMAP_BIT_ORDER == MSBFirst
+ if (m & 128)
+ *dptr++ = (s & 128) ? fg_color : bg_color;
+ else
+ *dptr++ = 0;
+ s <<= 1; m <<= 1;
+#else
+ if (m & 1)
+ *dptr++ = (s & 1) ? fg_color : bg_color;
+ else
+ *dptr++ = 0;
+ s >>= 1; m >>= 1;
+#endif
+ }
+ }
+
+ srow += BitmapBytePad (src->bits->width);
+ mrow += BitmapBytePad (src->bits->width);
+ drow = (uint32_t *) ((char *) drow + rowbytes);
+ }
+ }
+ else
+ {
+ memset (data, 0, src->bits->height * rowbytes);
+ }
+ }
+
+ err = xp_set_cursor (width, height, hot_x, hot_y, data, rowbytes);
+ return err == Success;
+}
+
+/* Convert the X cursor representation to native format if possible. */
+static Bool
+QuartzRealizeCursor (ScreenPtr pScreen, CursorPtr pCursor)
+{
+ if(pCursor == NULL || pCursor->bits == NULL)
+ return FALSE;
+
+ /* FIXME: cache ARGB8888 representation? */
+
+ return TRUE;
+}
+
+/* Free the storage space associated with a realized cursor. */
+static Bool
+QuartzUnrealizeCursor (ScreenPtr pScreen, CursorPtr pCursor)
+{
+ return TRUE;
+}
+
+/* Set the cursor sprite and position. */
+static void
+QuartzSetCursor (ScreenPtr pScreen, CursorPtr pCursor, int x, int y)
+{
+ QuartzCursorScreenPtr ScreenPriv = CURSOR_PRIV(pScreen);
+
+ if (!quartzServerVisible)
+ return;
+
+ if (pCursor == NULL)
+ {
+ if (ScreenPriv->CursorVisible)
+ {
+ xp_hide_cursor ();
+ ScreenPriv->CursorVisible = FALSE;
+ }
+ }
+ else
+ {
+ load_cursor (pCursor, pScreen->myNum);
+
+ if (!ScreenPriv->CursorVisible)
+ {
+ xp_show_cursor ();
+ ScreenPriv->CursorVisible = TRUE;
+ }
+ }
+}
+
+/* Move the cursor. This is a noop for us. */
+static void
+QuartzMoveCursor (ScreenPtr pScreen, int x, int y)
+{
+}
+
+static miPointerSpriteFuncRec quartzSpriteFuncsRec = {
+ QuartzRealizeCursor,
+ QuartzUnrealizeCursor,
+ QuartzSetCursor,
+ QuartzMoveCursor
+};
+
+static Bool
+QuartzCursorOffScreen (ScreenPtr *pScreen, int *x, int *y)
+{
+ return FALSE;
+}
+
+static void
+QuartzCrossScreen (ScreenPtr pScreen, Bool entering)
+{
+ return;
+}
+
+/* Change the cursor position without generating an event or motion history.
+ The input coordinates (x,y) are in pScreen-local X11 coordinates. */
+static void
+QuartzWarpCursor (ScreenPtr pScreen, int x, int y)
+{
+ if (!movedCursor)
+ {
+ /* Don't move the cursor the first time. This is the
+ jump-to-center initialization, and it's annoying. */
+
+ movedCursor = TRUE;
+ return;
+ }
+
+ if (quartzServerVisible)
+ {
+ int sx, sy;
+
+ sx = dixScreenOrigins[pScreen->myNum].x + darwinMainScreenX;
+ sy = dixScreenOrigins[pScreen->myNum].y + darwinMainScreenY;
+
+ CGWarpMouseCursorPosition (CGPointMake (sx + x, sy + y));
+ }
+
+ miPointerWarpCursor (pScreen, x, y);
+}
+
+void
+QuartzIgnoreNextWarpCursor (void)
+{
+ movedCursor = FALSE;
+}
+
+static miPointerScreenFuncRec quartzScreenFuncsRec = {
+ QuartzCursorOffScreen,
+ QuartzCrossScreen,
+ QuartzWarpCursor,
+ DarwinEnqueuePointerEvent,
+};
+
+/* Handle queries for best cursor size */
+static void
+QuartzCursorQueryBestSize (int class, unsigned short *width,
+ unsigned short *height, ScreenPtr pScreen)
+{
+ QuartzCursorScreenPtr ScreenPriv = CURSOR_PRIV(pScreen);
+
+ if (class == CursorShape)
+ {
+ /* FIXME: query window server? */
+ *width = 32;
+ *height = 32;
+ }
+ else
+ {
+ (*ScreenPriv->QueryBestSize) (class, width, height, pScreen);
+ }
+}
+
+/* Initialize cursor support */
+Bool
+QuartzInitCursor (ScreenPtr pScreen)
+{
+ QuartzCursorScreenPtr ScreenPriv;
+ miPointerScreenPtr PointPriv;
+
+ /* initialize software cursor handling (always needed as backup) */
+ if (!miDCInitialize (pScreen, &quartzScreenFuncsRec))
+ return FALSE;
+
+ /* allocate private storage for this screen's QuickDraw cursor info */
+ if (darwinCursorGeneration != serverGeneration)
+ {
+ if ((darwinCursorScreenIndex = AllocateScreenPrivateIndex ()) < 0)
+ return FALSE;
+
+ darwinCursorGeneration = serverGeneration;
+ }
+
+ ScreenPriv = xcalloc (1, sizeof(QuartzCursorScreenRec));
+ if (ScreenPriv == NULL)
+ return FALSE;
+
+ CURSOR_PRIV (pScreen) = ScreenPriv;
+
+ /* override some screen procedures */
+ ScreenPriv->QueryBestSize = pScreen->QueryBestSize;
+ pScreen->QueryBestSize = QuartzCursorQueryBestSize;
+
+ PointPriv = (miPointerScreenPtr) pScreen->devPrivates[miPointerScreenIndex].ptr;
+
+ ScreenPriv->spriteFuncs = PointPriv->spriteFuncs;
+ PointPriv->spriteFuncs = &quartzSpriteFuncsRec;
+
+ ScreenPriv->CursorVisible = TRUE;
+ return TRUE;
+}
+
+/* X server is hiding. Restore the Aqua cursor. */
+void
+QuartzSuspendXCursor (ScreenPtr pScreen)
+{
+}
+
+/* X server is showing. Restore the X cursor. */
+void
+QuartzResumeXCursor (ScreenPtr pScreen)
+{
+ WindowPtr pWin;
+ CursorPtr pCursor;
+ int x, y;
+
+ pWin = GetSpriteWindow ();
+ if (pWin->drawable.pScreen != pScreen)
+ return;
+
+ pCursor = GetSpriteCursor ();
+ if (pCursor == NULL)
+ return;
+
+ GetSpritePosition (&x, &y);
+ QuartzSetCursor (pScreen, pCursor, x, y);
+}
--- /dev/null
+/*
+ * quartzCursor.h
+ *
+ * External interface for Quartz hardware cursor
+ */
+/*
+ * Copyright (c) 2001 Torrey T. Lyons and Greg Parker.
+ * Copyright (c) 2002 Apple Computer, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name(s) of the above copyright
+ * holders shall not be used in advertising or otherwise to promote the sale,
+ * use or other dealings in this Software without prior written authorization.
+ */
+/* $XFree86: xc/programs/Xserver/hw/darwin/quartz/quartzCursor.h,v 1.1 2002/03/28 02:21:19 torrey Exp $ */
+
+#ifndef QUARTZCURSOR_H
+#define QUARTZCURSOR_H
+
+#include "screenint.h"
+
+Bool QuartzInitCursor(ScreenPtr pScreen);
+void QuartzSuspendXCursor(ScreenPtr pScreen);
+void QuartzResumeXCursor(ScreenPtr pScreen);
+void QuartzIgnoreNextWarpCursor (void);
+
+#endif
--- /dev/null
+//
+// quartzServer.c
+//
+// This class handles the interaction between CG and the X server thread
+//
+/*
+ * Copyright (c) 2001 Andreas Monitzer. All Rights Reserved.
+ * Copyright (c) 2002 Torrey T. Lyons. All Rights Reserved.
+ * Copyright (c) 2002 Apple Software, Inc. All Rights Reserved.
+ * Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name(s) of the above copyright
+ * holders shall not be used in advertising or otherwise to promote the
+ * sale, use or other dealings in this Software without prior written
+ * authorization.
+ */
+/* $XFree86: xc/programs/Xserver/hw/darwin/quartz/XServer.m,v 1.3 2002/07/15 18:57:44 torrey Exp $ */
+
+#include "quartz.h"
+#include "Xplugin.h"
+#include "X11Controller.h"
+#define _APPLEDRI_SERVER_
+#include "appledri.h"
+#include "dri-surface.h"
+#include "opaque.h"
+#include "globals.h"
+#include <fcntl.h>
+#include <stdarg.h>
+#include <unistd.h>
+
+char **envpGlobal; // argcGlobal and argvGlobal
+ // are from dix/globals.c
+
+void
+QuartzMessageMainThread (int type, int argc, ...)
+{
+ xEvent xe;
+ INT32 *argv;
+ int i, max_args;
+ va_list args;
+
+ memset (&xe, 0, sizeof (xe));
+ xe.u.u.type = ClientMessage;
+ xe.u.clientMessage.u.l.type = type;
+
+ argv = &xe.u.clientMessage.u.l.longs0;
+ max_args = 4;
+
+ if (argc > 0 && argc <= max_args)
+ {
+ va_start (args, argc);
+ for (i = 0; i < argc; i++)
+ argv[i] = (int) va_arg (args, int);
+ va_end (args);
+ }
+
+ DarwinEnqueueEvent (&xe);
+}
+
+static void
+event_handler (unsigned int type, const void *arg,
+ unsigned int arg_size, void *data)
+{
+ switch (type)
+ {
+ case XP_EVENT_DISPLAY_CHANGED:
+ QuartzMessageMainThread (kXquartzDisplayChanged, 0);
+ break;
+
+ case XP_EVENT_WINDOW_STATE_CHANGED:
+ if (arg_size >= sizeof (xp_window_state_event))
+ {
+ const xp_window_state_event *ws_arg = arg;
+ QuartzMessageMainThread (kXquartzWindowState, 2,
+ ws_arg->id, ws_arg->state);
+ }
+ break;
+
+ case XP_EVENT_WINDOW_MOVED:
+ if (arg_size == sizeof (xp_window_id))
+ {
+ xp_window_id id = * (xp_window_id *) arg;
+
+ QuartzMessageMainThread (kXquartzWindowMoved, 1, id);
+ }
+ break;
+
+ case XP_EVENT_SURFACE_DESTROYED:
+ case XP_EVENT_SURFACE_CHANGED:
+ if (arg_size == sizeof (xp_surface_id))
+ {
+ int kind;
+
+ if (type == XP_EVENT_SURFACE_DESTROYED)
+ kind = AppleDRISurfaceNotifyDestroyed;
+ else
+ kind = AppleDRISurfaceNotifyChanged;
+
+ DRISurfaceNotify (*(xp_surface_id *) arg, kind);
+ }
+ break;
+ }
+}
+
+static void
+server_thread (void *arg)
+{
+ extern int main (int argc, char **argv, char **envp);
+
+ /* Xinerama defaults to enabled */
+ noPanoramiXExtension = FALSE;
+
+ if (xp_init (XP_BACKGROUND_EVENTS | quartzXpluginOptions) != Success)
+ {
+ fprintf (stderr, "can't initialize window system\n");
+ exit (1);
+ }
+
+ xp_select_events (XP_EVENT_DISPLAY_CHANGED
+ | XP_EVENT_WINDOW_STATE_CHANGED
+ | XP_EVENT_WINDOW_MOVED
+ | XP_EVENT_SURFACE_CHANGED
+ | XP_EVENT_SURFACE_DESTROYED,
+ event_handler, NULL);
+
+ exit (main (argcGlobal, argvGlobal, envpGlobal));
+}
+
+/*
+ * DarwinHandleGUI
+ * This function is called first from main(). We use it to connect to
+ * the cg window server and spawn the the thread that will listen for
+ * cg events
+ */
+void DarwinHandleGUI(
+ int argc,
+ char *argv[],
+ char *envp[] )
+{
+ static Bool here_before;
+
+ extern void _InitHLTB (void);
+
+ if (here_before)
+ return;
+
+ here_before = TRUE;
+
+ DarwinInputPreInit ();
+
+ // Store command line arguments to pass back to main()
+ argcGlobal = argc;
+ argvGlobal = argv;
+ envpGlobal = envp;
+
+ /* Initially I ran the X server on the main thread, and received
+ events on the second thread. But now we may be using Carbon,
+ that needs to run on the main thread. (Otherwise, when it's
+ prebound, it will initialize itself on the wrong thread)
+
+ grr.. but doing that means that if the X thread gets scheduled
+ before the main thread when we're _not_ prebound, things fail,
+ so initialize by hand. */
+
+ _InitHLTB ();
+
+ X11ControllerMain (argc, argv, server_thread, NULL);
+
+ /* not reached */
+ exit (1);
+}
--- /dev/null
+/**************************************************************
+ *
+ * Quartz-specific support for the Darwin X Server
+ *
+ **************************************************************/
+/*
+ * Copyright (c) 2001 Greg Parker and Torrey T. Lyons.
+ * Copyright (c) 2002 Apple Computer, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name(s) of the above copyright
+ * holders shall not be used in advertising or otherwise to promote the sale,
+ * use or other dealings in this Software without prior written authorization.
+ */
+/* $XFree86: xc/programs/Xserver/hw/darwin/quartz/quartz.c,v 1.1 2002/03/28 02:21:18 torrey Exp $ */
+
+#include "quartz.h"
+#include "darwin.h"
+#include "quartz-audio.h"
+#include "quartz-cursor.h"
+#include "rootless.h"
+#include "rootless-window.h"
+#include "pseudoramiX.h"
+#include "globals.h"
+#include "dri.h"
+#define _APPLEWM_SERVER_
+#include "applewmstr.h"
+#include "X11Application.h"
+
+#include "scrnintstr.h"
+#include "colormapst.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/wait.h>
+
+#include <AvailabilityMacros.h>
+#include <CoreGraphics/CoreGraphics.h>
+
+/* Shared global variables for Quartz modes */
+int quartzEventWriteFD = -1;
+int quartzUseSysBeep = 1;
+int quartzServerVisible = FALSE;
+int quartzDesiredDepth = -1;
+int quartzHasRoot = FALSE, quartzEnableRootless = TRUE;
+int quartzFullscreenDisableHotkeys = TRUE;
+int noPseudoramiXExtension = FALSE;
+int quartzXpluginOptions = 0;
+
+extern char *display;
+
+static CGDirectDisplayID
+display_at_index (int index)
+{
+ CGError err;
+ CGDisplayCount cnt;
+ CGDirectDisplayID dpy[index+1];
+
+ err = CGGetActiveDisplayList (index + 1, dpy, &cnt);
+ if (err == kCGErrorSuccess && (int) cnt == index + 1)
+ return dpy[index];
+ else
+ return kCGNullDirectDisplay;
+}
+
+static CGRect
+display_screen_bounds (CGDirectDisplayID id, Bool remove_menubar)
+{
+ CGRect frame;
+
+ frame = CGDisplayBounds (id);
+
+ if (remove_menubar && !quartzHasRoot
+ && frame.origin.x == 0 && frame.origin.y == 0)
+ {
+ /* Remove Aqua menubar from display bounds. */
+
+ frame.origin.y += 22;
+ frame.size.height -= 22;
+ }
+
+ return frame;
+}
+
+static void
+addPseudoramiXScreens (int *x, int *y, int *width, int *height)
+{
+ CGDisplayCount i, total = 16; /* FIXME: hardcoded maximum */
+ CGRect unionRect = CGRectNull, frame;
+ CGDirectDisplayID screens[total];
+
+ CGGetActiveDisplayList (total, screens, &total);
+
+ /* Get the union of all screens */
+ for (i = 0; i < total; i++)
+ {
+ CGDirectDisplayID dpy = screens[i];
+
+ /* we can't remove the menubar from the screen - doing so
+ would constrain the pointer to the screen, not allowing it
+ to reach the menubar.. */
+
+ frame = display_screen_bounds (dpy, FALSE);
+ unionRect = CGRectUnion (unionRect, frame);
+ }
+
+ /* Use unionRect as the screen size for the X server. */
+ *x = unionRect.origin.x;
+ *y = unionRect.origin.y;
+ *width = unionRect.size.width;
+ *height = unionRect.size.height;
+
+ /* Tell PseudoramiX about the real screens. */
+ for (i = 0; i < total; i++)
+ {
+ CGDirectDisplayID dpy = screens[i];
+
+ frame = display_screen_bounds (dpy, TRUE);
+
+#ifdef DEBUG
+ ErrorF("PseudoramiX screen %d added: %dx%d @ (%d,%d).\n", i,
+ (int)frame.size.width, (int)frame.size.height,
+ (int)frame.origin.x, (int)frame.origin.y);
+#endif
+
+ frame.origin.x -= unionRect.origin.x;
+ frame.origin.y -= unionRect.origin.y;
+
+#ifdef DEBUG
+ ErrorF("PseudoramiX screen %d placed at X11 coordinate (%d,%d).\n",
+ i, (int)frame.origin.x, (int)frame.origin.y);
+#endif
+
+ PseudoramiXAddScreen(frame.origin.x, frame.origin.y,
+ frame.size.width, frame.size.height);
+ }
+}
+
+/* Do mode dependent initialization of each screen for Quartz. */
+Bool
+QuartzAddScreen (int index, ScreenPtr pScreen)
+{
+ DarwinFramebufferPtr dfb = SCREEN_PRIV(pScreen);
+
+ /* If no specific depth chosen, look for the depth of the main display.
+ Else if 16bpp specified, use that. Else use 32bpp. */
+
+ dfb->componentCount = 3;
+ dfb->bitsPerComponent = 8;
+ dfb->bitsPerPixel = 32;
+
+ if (quartzDesiredDepth == -1)
+ {
+ dfb->bitsPerComponent = CGDisplayBitsPerSample (kCGDirectMainDisplay);
+ dfb->bitsPerPixel = CGDisplayBitsPerPixel (kCGDirectMainDisplay);
+ }
+ else if (quartzDesiredDepth == 15)
+ {
+ dfb->bitsPerComponent = 5;
+ dfb->bitsPerPixel = 16;
+ }
+ else if (quartzDesiredDepth == 8)
+ {
+ dfb->bitsPerComponent = 8;
+ dfb->bitsPerPixel = 8;
+ dfb->componentCount = 1;
+ }
+
+ if (noPseudoramiXExtension)
+ {
+ CGDirectDisplayID dpy;
+ CGRect frame;
+
+ dpy = display_at_index (index);
+
+ frame = display_screen_bounds (dpy, TRUE);
+
+ dfb->x = frame.origin.x;
+ dfb->y = frame.origin.y;
+ dfb->width = frame.size.width;
+ dfb->height = frame.size.height;
+ }
+ else
+ {
+ addPseudoramiXScreens (&dfb->x, &dfb->y, &dfb->width, &dfb->height);
+ }
+
+ dfb->colorBitsPerPixel = dfb->bitsPerComponent * dfb->componentCount;
+
+ /* Passing zero width (pitch) makes miCreateScreenResources set the
+ screen pixmap to the framebuffer pointer, i.e. null. We'll take
+ it from there.. */
+ dfb->pitch = 0;
+ dfb->framebuffer = NULL;
+
+ DRIScreenInit (pScreen);
+
+ return TRUE;
+}
+
+/* Finalize mode specific setup of each screen. */
+Bool
+QuartzSetupScreen (int index, ScreenPtr pScreen)
+{
+ // do full screen or rootless specific setup
+ if (! RootlessSetupScreen(index, pScreen))
+ return FALSE;
+
+ // setup cursor support
+ if (! QuartzInitCursor(pScreen))
+ return FALSE;
+
+ DRIFinishScreenInit (pScreen);
+
+ return TRUE;
+}
+
+
+/* Quartz display initialization. */
+void
+QuartzInitOutput (int argc, char **argv)
+{
+ static int orig_noPanoramiXExtension;
+ int total;
+
+ if (serverGeneration == 1) {
+ orig_noPanoramiXExtension = noPanoramiXExtension;
+ QuartzAudioInit();
+ }
+
+ /* +xinerama option sets noPanoramiXExtension variable */
+ noPseudoramiXExtension = orig_noPanoramiXExtension;
+
+ total = 16; /* FIXME: hardcoded maximum */
+ if (total > 0)
+ {
+ CGDirectDisplayID screens[total];
+ CGGetActiveDisplayList (total, screens, &total);
+ }
+
+ if (noPseudoramiXExtension)
+ darwinScreensFound = total;
+ else
+ darwinScreensFound = 1; // only PseudoramiX knows about the rest
+
+ if (!quartzEnableRootless)
+ RootlessHideAllWindows ();
+}
+
+/* This function from randr.c */
+extern char *ConnectionInfo;
+static int padlength[4] = {0, 3, 2, 1};
+static void
+RREditConnectionInfo (ScreenPtr pScreen)
+{
+ xConnSetup *connSetup;
+ char *vendor;
+ xPixmapFormat *formats;
+ xWindowRoot *root;
+ xDepth *depth;
+ xVisualType *visual;
+ int screen = 0;
+ int d;
+
+ connSetup = (xConnSetup *) ConnectionInfo;
+ vendor = (char *) connSetup + sizeof (xConnSetup);
+ formats = (xPixmapFormat *) ((char *) vendor +
+ connSetup->nbytesVendor +
+ padlength[connSetup->nbytesVendor & 3]);
+ root = (xWindowRoot *) ((char *) formats +
+ sizeof (xPixmapFormat) * screenInfo.numPixmapFormats);
+ while (screen != pScreen->myNum)
+ {
+ depth = (xDepth *) ((char *) root +
+ sizeof (xWindowRoot));
+ for (d = 0; d < root->nDepths; d++)
+ {
+ visual = (xVisualType *) ((char *) depth +
+ sizeof (xDepth));
+ depth = (xDepth *) ((char *) visual +
+ depth->nVisuals * sizeof (xVisualType));
+ }
+ root = (xWindowRoot *) ((char *) depth);
+ screen++;
+ }
+ root->pixWidth = pScreen->width;
+ root->pixHeight = pScreen->height;
+ root->mmWidth = pScreen->mmWidth;
+ root->mmHeight = pScreen->mmHeight;
+}
+
+static void
+QuartzUpdateScreens (void)
+{
+ ScreenPtr pScreen;
+ WindowPtr pRoot;
+ int x, y, width, height, sx, sy;
+ xEvent e;
+
+ if (noPseudoramiXExtension || screenInfo.numScreens != 1)
+ {
+ /* FIXME: if not using Xinerama, we have multiple screens, and
+ to do this properly may need to add or remove screens. Which
+ isn't possible. So don't do anything. Another reason why
+ we default to running with Xinerama. */
+
+ return;
+ }
+
+ pScreen = screenInfo.screens[0];
+
+ PseudoramiXResetScreens ();
+ addPseudoramiXScreens (&x, &y, &width, &height);
+
+ dixScreenOrigins[pScreen->myNum].x = x;
+ dixScreenOrigins[pScreen->myNum].y = y;
+ pScreen->mmWidth = pScreen->mmWidth * ((double) width / pScreen->width);
+ pScreen->mmHeight = pScreen->mmHeight * ((double) height / pScreen->height);
+ pScreen->width = width;
+ pScreen->height = height;
+
+ /* FIXME: should probably do something with RandR here. */
+
+ DarwinAdjustScreenOrigins (&screenInfo);
+ RootlessRepositionWindows (screenInfo.screens[0]);
+ RootlessUpdateScreenPixmap (screenInfo.screens[0]);
+
+ sx = dixScreenOrigins[pScreen->myNum].x + darwinMainScreenX;
+ sy = dixScreenOrigins[pScreen->myNum].y + darwinMainScreenY;
+
+ /* Adjust the root window. */
+
+ pRoot = WindowTable[pScreen->myNum];
+ pScreen->ResizeWindow (pRoot, x - sx, y - sy, width, height, NULL);
+ pScreen->PaintWindowBackground (pRoot, &pRoot->borderClip, PW_BACKGROUND);
+ QuartzIgnoreNextWarpCursor ();
+ DefineInitialRootWindow (pRoot);
+
+ /* Send an event for the root reconfigure */
+
+ e.u.u.type = ConfigureNotify;
+ e.u.configureNotify.window = pRoot->drawable.id;
+ e.u.configureNotify.aboveSibling = None;
+ e.u.configureNotify.x = x - sx;
+ e.u.configureNotify.y = y - sy;
+ e.u.configureNotify.width = width;
+ e.u.configureNotify.height = height;
+ e.u.configureNotify.borderWidth = wBorderWidth (pRoot);
+ e.u.configureNotify.override = pRoot->overrideRedirect;
+ DeliverEvents (pRoot, &e, 1, NullWindow);
+
+ /* FIXME: what does this do? */
+ RREditConnectionInfo (pScreen);
+}
+
+static void
+do_exec (void (*callback) (void *data), void *data)
+{
+ /* Do the fork-twice trick to avoid needing to reap zombies */
+
+ int child1, child2 = 0;
+ int status;
+
+ /* we should really try to report errors here.. */
+
+ child1 = fork ();
+
+ switch (child1)
+ {
+ case -1: /* error */
+ break;
+
+ case 0: /* child1 */
+ child2 = fork ();
+
+ switch (child2)
+ {
+ int max_files, i;
+ char buf[1024], *tem;
+
+ case -1: /* error */
+ _exit (1);
+
+ case 0: /* child2 */
+ /* close all open files except for standard streams */
+ max_files = sysconf (_SC_OPEN_MAX);
+ for (i = 3; i < max_files; i++)
+ close (i);
+
+ /* ensure stdin is on /dev/null */
+ close (0);
+ open ("/dev/null", O_RDONLY);
+
+ /* cd $HOME */
+ tem = getenv ("HOME");
+ if (tem != NULL)
+ chdir (tem);
+
+ /* Setup environment */
+ snprintf (buf, sizeof (buf), ":%s", display);
+ setenv ("DISPLAY", buf, TRUE);
+ tem = getenv ("PATH");
+ if (tem != NULL && tem[0] != NULL)
+ snprintf (buf, sizeof (buf), "%s:/usr/X11R6/bin", tem);
+ else
+ snprintf (buf, sizeof (buf), "/bin:/usr/bin:/usr/X11R6/bin");
+ setenv ("PATH", buf, TRUE);
+
+ (*callback) (data);
+
+ _exit (2);
+
+ default: /* parent (child1) */
+ _exit (0);
+ }
+ break;
+
+ default: /* parent */
+ waitpid (child1, &status, 0);
+ }
+}
+
+static void
+run_client_callback (void *data)
+{
+ char **argv = data;
+ execvp (argv[0], argv);
+}
+
+/* Note that this function is called from both X server and appkit threads */
+void
+QuartzRunClient (const char *command)
+{
+ const char *shell;
+ const char *argv[5];
+
+ shell = getenv ("SHELL");
+ if (shell == NULL)
+ shell = "/bin/bash";
+
+ /* At least [ba]sh, [t]csh and zsh all work with this syntax. We
+ need to use an interactive shell to force it to load the user's
+ environment. Otherwise things like fink don't work at all well.. */
+
+ argv[0] = shell;
+ argv[1] = "-i";
+ argv[2] = "-c";
+ argv[3] = command;
+ argv[4] = NULL;
+
+ do_exec (run_client_callback, argv);
+}
+
+static void
+QuartzSetFullscreen (Bool state)
+{
+ if (quartzHasRoot == state)
+ return;
+
+ quartzHasRoot = state;
+
+ xp_disable_update ();
+
+ if (!quartzHasRoot && !quartzEnableRootless)
+ RootlessHideAllWindows ();
+
+ RootlessUpdateRooted (quartzHasRoot);
+
+ if (quartzHasRoot && !quartzEnableRootless)
+ RootlessShowAllWindows ();
+
+ /* Only update screen info when something is visible. Avoids the wm
+ moving the windows out from under the menubar when it shouldn't */
+
+ if (quartzHasRoot || quartzEnableRootless)
+ QuartzUpdateScreens ();
+
+ /* Somehow the menubar manages to interfere with our event stream
+ in fullscreen mode, even though it's not visible. */
+
+ X11ApplicationShowHideMenubar (!quartzHasRoot);
+
+ xp_reenable_update ();
+
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
+ if (quartzFullscreenDisableHotkeys)
+ xp_disable_hot_keys (quartzHasRoot);
+#endif
+}
+
+static void
+QuartzSetRootless (Bool state)
+{
+ if (quartzEnableRootless == state)
+ return;
+
+ quartzEnableRootless = state;
+
+ if (!quartzEnableRootless && !quartzHasRoot)
+ {
+ xp_disable_update ();
+ RootlessHideAllWindows ();
+ xp_reenable_update ();
+ }
+ else if (quartzEnableRootless && !quartzHasRoot)
+ {
+ xp_disable_update ();
+ RootlessShowAllWindows ();
+ QuartzUpdateScreens ();
+ xp_reenable_update ();
+ }
+}
+
+/* Show the X server on screen. Does nothing if already shown. Restore the
+ X clip regions the X server cursor state. */
+static void
+QuartzShow (void)
+{
+ int i;
+
+ if (quartzServerVisible)
+ return;
+
+ quartzServerVisible = TRUE;
+
+ for (i = 0; i < screenInfo.numScreens; i++)
+ {
+ if (screenInfo.screens[i])
+ QuartzResumeXCursor(screenInfo.screens[i]);
+ }
+
+ /* FIXME: not sure about this, it may need to have a preference like
+ in XDarwin..? */
+
+ if (!quartzEnableRootless)
+ QuartzSetFullscreen (TRUE);
+}
+
+/* Remove the X server display from the screen. Does nothing if already
+ hidden. Set X clip regions to prevent drawing, and restore the Aqua
+ cursor. */
+static void
+QuartzHide (void)
+{
+ int i;
+
+ if (!quartzServerVisible)
+ return;
+
+ for (i = 0; i < screenInfo.numScreens; i++)
+ {
+ if (screenInfo.screens[i])
+ QuartzSuspendXCursor(screenInfo.screens[i]);
+ }
+
+ QuartzSetFullscreen (FALSE);
+
+ quartzServerVisible = FALSE;
+}
+
+/* Cleanup before X server shutdown. Release the screen and restore the
+ Aqua cursor. */
+void
+QuartzGiveUp (void)
+{
+ int i;
+
+ for (i = 0; i < screenInfo.numScreens; i++) {
+ if (screenInfo.screens[i]) {
+ QuartzSuspendXCursor(screenInfo.screens[i]);
+ }
+ }
+}
+
+int
+QuartzProcessArgument( int argc, char *argv[], int i )
+{
+ /* This arg is passed when launched from the Aqua GUI. */
+ if (strncmp (argv[i], "-psn_", 5) == 0)
+ {
+ return 1;
+ }
+
+ if (strcmp (argv[i], "-depth") == 0)
+ {
+ int arg;
+
+ if (i == argc - 1)
+ FatalError ("-depth requires an argument\n");
+
+ arg = atoi (argv[i + 1]);
+ if (arg == 8 || arg == 15 || arg == 24)
+ quartzDesiredDepth = arg;
+ else
+ FatalError ("Only 8, 15 and 24 bit color depths are supported.\n");
+
+ return 2;
+ }
+
+ return 0;
+}
+
+void
+QuartzClientMessage (const xEvent *xe)
+{
+ switch (xe->u.clientMessage.u.l.type)
+ {
+ case kXquartzControllerNotify:
+ AppleWMSendEvent (AppleWMControllerNotify,
+ AppleWMControllerNotifyMask,
+ xe->u.clientMessage.u.l.longs0,
+ xe->u.clientMessage.u.l.longs1);
+ break;
+
+ case kXquartzPasteboardNotify:
+ AppleWMSendEvent (AppleWMPasteboardNotify,
+ AppleWMPasteboardNotifyMask,
+ xe->u.clientMessage.u.l.longs0,
+ xe->u.clientMessage.u.l.longs1);
+ break;
+
+ case kXquartzActivate:
+ QuartzShow ();
+ AppleWMSendEvent (AppleWMActivationNotify,
+ AppleWMActivationNotifyMask,
+ AppleWMIsActive, 0);
+ break;
+
+ case kXquartzDeactivate:
+ AppleWMSendEvent (AppleWMActivationNotify,
+ AppleWMActivationNotifyMask,
+ AppleWMIsInactive, 0);
+ QuartzHide ();
+ break;
+
+ case kXquartzDisplayChanged:
+ QuartzUpdateScreens ();
+ break;
+
+ case kXquartzWindowState:
+ RootlessNativeWindowStateChanged (xe->u.clientMessage.u.l.longs0,
+ xe->u.clientMessage.u.l.longs1);
+ break;
+
+ case kXquartzWindowMoved:
+ RootlessNativeWindowMoved (xe->u.clientMessage.u.l.longs0);
+ break;
+
+ case kXquartzToggleFullscreen:
+ if (quartzEnableRootless)
+ QuartzSetFullscreen (!quartzHasRoot);
+ else if (quartzHasRoot)
+ QuartzHide ();
+ else
+ QuartzShow ();
+ break;
+
+ case kXquartzSetRootless:
+ QuartzSetRootless (xe->u.clientMessage.u.l.longs0);
+ if (!quartzEnableRootless && !quartzHasRoot)
+ QuartzHide ();
+ }
+}
--- /dev/null
+/*
+ * quartz.h
+ *
+ * External interface of the Quartz modes seen by the generic, mode
+ * independent parts of the Darwin X server.
+ */
+/*
+ * Copyright (c) 2001 Greg Parker and Torrey T. Lyons.
+ * Copyright (c) 2002 Apple Computer, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name(s) of the above copyright
+ * holders shall not be used in advertising or otherwise to promote the sale,
+ * use or other dealings in this Software without prior written authorization.
+ */
+/* $XFree86: xc/programs/Xserver/hw/darwin/quartz/quartz.h,v 1.1 2002/03/28 02:21:18 torrey Exp $ */
+
+#ifndef _QUARTZ_H
+#define _QUARTZ_H
+
+#include "darwin.h"
+
+/* Local client message types */
+enum {
+ kXquartzControllerNotify = kXquartzFirstEvent,
+ kXquartzPasteboardNotify,
+ kXquartzActivate,
+ kXquartzDeactivate,
+ kXquartzDisplayChanged,
+ kXquartzWindowState,
+ kXquartzWindowMoved,
+ kXquartzToggleFullscreen,
+ kXquartzSetRootless,
+};
+
+extern int quartzUseSysBeep;
+extern int quartzServerVisible;
+extern int quartzDesiredDepth;
+extern int quartzHasRoot, quartzEnableRootless;
+extern int quartzFullscreenDisableHotkeys;
+extern int quartzXpluginOptions;
+
+int QuartzProcessArgument(int argc, char *argv[], int i);
+void QuartzInitOutput(int argc, char **argv);
+void QuartzGiveUp(void);
+
+void QuartzMessageMainThread (int type, int argc, ...);
+void QuartzClientMessage (const struct _xEvent *xe);
+
+void QuartzRunClient (const char *command);
+
+Bool QuartzAddScreen(int index, ScreenPtr pScreen);
+Bool QuartzSetupScreen(int index, ScreenPtr pScreen);
+
+#endif
--- /dev/null
+/*
+ * Common rootless definitions and code
+ *
+ * Greg Parker gparker@cs.stanford.edu
+ */
+
+/* Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
+
+ Permission is hereby granted, free of charge, to any person
+ obtaining a copy of this software and associated documentation files
+ (the "Software"), to deal in the Software without restriction,
+ including without limitation the rights to use, copy, modify, merge,
+ publish, distribute, sublicense, and/or sell copies of the Software,
+ and to permit persons to whom the Software is furnished to do so,
+ subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT
+ HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ DEALINGS IN THE SOFTWARE.
+
+ Except as contained in this notice, the name(s) of the above
+ copyright holders shall not be used in advertising or otherwise to
+ promote the sale, use or other dealings in this Software without
+ prior written authorization. */
+
+/* $XFree86: xc/programs/Xserver/hw/darwin/quartz/rootlessCommon.c,v 1.6 2002/07/15 19:58:31 torrey Exp $ */
+
+#include "rootless-common.h"
+#include "dri-surface.h"
+#include "fb.h"
+#include "colormapst.h"
+
+RegionRec rootlessHugeRoot = {{-32767, -32767, 32767, 32767}, NULL};
+
+/* Following two macros from miregion.c */
+
+/* true iff two Boxes overlap */
+#define EXTENTCHECK(r1,r2) \
+ (!( ((r1)->x2 <= (r2)->x1) || \
+ ((r1)->x1 >= (r2)->x2) || \
+ ((r1)->y2 <= (r2)->y1) || \
+ ((r1)->y1 >= (r2)->y2) ) )
+
+/* true iff Box r1 contains Box r2 */
+#define SUBSUMES(r1,r2) \
+ ( ((r1)->x1 <= (r2)->x1) && \
+ ((r1)->x2 >= (r2)->x2) && \
+ ((r1)->y1 <= (r2)->y1) && \
+ ((r1)->y2 >= (r2)->y2) )
+
+int rootlessNoDRIDrawing = 0;
+
+/* Returns the top-level parent of pWindow. The root is the top-level
+ parent of itself, even though the root is not otherwise considered
+ to be a top-level window. */
+WindowPtr
+TopLevelParent (WindowPtr pWindow)
+{
+ WindowPtr top;
+
+ if (IsRoot (pWindow))
+ return pWindow;
+
+ top = pWindow;
+ while (top != NULL && !IsTopLevel (top))
+ top = top->parent;
+
+ return top;
+}
+
+/* Returns TRUE if this window is visible inside a frame (e.g. it is
+ visible and has a top-level parent) */
+Bool
+IsFramedWindow (WindowPtr pWin)
+{
+ WindowPtr top;
+
+ if (!pWin->realized)
+ return FALSE;
+
+ top = TopLevelParent (pWin);
+
+ return top != NULL && WINREC (top) != NULL;
+}
+
+void
+TranslatePixmapBase (PixmapPtr pPix, int dx, int dy)
+{
+ unsigned diff;
+
+ pPix->devPrivate.ptr = ((char *) pPix->devPrivate.ptr +
+ ((dx + pPix->drawable.x)
+ * pPix->drawable.bitsPerPixel / 8 +
+ dy * pPix->devKind));
+
+ if (pPix->drawable.bitsPerPixel != FB_UNIT)
+ {
+ diff = ((unsigned) pPix->devPrivate.ptr) & (FB_UNIT / CHAR_BIT - 1);
+ pPix->devPrivate.ptr = ((char *) pPix->devPrivate.ptr) - diff;
+
+ if (pPix->drawable.bitsPerPixel == 16)
+ pPix->drawable.x = diff / (16 / CHAR_BIT);
+ else if (pPix->drawable.bitsPerPixel == 8)
+ pPix->drawable.x = diff / (8 / CHAR_BIT);
+ else
+ pPix->drawable.x = diff / (pPix->drawable.bitsPerPixel / CHAR_BIT);
+ }
+}
+
+void
+RootlessDisableUpdate (WindowPtr pWin)
+{
+ RootlessWindowRec *winRec = WINREC (pWin);
+
+ if (winRec != NULL
+ && !winRec->is_offscreen
+ && !winRec->is_reorder_pending
+ && !winRec->is_update_disabled)
+ {
+ xp_disable_update ();
+ winRec->is_update_disabled = TRUE;
+ }
+}
+
+void
+RootlessReenableUpdate (WindowPtr pWin)
+{
+ RootlessWindowRec *winRec = WINREC (pWin);
+
+ if (winRec != NULL && winRec->is_update_disabled)
+ {
+ xp_reenable_update ();
+ winRec->is_update_disabled = FALSE;
+ }
+}
+
+Bool
+RootlessResolveColormap (ScreenPtr pScreen, int first_color,
+ int n_colors, uint32_t *colors)
+{
+ int last, i;
+ ColormapPtr map;
+
+ map = RootlessGetColormap (pScreen);
+ if (map == NULL || map->class != PseudoColor)
+ return FALSE;
+
+ last = MIN (map->pVisual->ColormapEntries, first_color + n_colors);
+ for (i = MAX (0, first_color); i < last; i++)
+ {
+ Entry *ent = map->red + i;
+ uint16_t red, green, blue;
+
+ if (!ent->refcnt)
+ continue;
+ if (ent->fShared)
+ {
+ red = ent->co.shco.red->color;
+ green = ent->co.shco.green->color;
+ blue = ent->co.shco.blue->color;
+ }
+ else
+ {
+ red = ent->co.local.red;
+ green = ent->co.local.green;
+ blue = ent->co.local.blue;
+ }
+
+ colors[i - first_color] = (0xFF000000UL
+ | ((uint32_t) red & 0xff00) << 8
+ | (green & 0xff00)
+ | (blue >> 8));
+ }
+
+ return TRUE;
+}
+
+/* Prepare a window for direct access to its backing buffer. Each
+ top-level parent has a Pixmap representing its backing store, which
+ all of its children inherit. */
+void
+RootlessStartDrawing (WindowPtr pWindow)
+{
+ ScreenPtr pScreen = pWindow->drawable.pScreen;
+ WindowPtr top = TopLevelParent (pWindow);
+ RootlessWindowRec *winRec;
+
+ if (!rootlessNoDRIDrawing && DRIStartDrawing (&pWindow->drawable))
+ {
+ return;
+ }
+
+ /* At the top of the stack now. */
+
+ if (top == NULL || WINREC (top) == NULL)
+ return;
+
+ winRec = WINREC(top);
+
+ /* Make sure the window's top-level parent is prepared for drawing. */
+
+ if (!winRec->is_drawing)
+ {
+ void *data[2];
+ unsigned int rowbytes[2];
+ xp_error err;
+
+ int bw = wBorderWidth (top);
+
+ err = xp_lock_window (winRec->wid, NULL, NULL, data, rowbytes, NULL);
+ if (err != Success)
+ abort (); /* FIXME: */
+
+ winRec->data = data[0];
+ winRec->rowbytes = rowbytes[0];
+
+ winRec->pixmap =
+ GetScratchPixmapHeader(pScreen, winRec->width, winRec->height,
+ winRec->win->drawable.depth,
+ winRec->win->drawable.bitsPerPixel,
+ winRec->rowbytes, winRec->data);
+ TranslatePixmapBase (winRec->pixmap,
+ - (top->drawable.x - bw),
+ - (top->drawable.y - bw));
+
+ winRec->is_drawing = TRUE;
+ }
+
+ winRec->oldPixmap = pScreen->GetWindowPixmap (pWindow);
+ pScreen->SetWindowPixmap (pWindow, winRec->pixmap);
+}
+
+void
+RootlessFinishedDrawing (WindowPtr pWindow)
+{
+ /* Called after each drawing primitive, lets us unlock surfaces
+ as often as possible (which is a Good Thing to do.) */
+
+ DRIStopDrawing (&pWindow->drawable, FALSE);
+
+ /* Also, see if we're due a flush. */
+
+ RootlessMayRedisplay (pWindow->drawable.pScreen);
+}
+
+void
+RootlessStopDrawing (WindowPtr pWindow, Bool flush)
+{
+ WindowPtr top = TopLevelParent (pWindow);
+ RootlessWindowRec *winRec;
+
+ if (top == NULL || WINREC (top) == NULL)
+ return;
+
+ winRec = WINREC(top);
+
+ DRIStopDrawing (&pWindow->drawable, flush);
+
+ if (winRec->is_drawing)
+ {
+ ScreenPtr pScreen = pWindow->drawable.pScreen;
+
+ xp_unlock_window (winRec->wid, flush);
+
+ FreeScratchPixmapHeader (winRec->pixmap);
+ pScreen->SetWindowPixmap (pWindow, winRec->oldPixmap);
+ winRec->pixmap = NULL;
+
+ winRec->is_drawing = FALSE;
+ }
+ else if (flush)
+ {
+ xp_flush_window (winRec->wid);
+ }
+
+ /* FIXME: instead of just checking if we tried to flush (which
+ happens everytime we block for I/O), I used to check if
+ anything was actually marked in the window. But that often
+ caused problems with some window managers, and it didn't really
+ make any noticeable difference, so... */
+
+ if (flush && winRec->is_reorder_pending)
+ {
+ winRec->is_reorder_pending = FALSE;
+ RootlessReorderWindow (pWindow);
+ }
+
+ if (flush && winRec->is_update_disabled)
+ {
+ RootlessReenableUpdate (pWindow);
+ }
+}
+
+/* pRegion is GLOBAL */
+void
+RootlessDamageRegion (WindowPtr pWindow, RegionPtr pRegion)
+{
+ RootlessWindowRec *winRec;
+ RegionRec clipped;
+ WindowPtr pTop;
+ BoxPtr b1, b2;
+
+ RL_DEBUG_MSG("Damaged win 0x%x ", pWindow);
+
+ pTop = TopLevelParent (pWindow);
+ if (pTop == NULL)
+ return;
+
+ winRec = WINREC (pTop);
+ if (winRec == NULL)
+ return;
+
+ if (DRIDamageRegion (&pWindow->drawable, pRegion))
+ {
+ return;
+ }
+
+ /* We need to intersect the drawn region with the clip of the window
+ to avoid marking places we didn't actually draw (which can cause
+ problems when the window has an extra client-side backing store)
+
+ But this is a costly operation and since we'll normally just be
+ drawing inside the clip, go to some lengths to avoid the general
+ case intersection. */
+
+ b1 = REGION_EXTENTS (pScreen, &pWindow->borderClip);
+ b2 = REGION_EXTENTS (pScreen, pRegion);
+
+ if (EXTENTCHECK (b1, b2))
+ {
+ /* Regions may overlap. */
+
+ if (REGION_NUM_RECTS (pRegion) == 1)
+ {
+ int in;
+
+ /* Damaged region only has a single rect, so we can
+ just compare that against the region */
+
+ in = RECT_IN_REGION (pScreen, &pWindow->borderClip,
+ REGION_RECTS (pRegion));
+ if (in == rgnIN)
+ {
+ /* clip totally contains pRegion */
+
+ xp_mark_window (winRec->wid, REGION_NUM_RECTS (pRegion),
+ REGION_RECTS (pRegion),
+ -winRec->x, -winRec->y);
+
+ RootlessQueueRedisplay (pTop->drawable.pScreen);
+ goto out;
+ }
+ else if (in == rgnOUT)
+ {
+ /* clip doesn't contain pRegion */
+
+ goto out;
+ }
+ }
+
+ /* clip overlaps pRegion, need to intersect */
+
+ REGION_INIT (pScreen, &clipped, NullBox, 0);
+ REGION_INTERSECT (pScreen, &clipped, &pWindow->borderClip, pRegion);
+
+ xp_mark_window (winRec->wid, REGION_NUM_RECTS (&clipped),
+ REGION_RECTS (&clipped), -winRec->x, -winRec->y);
+
+ REGION_UNINIT (pScreen, &clipped);
+
+ RootlessQueueRedisplay (pTop->drawable.pScreen);
+ }
+
+out:
+#ifdef ROOTLESSDEBUG
+ {
+ BoxRec *box = REGION_RECTS(pRegion), *end;
+ int numBox = REGION_NUM_RECTS(pRegion);
+
+ for (end = box+numBox; box < end; box++) {
+ RL_DEBUG_MSG("Damage rect: %i, %i, %i, %i\n",
+ box->x1, box->x2, box->y1, box->y2);
+ }
+ }
+#endif
+ return;
+}
+
+/* pBox is GLOBAL */
+void
+RootlessDamageBox (WindowPtr pWindow, BoxPtr pBox)
+{
+ RegionRec region;
+
+ REGION_INIT (pWindow->drawable.pScreen, ®ion, pBox, 1);
+
+ RootlessDamageRegion (pWindow, ®ion);
+
+ REGION_UNINIT (pWindow->drawable.pScreen, ®ion); /* no-op */
+}
+
+
+/* (x, y, w, h) is in window-local coordinates. */
+void
+RootlessDamageRect(WindowPtr pWindow, int x, int y, int w, int h)
+{
+ BoxRec box;
+ RegionRec region;
+
+ x += pWindow->drawable.x;
+ y += pWindow->drawable.y;
+
+ box.x1 = x;
+ box.x2 = x + w;
+ box.y1 = y;
+ box.y2 = y + h;
+
+ REGION_INIT (pWindow->drawable.pScreen, ®ion, &box, 1);
+
+ RootlessDamageRegion (pWindow, ®ion);
+
+ REGION_UNINIT (pWindow->drawable.pScreen, ®ion); /* no-op */
+}
+
+/* Stop drawing and redisplay the damaged region of a window. */
+void
+RootlessRedisplay (WindowPtr pWindow)
+{
+ DRISynchronizeDrawable (&pWindow->drawable, TRUE);
+ RootlessStopDrawing(pWindow, TRUE);
+}
+
+/* Walk every window on a screen and redisplay the damaged regions. */
+void
+RootlessRedisplayScreen (ScreenPtr pScreen)
+{
+ RootlessScreenRec *screenRec = SCREENREC (pScreen);
+ WindowPtr root = WindowTable[pScreen->myNum];
+ WindowPtr win;
+
+ if (root != NULL)
+ {
+ RootlessRedisplay(root);
+
+ for (win = root->firstChild; win; win = win->nextSib)
+ {
+ if (WINREC (win) != NULL)
+ RootlessRedisplay (win);
+ }
+ }
+
+ screenRec->last_redisplay = GetTimeInMillis ();
+}
+
+void
+RootlessRepositionWindows (ScreenPtr pScreen)
+{
+ WindowPtr root = WindowTable[pScreen->myNum];
+ WindowPtr win;
+
+ if (root != NULL)
+ {
+ RootlessRepositionWindow (root);
+
+ for (win = root->firstChild; win; win = win->nextSib)
+ {
+ if (WINREC (win) != NULL)
+ RootlessRepositionWindow (win);
+ }
+ }
+}
+
+void
+RootlessFlushScreenColormaps (ScreenPtr pScreen)
+{
+ WindowPtr root = WindowTable[pScreen->myNum];
+ WindowPtr win;
+
+ if (root != NULL)
+ {
+ RootlessRepositionWindow (root);
+
+ for (win = root->firstChild; win; win = win->nextSib)
+ {
+ if (WINREC (win) != NULL)
+ RootlessFlushWindowColormap (win);
+ }
+ }
+}
--- /dev/null
+/*
+ * Common internal rootless definitions and code
+ *
+ * Greg Parker gparker@cs.stanford.edu
+ */
+
+/* Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
+
+ Permission is hereby granted, free of charge, to any person
+ obtaining a copy of this software and associated documentation files
+ (the "Software"), to deal in the Software without restriction,
+ including without limitation the rights to use, copy, modify, merge,
+ publish, distribute, sublicense, and/or sell copies of the Software,
+ and to permit persons to whom the Software is furnished to do so,
+ subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT
+ HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ DEALINGS IN THE SOFTWARE.
+
+ Except as contained in this notice, the name(s) of the above
+ copyright holders shall not be used in advertising or otherwise to
+ promote the sale, use or other dealings in this Software without
+ prior written authorization. */
+
+/* $XFree86: xc/programs/Xserver/hw/darwin/quartz/rootlessCommon.h,v 1.6 2002/07/24 05:58:33 torrey Exp $ */
+
+#ifndef _ROOTLESSCOMMON_H
+#define _ROOTLESSCOMMON_H
+
+#include "rootless.h"
+
+#include "pixmapstr.h"
+#include "windowstr.h"
+
+#ifdef RENDER
+#include "picturestr.h"
+#endif
+
+/* Debug output, or not. */
+#ifdef ROOTLESSDEBUG
+#define RL_DEBUG_MSG ErrorF
+#else
+#define RL_DEBUG_MSG(a, ...)
+#endif
+
+#undef MIN
+#define MIN(x,y) ((x) < (y) ? (x) : (y))
+#undef MAX
+#define MAX(x,y) ((x) > (y) ? (x) : (y))
+
+/* Global variables */
+extern int rootlessGCPrivateIndex;
+extern int rootlessScreenPrivateIndex;
+extern int rootlessWindowPrivateIndex;
+extern int rootlessNoDRIDrawing;
+
+/* RootlessGCRec: private per-gc data */
+typedef struct {
+ GCFuncs *originalFuncs;
+ GCOps *originalOps;
+} RootlessGCRec;
+
+/* RootlessWindowRec: private per-window data */
+typedef struct RootlessWindowRec {
+ int x, y;
+ unsigned int width, height;
+ unsigned int borderWidth;
+ int level;
+
+ xp_window_id wid;
+ WindowPtr win;
+
+ /* Valid when locked (i.e. is_drawing is set) */
+ void *data;
+ unsigned int rowbytes;
+
+ PixmapPtr pixmap;
+ PixmapPtr oldPixmap;
+
+ unsigned long unrealize_time; /* in seconds */
+
+ unsigned int is_drawing :1;
+ unsigned int is_update_disabled :1;
+ unsigned int is_reorder_pending :1;
+ unsigned int is_offscreen :1;
+ unsigned int is_obscured :1;
+} RootlessWindowRec;
+
+/* RootlessScreenRec: per-screen private data */
+typedef struct {
+ ScreenPtr pScreen;
+
+ CreateScreenResourcesProcPtr CreateScreenResources;
+ CloseScreenProcPtr CloseScreen;
+
+ CreateWindowProcPtr CreateWindow;
+ DestroyWindowProcPtr DestroyWindow;
+ RealizeWindowProcPtr RealizeWindow;
+ UnrealizeWindowProcPtr UnrealizeWindow;
+ ReparentWindowProcPtr ReparentWindow;
+ MoveWindowProcPtr MoveWindow;
+ ResizeWindowProcPtr ResizeWindow;
+ RestackWindowProcPtr RestackWindow;
+ ChangeBorderWidthProcPtr ChangeBorderWidth;
+ PositionWindowProcPtr PositionWindow;
+ ChangeWindowAttributesProcPtr ChangeWindowAttributes;
+
+ CreateGCProcPtr CreateGC;
+ PaintWindowBackgroundProcPtr PaintWindowBackground;
+ PaintWindowBorderProcPtr PaintWindowBorder;
+ CopyWindowProcPtr CopyWindow;
+ GetImageProcPtr GetImage;
+ SourceValidateProcPtr SourceValidate;
+
+ MarkOverlappedWindowsProcPtr MarkOverlappedWindows;
+ ValidateTreeProcPtr ValidateTree;
+
+#ifdef SHAPE
+ SetShapeProcPtr SetShape;
+#endif
+
+#ifdef RENDER
+ CompositeProcPtr Composite;
+ GlyphsProcPtr Glyphs;
+#endif
+
+ InstallColormapProcPtr InstallColormap;
+ UninstallColormapProcPtr UninstallColormap;
+ StoreColorsProcPtr StoreColors;
+
+ void *pixmap_data;
+ unsigned int pixmap_data_size;
+
+ ColormapPtr colormap;
+
+ void *redisplay_timer;
+ CARD32 last_redisplay;
+
+ unsigned int redisplay_timer_set :1;
+ unsigned int redisplay_queued :1;
+ unsigned int redisplay_expired :1;
+ unsigned int colormap_changed :1;
+} RootlessScreenRec;
+
+
+/* "Definition of the Porting Layer for the X11 Sample Server" says
+ unwrap and rewrap of screen functions is unnecessary, but
+ screen->CreateGC changes after a call to cfbCreateGC. */
+
+#define SCREEN_UNWRAP(screen, fn) \
+ screen->fn = SCREENREC(screen)->fn;
+
+#define SCREEN_WRAP(screen, fn) \
+ SCREENREC(screen)->fn = screen->fn; \
+ screen->fn = Rootless##fn
+
+/* Accessors for screen and window privates */
+
+#define SCREENREC(pScreen) \
+ ((RootlessScreenRec*)(pScreen)->devPrivates[rootlessScreenPrivateIndex].ptr)
+
+#define WINREC(pWin) \
+ ((RootlessWindowRec *)(pWin)->devPrivates[rootlessWindowPrivateIndex].ptr)
+
+/* BoxRec manipulators (Copied from shadowfb) */
+
+#define TRIM_BOX(box, pGC) { \
+ BoxPtr extents = &pGC->pCompositeClip->extents;\
+ if(box.x1 < extents->x1) box.x1 = extents->x1; \
+ if(box.x2 > extents->x2) box.x2 = extents->x2; \
+ if(box.y1 < extents->y1) box.y1 = extents->y1; \
+ if(box.y2 > extents->y2) box.y2 = extents->y2; \
+}
+
+#define TRANSLATE_BOX(box, pDraw) { \
+ box.x1 += pDraw->x; \
+ box.x2 += pDraw->x; \
+ box.y1 += pDraw->y; \
+ box.y2 += pDraw->y; \
+}
+
+#define TRIM_AND_TRANSLATE_BOX(box, pDraw, pGC) { \
+ TRANSLATE_BOX(box, pDraw); \
+ TRIM_BOX(box, pGC); \
+}
+
+#define BOX_NOT_EMPTY(box) \
+ (((box.x2 - box.x1) > 0) && ((box.y2 - box.y1) > 0))
+
+/* We don't want to clip windows to the edge of the screen. HUGE_ROOT
+ temporarily makes the root window really big. This is needed as a
+ wrapper around any function that calls SetWinSize or SetBorderSize
+ which clip a window against its parents, including the root. */
+
+extern RegionRec rootlessHugeRoot;
+
+#define HUGE_ROOT(pWin) \
+ do { \
+ WindowPtr w = pWin; \
+ while (w->parent != NULL) \
+ w = w->parent; \
+ saveRoot = w->winSize; \
+ w->winSize = rootlessHugeRoot; \
+ } while (0)
+
+#define NORMAL_ROOT(pWin) \
+ do { \
+ WindowPtr w = pWin; \
+ while (w->parent != NULL) \
+ w = w->parent; \
+ w->winSize = saveRoot; \
+ } while (0)
+
+/* Returns TRUE if this window is a top-level window (i.e. child of the root)
+ The root is not a top-level window. */
+#define IsTopLevel(pWin) \
+ ((pWin) != NULL && (pWin)->parent != NULL && (pWin)->parent->parent == NULL)
+
+/* Returns TRUE if this window is a root window */
+#define IsRoot(pWin) \
+ ((pWin) == WindowTable[(pWin)->drawable.pScreen->myNum])
+
+/* Returns the top-level parent of pWindow.
+ The root is the top-level parent of itself, even though the root is
+ not otherwise considered to be a top-level window. */
+extern WindowPtr TopLevelParent (WindowPtr pWindow);
+
+/* Returns TRUE if this window is visible inside a frame (e.g. it is
+ visible and has a top-level or root parent) */
+extern Bool IsFramedWindow (WindowPtr pWin);
+
+/* Adjust base address of pixmap by DX,DY */
+extern void TranslatePixmapBase (PixmapPtr pPix, int dx, int dy);
+
+/* Prepare a window for direct access to its backing buffer. */
+extern void RootlessStartDrawing (WindowPtr pWindow);
+
+/* Mark that no more drawing operations will hit the window until ``start
+ drawing'' is issued again. */
+extern void RootlessFinishedDrawing (WindowPtr pWindow);
+
+/* Finish drawing to a window's backing buffer. */
+extern void RootlessStopDrawing (WindowPtr pWindow, Bool flush);
+
+/* Routines that cause regions to get redrawn.
+ DamageRegion and DamageRect are in global coordinates.
+ DamageBox is in window-local coordinates. */
+extern void RootlessDamageRegion (WindowPtr pWindow, RegionPtr pRegion);
+extern void RootlessDamageRect (WindowPtr pWindow, int x, int y, int w, int h);
+extern void RootlessDamageBox (WindowPtr pWindow, BoxPtr pBox);
+extern void RootlessRedisplay (WindowPtr pWindow);
+extern void RootlessRedisplayScreen (ScreenPtr pScreen);
+
+extern void RootlessQueueRedisplay (ScreenPtr pScreen);
+extern Bool RootlessMayRedisplay (ScreenPtr pScreen);
+extern void RootlessScreenExpose (ScreenPtr pScreen);
+
+/* Return the colormap currently installed on the given screen. */
+extern ColormapPtr RootlessGetColormap (ScreenPtr pScreen);
+
+/* Convert colormap to ARGB. */
+extern Bool RootlessResolveColormap (ScreenPtr pScreen, int first_color,
+ int n_colors, uint32_t *colors);
+
+extern void RootlessFlushWindowColormap (WindowPtr pWin);
+extern void RootlessFlushScreenColormaps (ScreenPtr pScreen);
+
+/* Move windows back to their position relative to the screen origin. */
+extern void RootlessRepositionWindow (WindowPtr pWin);
+extern void RootlessRepositionWindows (ScreenPtr pScreen);
+
+/* Move the window to it's correct place in the physical stacking order */
+extern void RootlessReorderWindow (WindowPtr pWin);
+
+/* Bit mask for alpha channel with a particular number of bits per
+ pixel. Note that we only care for 32bpp data. OS X uses planar alpha
+ for 16bpp. */
+#define RootlessAlphaMask(bpp) ((bpp) == 32 ? 0xFF000000 : 0)
+
+#ifdef RENDER
+extern void RootlessComposite(CARD8 op, PicturePtr pSrc,
+ PicturePtr pMask, PicturePtr pDst,
+ INT16 xSrc, INT16 ySrc,
+ INT16 xMask, INT16 yMask,
+ INT16 xDst, INT16 yDst,
+ CARD16 width, CARD16 height);
+#endif
+
+extern void RootlessNativeWindowStateChanged (xp_window_id id,
+ unsigned int state);
+
+extern void RootlessEnableRoot (ScreenPtr pScreen);
+extern void RootlessDisableRoot (ScreenPtr pScreen);
+extern void RootlessSetWindowLevel (WindowPtr pWin, int level);
+
+#endif /* _ROOTLESSCOMMON_H */
--- /dev/null
+/*
+ * Graphics Context support for Mac OS X rootless X server
+ */
+/*
+ * Copyright (c) 2001 Greg Parker. All Rights Reserved.
+ * Copyright (c) 2002 Torrey T. Lyons. All Rights Reserved.
+ * Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name(s) of the above copyright
+ * holders shall not be used in advertising or otherwise to promote the sale,
+ * use or other dealings in this Software without prior written authorization.
+ */
+/* $XFree86: xc/programs/Xserver/hw/darwin/quartz/rootlessGC.c,v 1.3 2002/07/24 05:58:33 torrey Exp $ */
+
+#include "mi.h"
+#include "scrnintstr.h"
+#include "gcstruct.h"
+#include "pixmapstr.h"
+#include "windowstr.h"
+#include "dixfontstr.h"
+#include "mivalidate.h"
+#include "fb.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include "rootless-common.h"
+
+
+// GC functions
+static void
+RootlessValidateGC(GCPtr pGC, unsigned long changes,
+ DrawablePtr pDrawable);
+static void RootlessChangeGC(GCPtr pGC, unsigned long mask);
+static void RootlessCopyGC(GCPtr pGCSrc, unsigned long mask, GCPtr pGCDst);
+static void RootlessDestroyGC(GCPtr pGC);
+static void RootlessChangeClip(GCPtr pGC, int type, pointer pvalue,
+ int nrects);
+static void RootlessDestroyClip(GCPtr pGC);
+static void RootlessCopyClip(GCPtr pgcDst, GCPtr pgcSrc);
+
+GCFuncs rootlessGCFuncs = {
+ RootlessValidateGC,
+ RootlessChangeGC,
+ RootlessCopyGC,
+ RootlessDestroyGC,
+ RootlessChangeClip,
+ RootlessDestroyClip,
+ RootlessCopyClip,
+};
+
+// GC operations
+static void RootlessFillSpans();
+static void RootlessSetSpans();
+static void RootlessPutImage();
+static RegionPtr RootlessCopyArea();
+static RegionPtr RootlessCopyPlane();
+static void RootlessPolyPoint();
+static void RootlessPolylines();
+static void RootlessPolySegment();
+static void RootlessPolyRectangle();
+static void RootlessPolyArc();
+static void RootlessFillPolygon();
+static void RootlessPolyFillRect();
+static void RootlessPolyFillArc();
+static int RootlessPolyText8();
+static int RootlessPolyText16();
+static void RootlessImageText8();
+static void RootlessImageText16();
+static void RootlessImageGlyphBlt();
+static void RootlessPolyGlyphBlt();
+static void RootlessPushPixels();
+
+static GCOps rootlessGCOps = {
+ RootlessFillSpans,
+ RootlessSetSpans,
+ RootlessPutImage,
+ RootlessCopyArea,
+ RootlessCopyPlane,
+ RootlessPolyPoint,
+ RootlessPolylines,
+ RootlessPolySegment,
+ RootlessPolyRectangle,
+ RootlessPolyArc,
+ RootlessFillPolygon,
+ RootlessPolyFillRect,
+ RootlessPolyFillArc,
+ RootlessPolyText8,
+ RootlessPolyText16,
+ RootlessImageText8,
+ RootlessImageText16,
+ RootlessImageGlyphBlt,
+ RootlessPolyGlyphBlt,
+ RootlessPushPixels
+#ifdef NEED_LINEHELPER
+ , NULL
+#endif
+};
+
+
+Bool
+RootlessCreateGC(GCPtr pGC)
+{
+ RootlessGCRec *gcrec;
+ RootlessScreenRec *s;
+ Bool result;
+
+ SCREEN_UNWRAP(pGC->pScreen, CreateGC);
+ s = (RootlessScreenRec *) pGC->pScreen->
+ devPrivates[rootlessScreenPrivateIndex].ptr;
+ result = s->CreateGC(pGC);
+ gcrec = (RootlessGCRec *) pGC->devPrivates[rootlessGCPrivateIndex].ptr;
+ gcrec->originalOps = NULL; // don't wrap ops yet
+ gcrec->originalFuncs = pGC->funcs;
+ pGC->funcs = &rootlessGCFuncs;
+
+ SCREEN_WRAP(pGC->pScreen, CreateGC);
+ return result;
+}
+
+
+// GC func wrapping
+// ValidateGC wraps gcOps iff dest is viewable. All others just unwrap&call.
+
+// GCFUN_UNRAP assumes funcs have been wrapped and
+// does not assume ops have been wrapped
+#define GCFUNC_UNWRAP(pGC) \
+ RootlessGCRec *gcrec = (RootlessGCRec *) \
+ (pGC)->devPrivates[rootlessGCPrivateIndex].ptr; \
+ (pGC)->funcs = gcrec->originalFuncs; \
+ if (gcrec->originalOps) { \
+ (pGC)->ops = gcrec->originalOps; \
+}
+
+#define GCFUNC_WRAP(pGC) \
+ gcrec->originalFuncs = (pGC)->funcs; \
+ (pGC)->funcs = &rootlessGCFuncs; \
+ if (gcrec->originalOps) { \
+ gcrec->originalOps = (pGC)->ops; \
+ (pGC)->ops = &rootlessGCOps; \
+}
+
+/* Turn drawing on the root into a no-op */
+#define GC_IS_ROOT(pDst) ((pDst)->type == DRAWABLE_WINDOW \
+ && IsRoot ((WindowPtr) (pDst)) \
+ && WINREC ((WindowPtr) (pDst)) == NULL)
+
+#define GC_SKIP_ROOT(pDst) \
+ do { \
+ if (GC_IS_ROOT (pDst)) \
+ return; \
+ } while (0)
+
+/* Our main problem when drawing is that we have to make sure that
+ the alpha channel of the windows we're drawing in is always opaque.
+
+ fb makes this harder than it would otherwise be by noticing that a
+ planemask of 0x00ffffff includes all bits when depth=24, and so
+ "optimizes" the pm to 0xffffffff. We work around that by temporarily
+ setting depth=bpp while changing the GC.
+
+ Anyway, so the normal situation (in 32 bit mode) is that the
+ planemask is 0x00ffffff and thus fb leaves the alpha channel alone
+ (and it's opaque initially, so things work out).
+
+ But there's a problem with drawing with a planemask that doesn't
+ have all bits set - it normally causes fb to fall off its fastest
+ paths when blitting and filling.
+
+ So my solution to that is to try to recognize when we can relax the
+ planemask back to ~0, and do that for the duration of the drawing
+ operation, setting the alpha channel in fg/bg pixels to opaque at
+ the same time. We can do this when drawing op is GXcopy. We can also
+ do it when copying from another window (since its alpha channel must
+ also be opaque).
+
+ Note that even when we can't set planemask to all ones, fbBlt may
+ still choose altivec'd code if it's GXcopy and a forwards copy. This
+ is mainly intended for copying from pixmaps to windows. The copy
+ operation used sets alpha to opaque.
+
+ The three macros below are used to implement this, drawing ops look
+ something like this:
+
+ OP {
+ GC_SAVE (gc);
+ GCFUNC_UNWRAP (gc);
+
+ ...
+
+ if (can_accel_xxx (..) && otherwise-suitable)
+ GC_UNSET_PM (gc, dst);
+
+ gc->funcs->OP (gc, ...);
+
+ GC_RESTORE (gc, dst);
+ GCFUNC_WRAP (gc);
+ }
+
+ */
+
+#define GC_SAVE(pGC) \
+ unsigned long _save_fg = (pGC)->fgPixel; \
+ unsigned long _save_bg = (pGC)->bgPixel; \
+ unsigned long _save_pm = (pGC)->planemask; \
+ Bool _changed = FALSE
+
+#define GC_RESTORE(pGC, pDraw) \
+ do { \
+ if (_changed) { \
+ unsigned int depth = (pDraw)->depth; \
+ (pGC)->fgPixel = _save_fg; \
+ (pGC)->bgPixel = _save_bg; \
+ (pGC)->planemask = _save_pm; \
+ (pDraw)->depth = (pDraw)->bitsPerPixel; \
+ validate_gc (pGC, GCForeground | GCBackground \
+ | GCPlaneMask, pDraw); \
+ (pDraw)->depth = depth; \
+ } \
+ } while (0)
+
+#define GC_UNSET_PM(pGC, pDraw) \
+ do { \
+ unsigned int mask = RootlessAlphaMask ((pDraw)->bitsPerPixel); \
+ if (((pGC)->planemask & mask) != mask) { \
+ unsigned int depth = (pDraw)->depth; \
+ (pGC)->fgPixel |= mask; \
+ (pGC)->bgPixel |= mask; \
+ (pGC)->planemask |= mask; \
+ (pDraw)->depth = (pDraw)->bitsPerPixel; \
+ validate_gc (pGC, GCForeground \
+ | GCBackground | GCPlaneMask, pDraw); \
+ (pDraw)->depth = depth; \
+ _changed = TRUE; \
+ } \
+ } while (0)
+
+static void
+validate_gc (GCPtr pGC, unsigned long changes, DrawablePtr pDrawable)
+{
+ RootlessGCRec *gcrec = (RootlessGCRec *)
+ (pGC)->devPrivates[rootlessGCPrivateIndex].ptr;
+
+ pGC->funcs->ValidateGC(pGC, changes, pDrawable);
+
+ if (((WindowPtr) pDrawable)->viewable)
+ {
+ gcrec->originalOps = pGC->ops;
+ }
+}
+
+static RootlessWindowRec *
+can_accel_blit (DrawablePtr pDraw, GCPtr pGC)
+{
+ WindowPtr pTop;
+ RootlessWindowRec *winRec;
+ unsigned int pm;
+
+ if (pGC->alu != GXcopy)
+ return NULL;
+
+ if (pDraw->type != DRAWABLE_WINDOW)
+ return NULL;
+
+ pm = ~RootlessAlphaMask (pDraw->bitsPerPixel);
+ if ((pGC->planemask & pm) != pm)
+ return NULL;
+
+ pTop = TopLevelParent ((WindowPtr) pDraw);
+ if (pTop == NULL)
+ return NULL;
+
+ winRec = WINREC(pTop);
+ if (winRec == NULL)
+ return NULL;
+
+ return winRec;
+}
+
+static inline RootlessWindowRec *
+can_accel_fill (DrawablePtr pDraw, GCPtr pGC)
+{
+ if (pGC->fillStyle != FillSolid)
+ return NULL;
+
+ return can_accel_blit (pDraw, pGC);
+}
+
+static unsigned int
+box_bytes (DrawablePtr pDraw, BoxRec *box)
+{
+ unsigned int pixels;
+
+ pixels = (box->x2 - box->x1) * (box->y2 - box->y1);
+
+ return pixels * (pDraw->bitsPerPixel >> 3);
+}
+
+static void
+RootlessValidateGC(GCPtr pGC, unsigned long changes, DrawablePtr pDrawable)
+{
+ GCFUNC_UNWRAP(pGC);
+
+ gcrec->originalOps = NULL;
+
+ if (pDrawable->type == DRAWABLE_WINDOW)
+ {
+ /* Prevent fb relaxing planemask by telling it we use all
+ bits temporarily. */
+
+ unsigned int depth = pDrawable->depth;
+ pDrawable->depth = pDrawable->bitsPerPixel;
+ pGC->planemask &= ~RootlessAlphaMask (pDrawable->bitsPerPixel);
+ validate_gc (pGC, changes | GCPlaneMask, pDrawable);
+ pDrawable->depth = depth;
+ }
+ else
+ pGC->funcs->ValidateGC(pGC, changes, pDrawable);
+
+ GCFUNC_WRAP(pGC);
+}
+
+static void RootlessChangeGC(GCPtr pGC, unsigned long mask)
+{
+ GCFUNC_UNWRAP(pGC);
+ pGC->funcs->ChangeGC(pGC, mask);
+ GCFUNC_WRAP(pGC);
+}
+
+static void RootlessCopyGC(GCPtr pGCSrc, unsigned long mask, GCPtr pGCDst)
+{
+ GCFUNC_UNWRAP(pGCDst);
+ pGCDst->funcs->CopyGC(pGCSrc, mask, pGCDst);
+ GCFUNC_WRAP(pGCDst);
+}
+
+static void RootlessDestroyGC(GCPtr pGC)
+{
+ GCFUNC_UNWRAP(pGC);
+ pGC->funcs->DestroyGC(pGC);
+ GCFUNC_WRAP(pGC);
+}
+
+static void RootlessChangeClip(GCPtr pGC, int type, pointer pvalue, int nrects)
+{
+ GCFUNC_UNWRAP(pGC);
+ pGC->funcs->ChangeClip(pGC, type, pvalue, nrects);
+ GCFUNC_WRAP(pGC);
+}
+
+static void RootlessDestroyClip(GCPtr pGC)
+{
+ GCFUNC_UNWRAP(pGC);
+ pGC->funcs->DestroyClip(pGC);
+ GCFUNC_WRAP(pGC);
+}
+
+static void RootlessCopyClip(GCPtr pgcDst, GCPtr pgcSrc)
+{
+ GCFUNC_UNWRAP(pgcDst);
+ pgcDst->funcs->CopyClip(pgcDst, pgcSrc);
+ GCFUNC_WRAP(pgcDst);
+}
+
+
+// GC ops
+// We can't use shadowfb because shadowfb assumes one pixmap
+// and our root window is a special case.
+// So much of this code is copied from shadowfb.
+
+// assumes both funcs and ops are wrapped
+#define GCOP_UNWRAP(pGC) \
+ RootlessGCRec *gcrec = (RootlessGCRec *) \
+ (pGC)->devPrivates[rootlessGCPrivateIndex].ptr; \
+ GCFuncs *saveFuncs = pGC->funcs; \
+ (pGC)->funcs = gcrec->originalFuncs; \
+ (pGC)->ops = gcrec->originalOps;
+
+#define GCOP_WRAP(pGC) \
+ gcrec->originalOps = (pGC)->ops; \
+ (pGC)->funcs = saveFuncs; \
+ (pGC)->ops = &rootlessGCOps;
+
+
+static void
+RootlessFillSpans(DrawablePtr dst, GCPtr pGC, int nInit,
+ DDXPointPtr pptInit, int *pwidthInit, int sorted)
+{
+ GC_SAVE (pGC);
+
+ GC_SKIP_ROOT (dst);
+ GCOP_UNWRAP(pGC);
+ RL_DEBUG_MSG("fill spans start\n");
+
+ if (nInit <= 0) {
+ pGC->ops->FillSpans(dst, pGC, nInit, pptInit, pwidthInit, sorted);
+ } else {
+ DDXPointPtr ppt = pptInit;
+ int *pwidth = pwidthInit;
+ int i = nInit;
+ BoxRec box;
+
+ box.x1 = ppt->x;
+ box.x2 = box.x1 + *pwidth;
+ box.y2 = box.y1 = ppt->y;
+
+ while(--i) {
+ ppt++;
+ pwidthInit++;
+ if(box.x1 > ppt->x)
+ box.x1 = ppt->x;
+ if(box.x2 < (ppt->x + *pwidth))
+ box.x2 = ppt->x + *pwidth;
+ if(box.y1 > ppt->y)
+ box.y1 = ppt->y;
+ else if(box.y2 < ppt->y)
+ box.y2 = ppt->y;
+ }
+
+ box.y2++;
+
+ RootlessStartDrawing((WindowPtr) dst);
+
+ if (can_accel_fill (dst, pGC)
+ && box_bytes (dst, &box) >= xp_fill_bytes_threshold)
+ {
+ GC_UNSET_PM (pGC, dst);
+ }
+
+ pGC->ops->FillSpans(dst, pGC, nInit, pptInit, pwidthInit, sorted);
+
+ TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
+ if(BOX_NOT_EMPTY(box))
+ RootlessDamageBox ((WindowPtr) dst, &box);
+
+ RootlessFinishedDrawing ((WindowPtr) dst);
+ }
+
+ GC_RESTORE (pGC, dst);
+ GCOP_WRAP(pGC);
+ RL_DEBUG_MSG("fill spans end\n");
+}
+
+static void
+RootlessSetSpans(DrawablePtr dst, GCPtr pGC, char *pSrc,
+ DDXPointPtr pptInit, int *pwidthInit,
+ int nspans, int sorted)
+{
+ GC_SKIP_ROOT (dst);
+ GCOP_UNWRAP(pGC);
+ RL_DEBUG_MSG("set spans start\n");
+
+ if (nspans <= 0) {
+ pGC->ops->SetSpans(dst, pGC, pSrc, pptInit, pwidthInit,
+ nspans, sorted);
+ } else {
+ DDXPointPtr ppt = pptInit;
+ int *pwidth = pwidthInit;
+ int i = nspans;
+ BoxRec box;
+
+ box.x1 = ppt->x;
+ box.x2 = box.x1 + *pwidth;
+ box.y2 = box.y1 = ppt->y;
+
+ while(--i) {
+ ppt++;
+ pwidth++;
+ if(box.x1 > ppt->x)
+ box.x1 = ppt->x;
+ if(box.x2 < (ppt->x + *pwidth))
+ box.x2 = ppt->x + *pwidth;
+ if(box.y1 > ppt->y)
+ box.y1 = ppt->y;
+ else if(box.y2 < ppt->y)
+ box.y2 = ppt->y;
+ }
+
+ box.y2++;
+
+ RootlessStartDrawing((WindowPtr) dst);
+ pGC->ops->SetSpans(dst, pGC, pSrc, pptInit, pwidthInit,
+ nspans, sorted);
+
+ TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
+ if(BOX_NOT_EMPTY(box))
+ RootlessDamageBox ((WindowPtr) dst, &box);
+
+ RootlessFinishedDrawing ((WindowPtr) dst);
+ }
+ GCOP_WRAP(pGC);
+ RL_DEBUG_MSG("set spans end\n");
+}
+
+static void
+RootlessPutImage(DrawablePtr dst, GCPtr pGC,
+ int depth, int x, int y, int w, int h,
+ int leftPad, int format, char *pBits)
+{
+ BoxRec box;
+
+ GC_SKIP_ROOT (dst);
+ GCOP_UNWRAP(pGC);
+ RL_DEBUG_MSG("put image start\n");
+
+ RootlessStartDrawing((WindowPtr) dst);
+ pGC->ops->PutImage(dst, pGC, depth, x,y,w,h, leftPad, format, pBits);
+
+ box.x1 = x + dst->x;
+ box.x2 = box.x1 + w;
+ box.y1 = y + dst->y;
+ box.y2 = box.y1 + h;
+
+ TRIM_BOX(box, pGC);
+ if(BOX_NOT_EMPTY(box))
+ RootlessDamageBox ((WindowPtr) dst, &box);
+
+ RootlessFinishedDrawing ((WindowPtr) dst);
+
+ GCOP_WRAP(pGC);
+ RL_DEBUG_MSG("put image end\n");
+}
+
+/* changed area is *dest* rect */
+static RegionPtr
+RootlessCopyArea(DrawablePtr pSrc, DrawablePtr dst, GCPtr pGC,
+ int srcx, int srcy, int w, int h,
+ int dstx, int dsty)
+{
+ RegionPtr result;
+ BoxRec box;
+ GC_SAVE (pGC);
+ Bool src_drawing = FALSE;
+
+ if (GC_IS_ROOT (dst) || GC_IS_ROOT (pSrc))
+ return NULL; /* nothing exposed */
+
+ GCOP_UNWRAP(pGC);
+ RL_DEBUG_MSG("copy area start (src 0x%x, dst 0x%x)\n", pSrc, dst);
+
+ if (pSrc->type == DRAWABLE_WINDOW && IsFramedWindow((WindowPtr)pSrc))
+ {
+ unsigned int bytes;
+
+ /* If both source and dest are windows, and we're doing
+ a simple copy operation, we can remove the alpha-protecting
+ planemask (since source has opaque alpha as well) */
+
+ bytes = w * h * (pSrc->depth >> 3);
+
+ if (bytes >= xp_copy_bytes_threshold && can_accel_blit (pSrc, pGC))
+ {
+ GC_UNSET_PM (pGC, dst);
+ }
+
+ RootlessStartDrawing((WindowPtr) pSrc);
+ src_drawing = TRUE;
+ }
+ RootlessStartDrawing((WindowPtr) dst);
+ result = pGC->ops->CopyArea(pSrc, dst, pGC, srcx, srcy, w, h, dstx, dsty);
+
+ box.x1 = dstx + dst->x;
+ box.x2 = box.x1 + w;
+ box.y1 = dsty + dst->y;
+ box.y2 = box.y1 + h;
+
+ TRIM_BOX(box, pGC);
+ if(BOX_NOT_EMPTY(box))
+ RootlessDamageBox ((WindowPtr) dst, &box);
+
+ RootlessFinishedDrawing ((WindowPtr) dst);
+ if (src_drawing)
+ RootlessFinishedDrawing ((WindowPtr) pSrc);
+
+ GC_RESTORE (pGC, dst);
+ GCOP_WRAP(pGC);
+ RL_DEBUG_MSG("copy area end\n");
+ return result;
+}
+
+/* changed area is *dest* rect */
+static RegionPtr RootlessCopyPlane(DrawablePtr pSrc, DrawablePtr dst,
+ GCPtr pGC, int srcx, int srcy,
+ int w, int h, int dstx, int dsty,
+ unsigned long plane)
+{
+ RegionPtr result;
+ BoxRec box;
+ Bool src_drawing = FALSE;
+
+ if (GC_IS_ROOT (dst) || GC_IS_ROOT (pSrc))
+ return NULL; /* nothing exposed */
+
+ GCOP_UNWRAP(pGC);
+ RL_DEBUG_MSG("copy plane start\n");
+
+ if (pSrc->type == DRAWABLE_WINDOW && IsFramedWindow((WindowPtr)pSrc)) {
+ RootlessStartDrawing((WindowPtr) pSrc);
+ src_drawing = TRUE;
+ }
+ RootlessStartDrawing((WindowPtr) dst);
+ result = pGC->ops->CopyPlane(pSrc, dst, pGC, srcx, srcy, w, h,
+ dstx, dsty, plane);
+
+ box.x1 = dstx + dst->x;
+ box.x2 = box.x1 + w;
+ box.y1 = dsty + dst->y;
+ box.y2 = box.y1 + h;
+
+ TRIM_BOX(box, pGC);
+ if(BOX_NOT_EMPTY(box))
+ RootlessDamageBox ((WindowPtr) dst, &box);
+
+ RootlessFinishedDrawing ((WindowPtr) dst);
+ if (src_drawing)
+ RootlessFinishedDrawing ((WindowPtr) pSrc);
+
+ GCOP_WRAP(pGC);
+ RL_DEBUG_MSG("copy plane end\n");
+ return result;
+}
+
+// Options for size of changed area:
+// 0 = box per point
+// 1 = big box around all points
+// 2 = accumulate point in 20 pixel radius
+#define ROOTLESS_CHANGED_AREA 1
+#define abs(a) ((a) > 0 ? (a) : -(a))
+
+/* changed area is box around all points */
+static void RootlessPolyPoint(DrawablePtr dst, GCPtr pGC,
+ int mode, int npt, DDXPointPtr pptInit)
+{
+ GC_SKIP_ROOT (dst);
+ GCOP_UNWRAP(pGC);
+ RL_DEBUG_MSG("polypoint start\n");
+
+ RootlessStartDrawing((WindowPtr) dst);
+ pGC->ops->PolyPoint(dst, pGC, mode, npt, pptInit);
+
+ if (npt > 0) {
+#if ROOTLESS_CHANGED_AREA==0
+ // box per point
+ BoxRec box;
+
+ while (npt) {
+ box.x1 = pptInit->x;
+ box.y1 = pptInit->y;
+ box.x2 = box.x1 + 1;
+ box.y2 = box.y1 + 1;
+
+ TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
+ if(BOX_NOT_EMPTY(box))
+ RootlessDamageBox ((WindowPtr) dst, &box);
+
+ npt--;
+ pptInit++;
+ }
+
+#elif ROOTLESS_CHANGED_AREA==1
+ // one big box
+ BoxRec box;
+
+ box.x2 = box.x1 = pptInit->x;
+ box.y2 = box.y1 = pptInit->y;
+ while(--npt) {
+ pptInit++;
+ if(box.x1 > pptInit->x)
+ box.x1 = pptInit->x;
+ else if(box.x2 < pptInit->x)
+ box.x2 = pptInit->x;
+ if(box.y1 > pptInit->y)
+ box.y1 = pptInit->y;
+ else if(box.y2 < pptInit->y)
+ box.y2 = pptInit->y;
+ }
+
+ box.x2++;
+ box.y2++;
+
+ TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
+ if(BOX_NOT_EMPTY(box))
+ RootlessDamageBox ((WindowPtr) dst, &box);
+
+#elif ROOTLESS_CHANGED_AREA==2
+ // clever(?) method: accumulate point in 20-pixel radius
+ BoxRec box;
+ int firstx, firsty;
+
+ box.x2 = box.x1 = firstx = pptInit->x;
+ box.y2 = box.y1 = firsty = pptInit->y;
+ while(--npt) {
+ pptInit++;
+ if (abs(pptInit->x - firstx) > 20 ||
+ abs(pptInit->y - firsty) > 20) {
+ box.x2++;
+ box.y2++;
+ TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
+ if(BOX_NOT_EMPTY(box))
+ RootlessDamageBox ((WindowPtr) dst, &box);
+ box.x2 = box.x1 = firstx = pptInit->x;
+ box.y2 = box.y1 = firsty = pptInit->y;
+ } else {
+ if (box.x1 > pptInit->x) box.x1 = pptInit->x;
+ else if (box.x2 < pptInit->x) box.x2 = pptInit->x;
+ if (box.y1 > pptInit->y) box.y1 = pptInit->y;
+ else if (box.y2 < pptInit->y) box.y2 = pptInit->y;
+ }
+ }
+ box.x2++;
+ box.y2++;
+ TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
+ if(BOX_NOT_EMPTY(box))
+ RootlessDamageBox ((WindowPtr) dst, &box);
+#endif /* ROOTLESS_CHANGED_AREA */
+ }
+
+ RootlessFinishedDrawing ((WindowPtr) dst);
+
+ GCOP_WRAP(pGC);
+ RL_DEBUG_MSG("polypoint end\n");
+}
+
+#undef ROOTLESS_CHANGED_AREA
+
+/* changed area is box around each line */
+static void RootlessPolylines(DrawablePtr dst, GCPtr pGC,
+ int mode, int npt, DDXPointPtr pptInit)
+{
+ GC_SKIP_ROOT (dst);
+ GCOP_UNWRAP(pGC);
+ RL_DEBUG_MSG("poly lines start\n");
+
+ RootlessStartDrawing((WindowPtr) dst);
+ pGC->ops->Polylines(dst, pGC, mode, npt, pptInit);
+
+ if (npt > 0) {
+ BoxRec box;
+ int extra = pGC->lineWidth >> 1;
+
+ box.x2 = box.x1 = pptInit->x;
+ box.y2 = box.y1 = pptInit->y;
+
+ if(npt > 1) {
+ if(pGC->joinStyle == JoinMiter)
+ extra = 6 * pGC->lineWidth;
+ else if(pGC->capStyle == CapProjecting)
+ extra = pGC->lineWidth;
+ }
+
+ if(mode == CoordModePrevious) {
+ int x = box.x1;
+ int y = box.y1;
+
+ while(--npt) {
+ pptInit++;
+ x += pptInit->x;
+ y += pptInit->y;
+ if(box.x1 > x)
+ box.x1 = x;
+ else if(box.x2 < x)
+ box.x2 = x;
+ if(box.y1 > y)
+ box.y1 = y;
+ else if(box.y2 < y)
+ box.y2 = y;
+ }
+ } else {
+ while(--npt) {
+ pptInit++;
+ if(box.x1 > pptInit->x)
+ box.x1 = pptInit->x;
+ else if(box.x2 < pptInit->x)
+ box.x2 = pptInit->x;
+ if(box.y1 > pptInit->y)
+ box.y1 = pptInit->y;
+ else if(box.y2 < pptInit->y)
+ box.y2 = pptInit->y;
+ }
+ }
+
+ box.x2++;
+ box.y2++;
+
+ if(extra) {
+ box.x1 -= extra;
+ box.x2 += extra;
+ box.y1 -= extra;
+ box.y2 += extra;
+ }
+
+ TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
+ if(BOX_NOT_EMPTY(box))
+ RootlessDamageBox ((WindowPtr) dst, &box);
+ }
+
+ RootlessFinishedDrawing ((WindowPtr) dst);
+
+ GCOP_WRAP(pGC);
+ RL_DEBUG_MSG("poly lines end\n");
+}
+
+/* changed area is box around each line segment */
+static void RootlessPolySegment(DrawablePtr dst, GCPtr pGC,
+ int nseg, xSegment *pSeg)
+{
+ GC_SKIP_ROOT (dst);
+ GCOP_UNWRAP(pGC);
+ RL_DEBUG_MSG("poly segment start (win 0x%x)\n", dst);
+
+ RootlessStartDrawing((WindowPtr) dst);
+ pGC->ops->PolySegment(dst, pGC, nseg, pSeg);
+
+ if (nseg > 0) {
+ BoxRec box;
+ int extra = pGC->lineWidth;
+
+ if(pGC->capStyle != CapProjecting)
+ extra >>= 1;
+
+ if(pSeg->x2 > pSeg->x1) {
+ box.x1 = pSeg->x1;
+ box.x2 = pSeg->x2;
+ } else {
+ box.x2 = pSeg->x1;
+ box.x1 = pSeg->x2;
+ }
+
+ if(pSeg->y2 > pSeg->y1) {
+ box.y1 = pSeg->y1;
+ box.y2 = pSeg->y2;
+ } else {
+ box.y2 = pSeg->y1;
+ box.y1 = pSeg->y2;
+ }
+
+ while(--nseg) {
+ pSeg++;
+ if(pSeg->x2 > pSeg->x1) {
+ if(pSeg->x1 < box.x1) box.x1 = pSeg->x1;
+ if(pSeg->x2 > box.x2) box.x2 = pSeg->x2;
+ } else {
+ if(pSeg->x2 < box.x1) box.x1 = pSeg->x2;
+ if(pSeg->x1 > box.x2) box.x2 = pSeg->x1;
+ }
+ if(pSeg->y2 > pSeg->y1) {
+ if(pSeg->y1 < box.y1) box.y1 = pSeg->y1;
+ if(pSeg->y2 > box.y2) box.y2 = pSeg->y2;
+ } else {
+ if(pSeg->y2 < box.y1) box.y1 = pSeg->y2;
+ if(pSeg->y1 > box.y2) box.y2 = pSeg->y1;
+ }
+ }
+
+ box.x2++;
+ box.y2++;
+
+ if(extra) {
+ box.x1 -= extra;
+ box.x2 += extra;
+ box.y1 -= extra;
+ box.y2 += extra;
+ }
+
+ TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
+ if(BOX_NOT_EMPTY(box))
+ RootlessDamageBox ((WindowPtr) dst, &box);
+ }
+
+ RootlessFinishedDrawing ((WindowPtr) dst);
+
+ GCOP_WRAP(pGC);
+ RL_DEBUG_MSG("poly segment end\n");
+}
+
+/* changed area is box around each line (not entire rects) */
+static void RootlessPolyRectangle(DrawablePtr dst, GCPtr pGC,
+ int nRects, xRectangle *pRects)
+{
+ GC_SKIP_ROOT (dst);
+ GCOP_UNWRAP(pGC);
+ RL_DEBUG_MSG("poly rectangle start\n");
+
+ RootlessStartDrawing((WindowPtr) dst);
+ pGC->ops->PolyRectangle(dst, pGC, nRects, pRects);
+
+ if (nRects > 0) {
+ BoxRec box;
+ int offset1, offset2, offset3;
+
+ offset2 = pGC->lineWidth;
+ if(!offset2) offset2 = 1;
+ offset1 = offset2 >> 1;
+ offset3 = offset2 - offset1;
+
+ while(nRects--) {
+ box.x1 = pRects->x - offset1;
+ box.y1 = pRects->y - offset1;
+ box.x2 = box.x1 + pRects->width + offset2;
+ box.y2 = box.y1 + offset2;
+ TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
+ if(BOX_NOT_EMPTY(box))
+ RootlessDamageBox ((WindowPtr) dst, &box);
+
+ box.x1 = pRects->x - offset1;
+ box.y1 = pRects->y + offset3;
+ box.x2 = box.x1 + offset2;
+ box.y2 = box.y1 + pRects->height - offset2;
+ TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
+ if(BOX_NOT_EMPTY(box))
+ RootlessDamageBox ((WindowPtr) dst, &box);
+
+ box.x1 = pRects->x + pRects->width - offset1;
+ box.y1 = pRects->y + offset3;
+ box.x2 = box.x1 + offset2;
+ box.y2 = box.y1 + pRects->height - offset2;
+ TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
+ if(BOX_NOT_EMPTY(box))
+ RootlessDamageBox ((WindowPtr) dst, &box);
+
+ box.x1 = pRects->x - offset1;
+ box.y1 = pRects->y + pRects->height - offset1;
+ box.x2 = box.x1 + pRects->width + offset2;
+ box.y2 = box.y1 + offset2;
+ TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
+ if(BOX_NOT_EMPTY(box))
+ RootlessDamageBox ((WindowPtr) dst, &box);
+
+ pRects++;
+ }
+ }
+
+ RootlessFinishedDrawing ((WindowPtr) dst);
+
+ GCOP_WRAP(pGC);
+ RL_DEBUG_MSG("poly rectangle end\n");
+}
+
+
+/* changed area is box around each arc (assumes all arcs are 360 degrees) */
+static void RootlessPolyArc(DrawablePtr dst, GCPtr pGC, int narcs, xArc *parcs)
+{
+ GC_SKIP_ROOT (dst);
+ GCOP_UNWRAP(pGC);
+ RL_DEBUG_MSG("poly arc start\n");
+
+ RootlessStartDrawing((WindowPtr) dst);
+ pGC->ops->PolyArc(dst, pGC, narcs, parcs);
+
+ if (narcs > 0) {
+ int extra = pGC->lineWidth >> 1;
+ BoxRec box;
+
+ box.x1 = parcs->x;
+ box.x2 = box.x1 + parcs->width;
+ box.y1 = parcs->y;
+ box.y2 = box.y1 + parcs->height;
+
+ /* should I break these up instead ? */
+
+ while(--narcs) {
+ parcs++;
+ if(box.x1 > parcs->x)
+ box.x1 = parcs->x;
+ if(box.x2 < (parcs->x + parcs->width))
+ box.x2 = parcs->x + parcs->width;
+ if(box.y1 > parcs->y)
+ box.y1 = parcs->y;
+ if(box.y2 < (parcs->y + parcs->height))
+ box.y2 = parcs->y + parcs->height;
+ }
+
+ if(extra) {
+ box.x1 -= extra;
+ box.x2 += extra;
+ box.y1 -= extra;
+ box.y2 += extra;
+ }
+
+ box.x2++;
+ box.y2++;
+
+ TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
+ if(BOX_NOT_EMPTY(box))
+ RootlessDamageBox ((WindowPtr) dst, &box);
+ }
+
+ RootlessFinishedDrawing ((WindowPtr) dst);
+
+ GCOP_WRAP(pGC);
+ RL_DEBUG_MSG("poly arc end\n");
+}
+
+
+/* changed area is box around each poly */
+static void RootlessFillPolygon(DrawablePtr dst, GCPtr pGC,
+ int shape, int mode, int count,
+ DDXPointPtr pptInit)
+{
+ GC_SAVE (pGC);
+
+ GC_SKIP_ROOT (dst);
+ GCOP_UNWRAP(pGC);
+ RL_DEBUG_MSG("fill poly start (win 0x%x, fillStyle 0x%x)\n", dst,
+ pGC->fillStyle);
+
+ if (count <= 2) {
+ pGC->ops->FillPolygon(dst, pGC, shape, mode, count, pptInit);
+ } else {
+ DDXPointPtr ppt = pptInit;
+ int i = count;
+ BoxRec box;
+
+ box.x2 = box.x1 = ppt->x;
+ box.y2 = box.y1 = ppt->y;
+
+ if(mode != CoordModeOrigin) {
+ int x = box.x1;
+ int y = box.y1;
+
+ while(--i) {
+ ppt++;
+ x += ppt->x;
+ y += ppt->y;
+ if(box.x1 > x)
+ box.x1 = x;
+ else if(box.x2 < x)
+ box.x2 = x;
+ if(box.y1 > y)
+ box.y1 = y;
+ else if(box.y2 < y)
+ box.y2 = y;
+ }
+ } else {
+ while(--i) {
+ ppt++;
+ if(box.x1 > ppt->x)
+ box.x1 = ppt->x;
+ else if(box.x2 < ppt->x)
+ box.x2 = ppt->x;
+ if(box.y1 > ppt->y)
+ box.y1 = ppt->y;
+ else if(box.y2 < ppt->y)
+ box.y2 = ppt->y;
+ }
+ }
+
+ box.x2++;
+ box.y2++;
+
+ RootlessStartDrawing((WindowPtr) dst);
+
+ if (can_accel_fill (dst, pGC)
+ && box_bytes (dst, &box) >= xp_fill_bytes_threshold)
+ {
+ GC_UNSET_PM (pGC, dst);
+ }
+
+ pGC->ops->FillPolygon(dst, pGC, shape, mode, count, pptInit);
+
+ TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
+ if(BOX_NOT_EMPTY(box))
+ RootlessDamageBox ((WindowPtr) dst, &box);
+
+ RootlessFinishedDrawing ((WindowPtr) dst);
+ }
+
+ GC_RESTORE (pGC, dst);
+ GCOP_WRAP(pGC);
+ RL_DEBUG_MSG("fill poly end\n");
+}
+
+/* changed area is the rects */
+static void RootlessPolyFillRect(DrawablePtr dst, GCPtr pGC,
+ int nRectsInit, xRectangle *pRectsInit)
+{
+ GC_SAVE (pGC);
+
+ GC_SKIP_ROOT (dst);
+ GCOP_UNWRAP(pGC);
+ RL_DEBUG_MSG("fill rect start (win 0x%x, fillStyle 0x%x)\n", dst,
+ pGC->fillStyle);
+
+ if (nRectsInit <= 0) {
+ pGC->ops->PolyFillRect(dst, pGC, nRectsInit, pRectsInit);
+ } else {
+ BoxRec box;
+ xRectangle *pRects = pRectsInit;
+ int nRects = nRectsInit;
+
+ box.x1 = pRects->x;
+ box.x2 = box.x1 + pRects->width;
+ box.y1 = pRects->y;
+ box.y2 = box.y1 + pRects->height;
+
+ while(--nRects) {
+ pRects++;
+ if(box.x1 > pRects->x)
+ box.x1 = pRects->x;
+ if(box.x2 < (pRects->x + pRects->width))
+ box.x2 = pRects->x + pRects->width;
+ if(box.y1 > pRects->y)
+ box.y1 = pRects->y;
+ if(box.y2 < (pRects->y + pRects->height))
+ box.y2 = pRects->y + pRects->height;
+ }
+
+ /* cfb messes with the pRectsInit so we have to do our
+ calculations first */
+
+ RootlessStartDrawing((WindowPtr) dst);
+
+ if (can_accel_fill (dst, pGC)
+ && box_bytes (dst, &box) >= xp_fill_bytes_threshold)
+ {
+ GC_UNSET_PM (pGC, dst);
+ }
+
+ pGC->ops->PolyFillRect (dst, pGC, nRectsInit, pRectsInit);
+
+ TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
+ if(BOX_NOT_EMPTY(box))
+ RootlessDamageBox ((WindowPtr) dst, &box);
+
+ RootlessFinishedDrawing ((WindowPtr) dst);
+ }
+
+ GC_RESTORE (pGC, dst);
+ GCOP_WRAP(pGC);
+ RL_DEBUG_MSG("fill rect end\n");
+}
+
+
+/* changed area is box around each arc (assuming arcs are all 360 degrees) */
+static void RootlessPolyFillArc(DrawablePtr dst, GCPtr pGC,
+ int narcs, xArc *parcs)
+{
+ GC_SAVE (pGC);
+
+ GC_SKIP_ROOT (dst);
+ GCOP_UNWRAP(pGC);
+ RL_DEBUG_MSG("fill arc start\n");
+
+ if (narcs > 0) {
+ BoxRec box;
+ int i;
+
+ box.x1 = parcs->x;
+ box.x2 = box.x1 + parcs->width;
+ box.y1 = parcs->y;
+ box.y2 = box.y1 + parcs->height;
+
+ /* should I break these up instead ? */
+
+ for (i = 0; i < narcs; i++)
+ {
+ if(box.x1 > parcs[i].x)
+ box.x1 = parcs[i].x;
+ if(box.x2 < (parcs[i].x + parcs[i].width))
+ box.x2 = parcs[i].x + parcs[i].width;
+ if(box.y1 > parcs[i].y)
+ box.y1 = parcs[i].y;
+ if(box.y2 < (parcs[i].y + parcs[i].height))
+ box.y2 = parcs[i].y + parcs[i].height;
+ }
+
+ RootlessStartDrawing((WindowPtr) dst);
+
+ if (can_accel_fill (dst, pGC)
+ && box_bytes (dst, &box) >= xp_fill_bytes_threshold)
+ {
+ GC_UNSET_PM (pGC, dst);
+ }
+
+ pGC->ops->PolyFillArc(dst, pGC, narcs, parcs);
+
+ TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
+ if(BOX_NOT_EMPTY(box))
+ RootlessDamageBox ((WindowPtr) dst, &box);
+
+ RootlessFinishedDrawing ((WindowPtr) dst);
+ }
+ else
+ pGC->ops->PolyFillArc(dst, pGC, narcs, parcs);
+
+ GC_RESTORE (pGC, dst);
+ GCOP_WRAP(pGC);
+ RL_DEBUG_MSG("fill arc end\n");
+}
+
+
+static void RootlessImageText8(DrawablePtr dst, GCPtr pGC,
+ int x, int y, int count, char *chars)
+{
+ GC_SAVE (pGC);
+
+ GC_SKIP_ROOT (dst);
+ GCOP_UNWRAP(pGC);
+ RL_DEBUG_MSG("imagetext8 start\n");
+
+ RootlessStartDrawing((WindowPtr) dst);
+
+ if (count > 0) {
+ int top, bot, Min, Max;
+ BoxRec box;
+
+ top = max(FONTMAXBOUNDS(pGC->font, ascent), FONTASCENT(pGC->font));
+ bot = max(FONTMAXBOUNDS(pGC->font, descent), FONTDESCENT(pGC->font));
+
+ Min = count * FONTMINBOUNDS(pGC->font, characterWidth);
+ if(Min > 0) Min = 0;
+ Max = count * FONTMAXBOUNDS(pGC->font, characterWidth);
+ if(Max < 0) Max = 0;
+
+ /* ugh */
+ box.x1 = dst->x + x + Min +
+ FONTMINBOUNDS(pGC->font, leftSideBearing);
+ box.x2 = dst->x + x + Max +
+ FONTMAXBOUNDS(pGC->font, rightSideBearing);
+
+ box.y1 = dst->y + y - top;
+ box.y2 = dst->y + y + bot;
+
+ if (can_accel_fill (dst, pGC)
+ && box_bytes (dst, &box) >= xp_fill_bytes_threshold)
+ {
+ GC_UNSET_PM (pGC, dst);
+ }
+
+ pGC->ops->ImageText8(dst, pGC, x, y, count, chars);
+
+ TRIM_BOX(box, pGC);
+ if(BOX_NOT_EMPTY(box))
+ RootlessDamageBox ((WindowPtr) dst, &box);
+ }
+ else
+ pGC->ops->ImageText8(dst, pGC, x, y, count, chars);
+
+ RootlessFinishedDrawing ((WindowPtr) dst);
+
+ GC_RESTORE (pGC, dst);
+ GCOP_WRAP(pGC);
+ RL_DEBUG_MSG("imagetext8 end\n");
+}
+
+static int RootlessPolyText8(DrawablePtr dst, GCPtr pGC,
+ int x, int y, int count, char *chars)
+{
+ int width; // the result, sorta
+
+ if (GC_IS_ROOT (dst))
+ return 0; /* FIXME: ok? */
+
+ GCOP_UNWRAP(pGC);
+ RL_DEBUG_MSG("polytext8 start\n");
+
+ RootlessStartDrawing((WindowPtr) dst);
+ width = pGC->ops->PolyText8(dst, pGC, x, y, count, chars);
+ width -= x;
+
+ if(width > 0) {
+ BoxRec box;
+
+ /* ugh */
+ box.x1 = dst->x + x + FONTMINBOUNDS(pGC->font, leftSideBearing);
+ box.x2 = dst->x + x + FONTMAXBOUNDS(pGC->font, rightSideBearing);
+
+ if(count > 1) {
+ if(width > 0) box.x2 += width;
+ else box.x1 += width;
+ }
+
+ box.y1 = dst->y + y - FONTMAXBOUNDS(pGC->font, ascent);
+ box.y2 = dst->y + y + FONTMAXBOUNDS(pGC->font, descent);
+
+ TRIM_BOX(box, pGC);
+ if(BOX_NOT_EMPTY(box))
+ RootlessDamageBox ((WindowPtr) dst, &box);
+ }
+
+ RootlessFinishedDrawing ((WindowPtr) dst);
+
+ GCOP_WRAP(pGC);
+ RL_DEBUG_MSG("polytext8 end\n");
+ return (width + x);
+}
+
+static void RootlessImageText16(DrawablePtr dst, GCPtr pGC,
+ int x, int y, int count, unsigned short *chars)
+{
+ GC_SAVE (pGC);
+
+ GC_SKIP_ROOT (dst);
+ GCOP_UNWRAP(pGC);
+ RL_DEBUG_MSG("imagetext16 start\n");
+
+ if (count > 0) {
+ int top, bot, Min, Max;
+ BoxRec box;
+
+ top = max(FONTMAXBOUNDS(pGC->font, ascent), FONTASCENT(pGC->font));
+ bot = max(FONTMAXBOUNDS(pGC->font, descent), FONTDESCENT(pGC->font));
+
+ Min = count * FONTMINBOUNDS(pGC->font, characterWidth);
+ if(Min > 0) Min = 0;
+ Max = count * FONTMAXBOUNDS(pGC->font, characterWidth);
+ if(Max < 0) Max = 0;
+
+ /* ugh */
+ box.x1 = dst->x + x + Min +
+ FONTMINBOUNDS(pGC->font, leftSideBearing);
+ box.x2 = dst->x + x + Max +
+ FONTMAXBOUNDS(pGC->font, rightSideBearing);
+
+ box.y1 = dst->y + y - top;
+ box.y2 = dst->y + y + bot;
+
+ RootlessStartDrawing((WindowPtr) dst);
+
+ if (can_accel_fill (dst, pGC)
+ && box_bytes (dst, &box) >= xp_fill_bytes_threshold)
+ {
+ GC_UNSET_PM (pGC, dst);
+ }
+
+ pGC->ops->ImageText16(dst, pGC, x, y, count, chars);
+
+ TRIM_BOX(box, pGC);
+ if(BOX_NOT_EMPTY(box))
+ RootlessDamageBox ((WindowPtr) dst, &box);
+
+ RootlessFinishedDrawing ((WindowPtr) dst);
+ }
+ else
+ pGC->ops->ImageText16(dst, pGC, x, y, count, chars);
+
+ GC_RESTORE (pGC, dst);
+ GCOP_WRAP(pGC);
+ RL_DEBUG_MSG("imagetext16 end\n");
+}
+
+static int RootlessPolyText16(DrawablePtr dst, GCPtr pGC,
+ int x, int y, int count, unsigned short *chars)
+{
+ int width; // the result, sorta
+
+ if (GC_IS_ROOT (dst))
+ return 0; /* FIXME: ok? */
+
+ GCOP_UNWRAP(pGC);
+ RL_DEBUG_MSG("polytext16 start\n");
+
+ RootlessStartDrawing((WindowPtr) dst);
+ width = pGC->ops->PolyText16(dst, pGC, x, y, count, chars);
+ width -= x;
+
+ if (width > 0) {
+ BoxRec box;
+
+ /* ugh */
+ box.x1 = dst->x + x + FONTMINBOUNDS(pGC->font, leftSideBearing);
+ box.x2 = dst->x + x + FONTMAXBOUNDS(pGC->font, rightSideBearing);
+
+ if(count > 1) {
+ if(width > 0) box.x2 += width;
+ else box.x1 += width;
+ }
+
+ box.y1 = dst->y + y - FONTMAXBOUNDS(pGC->font, ascent);
+ box.y2 = dst->y + y + FONTMAXBOUNDS(pGC->font, descent);
+
+ TRIM_BOX(box, pGC);
+ if(BOX_NOT_EMPTY(box))
+ RootlessDamageBox ((WindowPtr) dst, &box);
+ }
+
+ RootlessFinishedDrawing ((WindowPtr) dst);
+
+ GCOP_WRAP(pGC);
+ RL_DEBUG_MSG("polytext16 end\n");
+ return width + x;
+}
+
+static void RootlessImageGlyphBlt(DrawablePtr dst, GCPtr pGC,
+ int x, int y, unsigned int nglyph,
+ CharInfoPtr *ppci, pointer unused)
+{
+ GC_SKIP_ROOT (dst);
+ GCOP_UNWRAP(pGC);
+ RL_DEBUG_MSG("imageglyph start\n");
+
+ RootlessStartDrawing((WindowPtr) dst);
+ pGC->ops->ImageGlyphBlt(dst, pGC, x, y, nglyph, ppci, unused);
+
+ if (nglyph > 0) {
+ int top, bot, width = 0;
+ BoxRec box;
+
+ top = max(FONTMAXBOUNDS(pGC->font, ascent), FONTASCENT(pGC->font));
+ bot = max(FONTMAXBOUNDS(pGC->font, descent), FONTDESCENT(pGC->font));
+
+ box.x1 = ppci[0]->metrics.leftSideBearing;
+ if(box.x1 > 0) box.x1 = 0;
+ box.x2 = ppci[nglyph - 1]->metrics.rightSideBearing -
+ ppci[nglyph - 1]->metrics.characterWidth;
+ if(box.x2 < 0) box.x2 = 0;
+
+ box.x2 += dst->x + x;
+ box.x1 += dst->x + x;
+
+ while(nglyph--) {
+ width += (*ppci)->metrics.characterWidth;
+ ppci++;
+ }
+
+ if(width > 0)
+ box.x2 += width;
+ else
+ box.x1 += width;
+
+ box.y1 = dst->y + y - top;
+ box.y2 = dst->y + y + bot;
+
+ TRIM_BOX(box, pGC);
+ if(BOX_NOT_EMPTY(box))
+ RootlessDamageBox ((WindowPtr) dst, &box);
+ }
+
+ RootlessFinishedDrawing ((WindowPtr) dst);
+
+ GCOP_WRAP(pGC);
+ RL_DEBUG_MSG("imageglyph end\n");
+}
+
+static void RootlessPolyGlyphBlt(DrawablePtr dst, GCPtr pGC,
+ int x, int y, unsigned int nglyph,
+ CharInfoPtr *ppci, pointer pglyphBase)
+{
+ GC_SKIP_ROOT (dst);
+ GCOP_UNWRAP(pGC);
+ RL_DEBUG_MSG("polyglyph start\n");
+
+ RootlessStartDrawing((WindowPtr) dst);
+ pGC->ops->PolyGlyphBlt(dst, pGC, x, y, nglyph, ppci, pglyphBase);
+
+ if (nglyph > 0) {
+ BoxRec box;
+
+ /* ugh */
+ box.x1 = dst->x + x + ppci[0]->metrics.leftSideBearing;
+ box.x2 = dst->x + x + ppci[nglyph - 1]->metrics.rightSideBearing;
+
+ if(nglyph > 1) {
+ int width = 0;
+
+ while(--nglyph) {
+ width += (*ppci)->metrics.characterWidth;
+ ppci++;
+ }
+
+ if(width > 0) box.x2 += width;
+ else box.x1 += width;
+ }
+
+ box.y1 = dst->y + y - FONTMAXBOUNDS(pGC->font, ascent);
+ box.y2 = dst->y + y + FONTMAXBOUNDS(pGC->font, descent);
+
+ TRIM_BOX(box, pGC);
+ if(BOX_NOT_EMPTY(box))
+ RootlessDamageBox ((WindowPtr) dst, &box);
+ }
+
+ RootlessFinishedDrawing ((WindowPtr) dst);
+
+ GCOP_WRAP(pGC);
+ RL_DEBUG_MSG("polyglyph end\n");
+}
+
+
+/* changed area is in dest */
+static void
+RootlessPushPixels(GCPtr pGC, PixmapPtr pBitMap, DrawablePtr dst,
+ int dx, int dy, int xOrg, int yOrg)
+{
+ BoxRec box;
+
+ GC_SKIP_ROOT (dst);
+ GCOP_UNWRAP(pGC);
+ RL_DEBUG_MSG("push pixels start\n");
+
+ RootlessStartDrawing((WindowPtr) dst);
+ pGC->ops->PushPixels(pGC, pBitMap, dst, dx, dy, xOrg, yOrg);
+
+ box.x1 = xOrg + dst->x;
+ box.x2 = box.x1 + dx;
+ box.y1 = yOrg + dst->y;
+ box.y2 = box.y1 + dy;
+
+ TRIM_BOX(box, pGC);
+ if(BOX_NOT_EMPTY(box))
+ RootlessDamageBox ((WindowPtr) dst, &box);
+
+ RootlessFinishedDrawing ((WindowPtr) dst);
+
+ GCOP_WRAP(pGC);
+ RL_DEBUG_MSG("push pixels end\n");
+}
--- /dev/null
+/*
+ * Support for RENDER extension with rootless
+ */
+/*
+ * Copyright (c) 2002 Torrey T. Lyons. All Rights Reserved.
+ * Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name(s) of the above copyright
+ * holders shall not be used in advertising or otherwise to promote the sale,
+ * use or other dealings in this Software without prior written authorization.
+ */
+/* This file is largely based on fbcompose.c and fbpict.c, which contain
+ * the following copyright:
+ *
+ * Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc.
+ */
+ /* $XFree86: xc/programs/Xserver/hw/darwin/quartz/aquaPicture.c,v 1.3 2002/09/28 00:00:03 torrey Exp $ */
+
+#define DEFAULT_LOG_FORMATS 0
+
+#ifdef RENDER
+
+#include "fb.h"
+#include "picturestr.h"
+#include "mipict.h"
+#include "fbpict.h"
+#include "rootless.h"
+
+# define mod(a,b) ((b) == 1 ? 0 : (a) >= 0 ? (a) % (b) : (b) - (-a) % (b))
+
+
+// Replacement for fbStore_x8r8g8b8 that sets the alpha channel
+void
+RootlessStore_x8r8g8b8 (FbCompositeOperand *op, CARD32 value)
+{
+ FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset;
+ ((CARD32 *)line)[offset >> 5] = (value & 0xffffff) | 0xff000000;
+}
+
+
+// Defined in fbcompose.c
+extern FbCombineFunc fbCombineFuncU[];
+extern FbCombineFunc fbCombineFuncC[];
+
+void
+RootlessCompositeGeneral(
+ CARD8 op,
+ PicturePtr pSrc,
+ PicturePtr pMask,
+ PicturePtr pDst,
+ INT16 xSrc,
+ INT16 ySrc,
+ INT16 xMask,
+ INT16 yMask,
+ INT16 xDst,
+ INT16 yDst,
+ CARD16 width,
+ CARD16 height)
+{
+ FbCompositeOperand src[4],msk[4],dst[4],*pmsk;
+ FbCompositeOperand *srcPict, *srcAlpha;
+ FbCompositeOperand *dstPict, *dstAlpha;
+ FbCompositeOperand *mskPict = 0, *mskAlpha = 0;
+ FbCombineFunc f;
+ int w;
+
+ if (!fbBuildCompositeOperand (pSrc, src, xSrc, ySrc, TRUE, TRUE))
+ return;
+ if (!fbBuildCompositeOperand (pDst, dst, xDst, yDst, FALSE, TRUE))
+ return;
+
+ // Use Rootless operands for on screen picture formats
+ if (pDst->format == PICT_x8r8g8b8) {
+ dst[0].store = RootlessStore_x8r8g8b8;
+ }
+
+ if (pSrc->alphaMap)
+ {
+ srcPict = &src[1];
+ srcAlpha = &src[2];
+ }
+ else
+ {
+ srcPict = &src[0];
+ srcAlpha = 0;
+ }
+ if (pDst->alphaMap)
+ {
+ dstPict = &dst[1];
+ dstAlpha = &dst[2];
+ }
+ else
+ {
+ dstPict = &dst[0];
+ dstAlpha = 0;
+ }
+ f = fbCombineFuncU[op];
+ if (pMask)
+ {
+ if (!fbBuildCompositeOperand (pMask, msk, xMask, yMask, TRUE, TRUE))
+ return;
+ pmsk = msk;
+ if (pMask->componentAlpha)
+ f = fbCombineFuncC[op];
+ if (pMask->alphaMap)
+ {
+ mskPict = &msk[1];
+ mskAlpha = &msk[2];
+ }
+ else
+ {
+ mskPict = &msk[0];
+ mskAlpha = 0;
+ }
+ }
+ else
+ pmsk = 0;
+ while (height--)
+ {
+ w = width;
+
+ while (w--)
+ {
+ (*f) (src, pmsk, dst);
+ (*src->over) (src);
+ (*dst->over) (dst);
+ if (pmsk)
+ (*pmsk->over) (pmsk);
+ }
+ (*src->down) (src);
+ (*dst->down) (dst);
+ if (pmsk)
+ (*pmsk->down) (pmsk);
+ }
+}
+
+static int rootless_log_pict_formats = DEFAULT_LOG_FORMATS;
+
+static const char *op_name (int op)
+{
+ static const char *ops[] = {
+ "Clear", "Src", "Dst", "Over", "OverReverse", "In", "InReverse",
+ "Out", "OutReverse", "Atop", "AtopReverse", "Xor", "Add",
+ "Saturate", "Maximum",
+
+ "DisjointClear", "DisjointSrc", "DisjointDst", "DisjointOver",
+ "DisjointOverReverse", "DisjointIn", "DisjointInReverse",
+ "DisjointOut", "DisjointOutReverse", "DisjointAtop",
+ "DisjointAtopReverse", "DisjointXor", "DisjointMaximum",
+
+ "ConjointClear", "ConjointSrc", "ConjointDst", "ConjointOver",
+ "ConjointOverReverse", "ConjointIn", "ConjointInReverse",
+ "ConjointOut", "ConjointOutReverse", "ConjointAtop",
+ "ConjointAtopReverse", "ConjointXor", "ConjointMaximum",
+ };
+
+ if (op >= 0 && op < (int) (sizeof (ops) / sizeof (ops[0])))
+ return ops[op];
+ else
+ return "Unknown";
+}
+
+static const char *type_name (int type)
+{
+ switch (type)
+ {
+ case PICT_TYPE_OTHER:
+ return "Other";
+ case PICT_TYPE_A:
+ return "A";
+ case PICT_TYPE_ARGB:
+ return "ARGB";
+ case PICT_TYPE_ABGR:
+ return "ABGR";
+ case PICT_TYPE_COLOR:
+ return "Color";
+ case PICT_TYPE_GRAY:
+ return "Gray";
+ default:
+ return "Unknown";
+ }
+}
+
+static void log_format (int op, unsigned int src,
+ unsigned int dst, unsigned int mask)
+{
+ struct op {
+ int op;
+ unsigned int src, dst, mask;
+ };
+
+ static struct op *ops;
+ static int n_ops, allocated_ops;
+
+ int i;
+
+ for (i = 0; i < n_ops; i++)
+ {
+ if (ops[i].op == op && ops[i].src == src
+ && ops[i].dst == dst && ops[i].mask == mask)
+ {
+ return;
+ }
+ }
+
+ if (n_ops == allocated_ops)
+ {
+ allocated_ops *= 2;
+ ops = realloc (ops, allocated_ops * sizeof (struct op));
+ }
+
+ ops[n_ops].op = op;
+ ops[n_ops].src = src;
+ ops[n_ops].dst = dst;
+ ops[n_ops].mask = mask;
+ n_ops++;
+
+ fprintf (stderr,
+ "op: %s src (%dbpp %s %04x) dst (%dbpp %s %04x) mask (%dbpp %s %04x)\n",
+ op_name (op), PICT_FORMAT_BPP (src),
+ type_name (PICT_FORMAT_TYPE (src)),
+ src & 0xffff, PICT_FORMAT_BPP (dst),
+ type_name (PICT_FORMAT_TYPE (dst)),
+ dst & 0xffff, PICT_FORMAT_BPP (mask),
+ type_name (PICT_FORMAT_TYPE (mask)),
+ mask & 0xffff);
+}
+
+void
+RootlessComposite(
+ CARD8 op,
+ PicturePtr pSrc,
+ PicturePtr pMask,
+ PicturePtr pDst,
+ INT16 xSrc,
+ INT16 ySrc,
+ INT16 xMask,
+ INT16 yMask,
+ INT16 xDst,
+ INT16 yDst,
+ CARD16 width,
+ CARD16 height)
+{
+ RegionRec region;
+ int n;
+ BoxPtr pbox;
+ CompositeFunc func;
+ Bool srcRepeat = pSrc->repeat;
+ Bool maskRepeat = FALSE;
+ Bool srcAlphaMap = pSrc->alphaMap != 0;
+ Bool maskAlphaMap = FALSE;
+ Bool dstAlphaMap = pDst->alphaMap != 0;
+ int x_msk, y_msk, x_src, y_src, x_dst, y_dst;
+ int w, h, w_this, h_this;
+ int dstDepth = pDst->pDrawable->depth;
+
+ xDst += pDst->pDrawable->x;
+ yDst += pDst->pDrawable->y;
+ xSrc += pSrc->pDrawable->x;
+ ySrc += pSrc->pDrawable->y;
+ if (pMask)
+ {
+ xMask += pMask->pDrawable->x;
+ yMask += pMask->pDrawable->y;
+ maskRepeat = pMask->repeat;
+ maskAlphaMap = pMask->alphaMap != 0;
+ }
+
+ if (rootless_log_pict_formats)
+ {
+ log_format (op, pSrc->format, pDst->format,
+ pMask != 0 ? pMask->format : 0);
+ }
+
+ if (!miComputeCompositeRegion (®ion,
+ pSrc,
+ pMask,
+ pDst,
+ xSrc,
+ ySrc,
+ xMask,
+ yMask,
+ xDst,
+ yDst,
+ width,
+ height))
+ return;
+
+ if (pDst->pDrawable->type == DRAWABLE_WINDOW
+ && pDst->pDrawable->depth == 24
+ && pDst->pDrawable->bitsPerPixel == 32)
+ {
+ /* fbpict code sets bits above depth to zero. We don't want that! */
+
+ pDst->pDrawable->depth = 32;
+ }
+
+ func = RootlessCompositeGeneral;
+
+ if (!maskAlphaMap && !srcAlphaMap && !dstAlphaMap)
+ switch (op) {
+ case PictOpOver:
+ if (pMask)
+ {
+ if (srcRepeat &&
+ pSrc->pDrawable->width == 1 &&
+ pSrc->pDrawable->height == 1)
+ {
+ srcRepeat = FALSE;
+ if (PICT_FORMAT_COLOR(pSrc->format)) {
+ switch (pMask->format) {
+ case PICT_a8:
+ switch (pDst->format) {
+ case PICT_r5g6b5:
+ case PICT_b5g6r5:
+ func = fbCompositeSolidMask_nx8x0565;
+ break;
+ case PICT_r8g8b8:
+ case PICT_b8g8r8:
+ func = fbCompositeSolidMask_nx8x0888;
+ break;
+ case PICT_a8r8g8b8:
+ case PICT_x8r8g8b8:
+ case PICT_a8b8g8r8:
+ case PICT_x8b8g8r8:
+ func = fbCompositeSolidMask_nx8x8888;
+ break;
+ }
+ break;
+ case PICT_a8r8g8b8:
+ if (pMask->componentAlpha) {
+ switch (pDst->format) {
+ case PICT_a8r8g8b8:
+ case PICT_x8r8g8b8:
+ func = fbCompositeSolidMask_nx8888x8888C;
+ break;
+ case PICT_r5g6b5:
+ func = fbCompositeSolidMask_nx8888x0565C;
+ break;
+ }
+ }
+ break;
+ case PICT_a8b8g8r8:
+ if (pMask->componentAlpha) {
+ switch (pDst->format) {
+ case PICT_a8b8g8r8:
+ case PICT_x8b8g8r8:
+ func = fbCompositeSolidMask_nx8888x8888C;
+ break;
+ case PICT_b5g6r5:
+ func = fbCompositeSolidMask_nx8888x0565C;
+ break;
+ }
+ }
+ break;
+ case PICT_a1:
+ switch (pDst->format) {
+ case PICT_r5g6b5:
+ case PICT_b5g6r5:
+ case PICT_r8g8b8:
+ case PICT_b8g8r8:
+ case PICT_a8r8g8b8:
+ case PICT_x8r8g8b8:
+ case PICT_a8b8g8r8:
+ case PICT_x8b8g8r8:
+ func = fbCompositeSolidMask_nx1xn;
+ break;
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ switch (pSrc->format) {
+ case PICT_a8r8g8b8:
+ case PICT_x8r8g8b8:
+ switch (pDst->format) {
+ case PICT_a8r8g8b8:
+ case PICT_x8r8g8b8:
+ func = fbCompositeSrc_8888x8888;
+ break;
+ case PICT_r8g8b8:
+ func = fbCompositeSrc_8888x0888;
+ break;
+ case PICT_r5g6b5:
+ func = fbCompositeSrc_8888x0565;
+ break;
+ }
+ break;
+ case PICT_a8b8g8r8:
+ case PICT_x8b8g8r8:
+ switch (pDst->format) {
+ case PICT_a8b8g8r8:
+ case PICT_x8b8g8r8:
+ func = fbCompositeSrc_8888x8888;
+ break;
+ case PICT_b8g8r8:
+ func = fbCompositeSrc_8888x0888;
+ break;
+ case PICT_b5g6r5:
+ func = fbCompositeSrc_8888x0565;
+ break;
+ }
+ break;
+ case PICT_r5g6b5:
+ switch (pDst->format) {
+ case PICT_r5g6b5:
+ func = fbCompositeSrc_0565x0565;
+ break;
+ }
+ break;
+ case PICT_b5g6r5:
+ switch (pDst->format) {
+ case PICT_b5g6r5:
+ func = fbCompositeSrc_0565x0565;
+ break;
+ }
+ break;
+ }
+ }
+ break;
+ case PictOpAdd:
+ if (pMask == 0)
+ {
+ switch (pSrc->format) {
+ case PICT_a8r8g8b8:
+ switch (pDst->format) {
+ case PICT_a8r8g8b8:
+ func = fbCompositeSrcAdd_8888x8888;
+ break;
+ }
+ break;
+ case PICT_a8b8g8r8:
+ switch (pDst->format) {
+ case PICT_a8b8g8r8:
+ func = fbCompositeSrcAdd_8888x8888;
+ break;
+ }
+ break;
+ case PICT_a8:
+ switch (pDst->format) {
+ case PICT_a8:
+ func = fbCompositeSrcAdd_8000x8000;
+ break;
+ }
+ break;
+ case PICT_a1:
+ switch (pDst->format) {
+ case PICT_a1:
+ func = fbCompositeSrcAdd_1000x1000;
+ break;
+ }
+ break;
+ }
+ }
+ break;
+ }
+
+ n = REGION_NUM_RECTS (®ion);
+ pbox = REGION_RECTS (®ion);
+ while (n--)
+ {
+ h = pbox->y2 - pbox->y1;
+ y_src = pbox->y1 - yDst + ySrc;
+ y_msk = pbox->y1 - yDst + yMask;
+ y_dst = pbox->y1;
+ while (h)
+ {
+ h_this = h;
+ w = pbox->x2 - pbox->x1;
+ x_src = pbox->x1 - xDst + xSrc;
+ x_msk = pbox->x1 - xDst + xMask;
+ x_dst = pbox->x1;
+ if (maskRepeat)
+ {
+ y_msk = mod (y_msk, pMask->pDrawable->height);
+ if (h_this > pMask->pDrawable->height - y_msk)
+ h_this = pMask->pDrawable->height - y_msk;
+ }
+ if (srcRepeat)
+ {
+ y_src = mod (y_src, pSrc->pDrawable->height);
+ if (h_this > pSrc->pDrawable->height - y_src)
+ h_this = pSrc->pDrawable->height - y_src;
+ }
+ while (w)
+ {
+ w_this = w;
+ if (maskRepeat)
+ {
+ x_msk = mod (x_msk, pMask->pDrawable->width);
+ if (w_this > pMask->pDrawable->width - x_msk)
+ w_this = pMask->pDrawable->width - x_msk;
+ }
+ if (srcRepeat)
+ {
+ x_src = mod (x_src, pSrc->pDrawable->width);
+ if (w_this > pSrc->pDrawable->width - x_src)
+ w_this = pSrc->pDrawable->width - x_src;
+ }
+ (*func) (op, pSrc, pMask, pDst,
+ x_src, y_src, x_msk, y_msk, x_dst, y_dst,
+ w_this, h_this);
+ w -= w_this;
+ x_src += w_this;
+ x_msk += w_this;
+ x_dst += w_this;
+ }
+ h -= h_this;
+ y_src += h_this;
+ y_msk += h_this;
+ y_dst += h_this;
+ }
+ pbox++;
+ }
+ REGION_UNINIT (pDst->pDrawable->pScreen, ®ion);
+
+ pDst->pDrawable->depth = dstDepth;
+}
+
+#endif /* RENDER */
--- /dev/null
+/*
+ * Screen routines for Mac OS X rootless X server
+ *
+ * Greg Parker gparker@cs.stanford.edu
+ *
+ * February 2001 Created
+ * March 3, 2001 Restructured as generic rootless mode
+ */
+
+/* Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
+
+ Permission is hereby granted, free of charge, to any person
+ obtaining a copy of this software and associated documentation files
+ (the "Software"), to deal in the Software without restriction,
+ including without limitation the rights to use, copy, modify, merge,
+ publish, distribute, sublicense, and/or sell copies of the Software,
+ and to permit persons to whom the Software is furnished to do so,
+ subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT
+ HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ DEALINGS IN THE SOFTWARE.
+
+ Except as contained in this notice, the name(s) of the above
+ copyright holders shall not be used in advertising or otherwise to
+ promote the sale, use or other dealings in this Software without
+ prior written authorization. */
+
+/* $XFree86: xc/programs/Xserver/hw/darwin/quartz/rootlessScreen.c,v 1.2 2002/04/03 00:06:32 torrey Exp $ */
+
+
+#include "mi.h"
+#include "scrnintstr.h"
+#include "gcstruct.h"
+#include "pixmapstr.h"
+#include "windowstr.h"
+#include "propertyst.h"
+#include "mivalidate.h"
+#include "picturestr.h"
+#include "os.h"
+#include "servermd.h"
+#include "colormapst.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include "rootless-common.h"
+#include "rootless-window.h"
+
+/* In milcroseconds */
+#define REDISPLAY_DELAY 10
+#define REDISPLAY_MAX_DELAY 60
+
+extern int RootlessMiValidateTree(WindowPtr pRoot,
+ WindowPtr pChild, VTKind kind);
+extern Bool RootlessCreateGC(GCPtr pGC);
+
+int rootlessGCPrivateIndex = -1;
+int rootlessScreenPrivateIndex = -1;
+int rootlessWindowPrivateIndex = -1;
+
+void
+RootlessUpdateScreenPixmap (ScreenPtr pScreen)
+{
+ RootlessScreenRec *s = SCREENREC(pScreen);
+ PixmapPtr pPix;
+ unsigned int rowbytes;
+
+ pPix = (*pScreen->GetScreenPixmap) (pScreen);
+ if (pPix == NULL)
+ {
+ pPix = (*pScreen->CreatePixmap) (pScreen, 0, 0, pScreen->rootDepth);
+ (*pScreen->SetScreenPixmap) (pPix);
+ }
+
+ rowbytes = PixmapBytePad (pScreen->width, pScreen->rootDepth);
+
+ if (s->pixmap_data_size < rowbytes)
+ {
+ if (s->pixmap_data != NULL)
+ xfree (s->pixmap_data);
+
+ s->pixmap_data_size = rowbytes;
+ s->pixmap_data = xalloc (s->pixmap_data_size);
+ if (s->pixmap_data == NULL)
+ return;
+
+ xp_fill_bytes (s->pixmap_data_size, 1, ~0,
+ s->pixmap_data, s->pixmap_data_size);
+
+ pScreen->ModifyPixmapHeader (pPix, pScreen->width, pScreen->height,
+ pScreen->rootDepth,
+ BitsPerPixel (pScreen->rootDepth),
+ 0, s->pixmap_data);
+ /* ModifyPixmapHeader ignores zero arguments, so install rowbytes
+ by hand. */
+ pPix->devKind = 0;
+ }
+}
+
+static Bool
+RootlessCreateScreenResources (ScreenPtr pScreen)
+{
+ Bool ret = TRUE;
+
+ SCREEN_UNWRAP (pScreen, CreateScreenResources);
+
+ if (pScreen->CreateScreenResources != NULL)
+ ret = (*pScreen->CreateScreenResources) (pScreen);
+
+ SCREEN_WRAP(pScreen, CreateScreenResources);
+
+ if (!ret)
+ return ret;
+
+ /* miCreateScreenResources doesn't like our null framebuffer pointer,
+ it leaves the screen pixmap with an uninitialized data pointer. So
+ we gave it depth=0,bits=0, which says, leave it the fsck alone.
+ So we have some work to do since we need the screen pixmap to be
+ valid (e.g. CopyArea from the root window) */
+
+ RootlessUpdateScreenPixmap (pScreen);
+
+ return ret;
+}
+
+static Bool
+RootlessCloseScreen(int i, ScreenPtr pScreen)
+{
+ RootlessScreenRec *s;
+
+ s = SCREENREC(pScreen);
+
+ /* FIXME: unwrap everything that was wrapped? */
+ pScreen->CloseScreen = s->CloseScreen;
+
+ if (s->pixmap_data != NULL)
+ {
+ xfree (s->pixmap_data);
+ s->pixmap_data = NULL;
+ s->pixmap_data_size = 0;
+ }
+
+ xfree(s);
+ return pScreen->CloseScreen(i, pScreen);
+}
+
+static void
+RootlessGetImage(DrawablePtr pDrawable, int sx, int sy, int w, int h,
+ unsigned int format, unsigned long planeMask, char *pdstLine)
+{
+ ScreenPtr pScreen = pDrawable->pScreen;
+ SCREEN_UNWRAP(pScreen, GetImage);
+
+ if (pDrawable->type == DRAWABLE_WINDOW)
+ {
+ int x0, y0, x1, y1;
+
+ RootlessWindowRec *winRec;
+
+ /* Many apps use GetImage to sync with the visible frame buffer
+ FIXME: entire screen or just window or all screens? */
+ RootlessRedisplayScreen (pScreen);
+
+ /* RedisplayScreen stops drawing, so we need to start it again */
+ RootlessStartDrawing ((WindowPtr) pDrawable);
+
+ /* Check that we have some place to read from. */
+ winRec = WINREC (TopLevelParent ((WindowPtr) pDrawable));
+ if (winRec == NULL)
+ goto out;
+
+ /* Clip to top-level window bounds. */
+
+ x0 = pDrawable->x + sx;
+ y0 = pDrawable->y + sy;
+ x1 = x0 + w;
+ y1 = y0 + h;
+
+ x0 = MAX (x0, winRec->x);
+ y0 = MAX (y0, winRec->y);
+ x1 = MIN (x1, winRec->x + (int) winRec->width);
+ y1 = MIN (y1, winRec->y + (int) winRec->height);
+
+ /* FIXME: if clipped we need to adjust the data returned from
+ fbGetImage (), since it calculates the destination stride
+ from the passed in width.. */
+
+ sx = x0 - pDrawable->x;
+ sy = y0 - pDrawable->y;
+ w = x1 - x0;
+ h = y1 - y0;
+
+ if (w <= 0 || h <= 0)
+ goto out;
+ }
+
+ pScreen->GetImage(pDrawable, sx, sy, w, h, format, planeMask, pdstLine);
+
+out:
+ SCREEN_WRAP(pScreen, GetImage);
+}
+
+/*
+ * RootlessSourceValidate
+ * CopyArea and CopyPlane use a GC tied to the destination drawable.
+ * StartDrawing/StopDrawing wrappers won't be called if source is
+ * a visible window but the destination isn't. So, we call StartDrawing
+ * here and leave StopDrawing for the block handler.
+ */
+static void
+RootlessSourceValidate(DrawablePtr pDrawable, int x, int y, int w, int h)
+{
+ SCREEN_UNWRAP(pDrawable->pScreen, SourceValidate);
+ if (pDrawable->type == DRAWABLE_WINDOW) {
+ WindowPtr pWin = (WindowPtr)pDrawable;
+ RootlessStartDrawing(pWin);
+ }
+ if (pDrawable->pScreen->SourceValidate) {
+ pDrawable->pScreen->SourceValidate(pDrawable, x, y, w, h);
+ }
+ SCREEN_WRAP(pDrawable->pScreen, SourceValidate);
+}
+
+#ifdef RENDER
+
+static void
+rootlessComposite(CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst,
+ INT16 xSrc, INT16 ySrc, INT16 xMask, INT16 yMask,
+ INT16 xDst, INT16 yDst, CARD16 width, CARD16 height)
+{
+ ScreenPtr pScreen = pDst->pDrawable->pScreen;
+ PictureScreenPtr ps = GetPictureScreen(pScreen);
+ WindowPtr srcWin, dstWin, maskWin = NULL;
+
+ if (pMask) {
+ maskWin = (pMask->pDrawable->type == DRAWABLE_WINDOW) ?
+ (WindowPtr)pMask->pDrawable : NULL;
+ }
+ srcWin = (pSrc->pDrawable->type == DRAWABLE_WINDOW) ?
+ (WindowPtr)pSrc->pDrawable : NULL;
+ dstWin = (pDst->pDrawable->type == DRAWABLE_WINDOW) ?
+ (WindowPtr)pDst->pDrawable : NULL;
+
+ ps->Composite = SCREENREC(pScreen)->Composite;
+
+ if (srcWin && IsFramedWindow(srcWin)) RootlessStartDrawing(srcWin);
+ if (maskWin && IsFramedWindow(maskWin)) RootlessStartDrawing(maskWin);
+ if (dstWin && IsFramedWindow(dstWin)) RootlessStartDrawing(dstWin);
+
+ ps->Composite(op, pSrc, pMask, pDst,
+ xSrc, ySrc, xMask, yMask,
+ xDst, yDst, width, height);
+
+ if (dstWin && IsFramedWindow(dstWin)) {
+ RootlessDamageRect(dstWin, xDst, yDst, width, height);
+ }
+
+ ps->Composite = RootlessComposite;
+}
+
+static void
+RootlessGlyphs(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
+ PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
+ int nlist, GlyphListPtr list, GlyphPtr *glyphs)
+{
+ ScreenPtr pScreen = pDst->pDrawable->pScreen;
+ PictureScreenPtr ps = GetPictureScreen(pScreen);
+ int x, y;
+ int n;
+ GlyphPtr glyph;
+ WindowPtr srcWin, dstWin;
+
+ srcWin = (pSrc->pDrawable->type == DRAWABLE_WINDOW) ?
+ (WindowPtr)pSrc->pDrawable : NULL;
+ dstWin = (pDst->pDrawable->type == DRAWABLE_WINDOW) ?
+ (WindowPtr)pDst->pDrawable : NULL;
+
+ if (srcWin && IsFramedWindow(srcWin)) RootlessStartDrawing(srcWin);
+ if (dstWin && IsFramedWindow(dstWin)) RootlessStartDrawing(dstWin);
+
+ ps->Glyphs = SCREENREC(pScreen)->Glyphs;
+ ps->Glyphs(op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, list, glyphs);
+ ps->Glyphs = RootlessGlyphs;
+
+ if (dstWin && IsFramedWindow(dstWin))
+ {
+ x = xSrc;
+ y = ySrc;
+
+ while (nlist--)
+ {
+ /* Originally this code called DamageRect for the bounding
+ box of each glyph. But that was causing way too much
+ time to be spent in CGSBoundingRegionAddRect. So compute
+ the union of all glyphs in a list and damage that. It
+ shouldn't be very different. */
+
+ x += list->xOff;
+ y += list->yOff;
+ n = list->len;
+
+ if (n > 0)
+ {
+ BoxRec box;
+
+ glyph = *glyphs++;
+
+ box.x1 = x - glyph->info.x;
+ box.y1 = y - glyph->info.y;
+ box.x2 = box.x1 + glyph->info.width;
+ box.y2 = box.y2 + glyph->info.height;
+
+ x += glyph->info.xOff;
+ y += glyph->info.yOff;
+
+ while (--n > 0)
+ {
+ short x1, y1, x2, y2;
+
+ glyph = *glyphs++;
+
+ x1 = x - glyph->info.x;
+ y1 = y - glyph->info.y;
+ x2 = x1 + glyph->info.width;
+ y2 = y1 + glyph->info.height;
+
+ box.x1 = MAX (box.x1, x1);
+ box.y1 = MAX (box.y1, y1);
+ box.x2 = MAX (box.x2, x2);
+ box.y2 = MAX (box.y2, y2);
+
+ x += glyph->info.xOff;
+ y += glyph->info.yOff;
+ }
+
+ RootlessDamageBox (dstWin, &box);
+ }
+
+ list++;
+ }
+ }
+}
+
+#endif /* RENDER */
+
+/* ValidateTree is modified in two ways:
+ - top-level windows don't clip each other
+ - windows aren't clipped against root.
+ These only matter when validating from the root. */
+static int
+RootlessValidateTree(WindowPtr pParent, WindowPtr pChild, VTKind kind)
+{
+ int result;
+ RegionRec saveRoot;
+ ScreenPtr pScreen = pParent->drawable.pScreen;
+
+ SCREEN_UNWRAP(pScreen, ValidateTree);
+ RL_DEBUG_MSG("VALIDATETREE start ");
+
+ /* Use our custom version to validate from root */
+ if (IsRoot(pParent)) {
+ RL_DEBUG_MSG("custom ");
+ result = RootlessMiValidateTree(pParent, pChild, kind);
+ } else {
+ HUGE_ROOT(pParent);
+ result = pScreen->ValidateTree(pParent, pChild, kind);
+ NORMAL_ROOT(pParent);
+ }
+
+ SCREEN_WRAP(pScreen, ValidateTree);
+ RL_DEBUG_MSG("VALIDATETREE end\n");
+
+ return result;
+}
+
+/* MarkOverlappedWindows is modified to ignore overlapping top-level
+ windows. */
+static Bool
+RootlessMarkOverlappedWindows(WindowPtr pWin, WindowPtr pFirst,
+ WindowPtr *ppLayerWin)
+{
+ RegionRec saveRoot;
+ Bool result;
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ SCREEN_UNWRAP(pScreen, MarkOverlappedWindows);
+ RL_DEBUG_MSG("MARKOVERLAPPEDWINDOWS start ");
+
+ HUGE_ROOT(pWin);
+ if (IsRoot(pWin)) {
+ /* root - mark nothing */
+ RL_DEBUG_MSG("is root not marking ");
+ result = FALSE;
+ }
+ else if (! IsTopLevel(pWin)) {
+ /* not top-level window - mark normally */
+ result = pScreen->MarkOverlappedWindows(pWin, pFirst, ppLayerWin);
+ }
+ else {
+ /* top-level window - mark children ONLY - NO overlaps with sibs (?)
+ This code copied from miMarkOverlappedWindows() */
+
+ register WindowPtr pChild;
+ Bool anyMarked = FALSE;
+ void (* MarkWindow)() = pScreen->MarkWindow;
+
+ RL_DEBUG_MSG("is top level! ");
+ /* single layered systems are easy */
+ if (ppLayerWin) *ppLayerWin = pWin;
+
+ if (pWin == pFirst) {
+ /* Blindly mark pWin and all of its inferiors. This is a slight
+ * overkill if there are mapped windows that outside pWin's border,
+ * but it's better than wasting time on RectIn checks.
+ */
+ pChild = pWin;
+ while (1) {
+ if (pChild->viewable) {
+ if (REGION_BROKEN (pScreen, &pChild->winSize))
+ SetWinSize (pChild);
+ if (REGION_BROKEN (pScreen, &pChild->borderSize))
+ SetBorderSize (pChild);
+ (* MarkWindow)(pChild);
+ if (pChild->firstChild) {
+ pChild = pChild->firstChild;
+ continue;
+ }
+ }
+ while (!pChild->nextSib && (pChild != pWin))
+ pChild = pChild->parent;
+ if (pChild == pWin)
+ break;
+ pChild = pChild->nextSib;
+ }
+ anyMarked = TRUE;
+ pFirst = pFirst->nextSib;
+ }
+ if (anyMarked)
+ (* MarkWindow)(pWin->parent);
+ result = anyMarked;
+ }
+ NORMAL_ROOT(pWin);
+ SCREEN_WRAP(pScreen, MarkOverlappedWindows);
+ RL_DEBUG_MSG("MARKOVERLAPPEDWINDOWS end\n");
+ return result;
+}
+
+static void
+expose_1 (WindowPtr pWin)
+{
+ WindowPtr pChild;
+
+ if (!pWin->realized)
+ return;
+
+ (*pWin->drawable.pScreen->PaintWindowBackground) (pWin, &pWin->borderClip,
+ PW_BACKGROUND);
+
+ /* FIXME: comments in windowstr.h indicate that borderClip doesn't
+ include subwindow visibility. But I'm not so sure.. so we may
+ be exposing too much.. */
+
+ miSendExposures (pWin, &pWin->borderClip,
+ pWin->drawable.x, pWin->drawable.y);
+
+ for (pChild = pWin->firstChild; pChild != NULL; pChild = pChild->nextSib)
+ expose_1 (pChild);
+}
+
+void
+RootlessScreenExpose (ScreenPtr pScreen)
+{
+ expose_1 (WindowTable[pScreen->myNum]);
+}
+
+ColormapPtr
+RootlessGetColormap (ScreenPtr pScreen)
+{
+ RootlessScreenRec *s = SCREENREC (pScreen);
+
+ return s->colormap;
+}
+
+static void
+RootlessInstallColormap (ColormapPtr pMap)
+{
+ ScreenPtr pScreen = pMap->pScreen;
+ RootlessScreenRec *s = SCREENREC (pScreen);
+
+ SCREEN_UNWRAP(pScreen, InstallColormap);
+
+ if (s->colormap != pMap)
+ {
+ s->colormap = pMap;
+ s->colormap_changed = TRUE;
+ RootlessQueueRedisplay (pScreen);
+ }
+
+ pScreen->InstallColormap (pMap);
+
+ SCREEN_WRAP (pScreen, InstallColormap);
+}
+
+static void
+RootlessUninstallColormap (ColormapPtr pMap)
+{
+ ScreenPtr pScreen = pMap->pScreen;
+ RootlessScreenRec *s = SCREENREC (pScreen);
+
+ SCREEN_UNWRAP(pScreen, UninstallColormap);
+
+ if (s->colormap == pMap)
+ s->colormap = NULL;
+
+ pScreen->UninstallColormap (pMap);
+
+ SCREEN_WRAP(pScreen, UninstallColormap);
+}
+
+static void
+RootlessStoreColors (ColormapPtr pMap, int ndef, xColorItem *pdef)
+{
+ ScreenPtr pScreen = pMap->pScreen;
+ RootlessScreenRec *s = SCREENREC (pScreen);
+
+ SCREEN_UNWRAP(pScreen, StoreColors);
+
+ if (s->colormap == pMap && ndef > 0)
+ {
+ s->colormap_changed = TRUE;
+ RootlessQueueRedisplay (pScreen);
+ }
+
+ pScreen->StoreColors (pMap, ndef, pdef);
+
+ SCREEN_WRAP(pScreen, StoreColors);
+}
+
+static CARD32
+redisplay_callback (OsTimerPtr timer, CARD32 time, void *arg)
+{
+ RootlessScreenRec *screenRec = arg;
+
+ if (!screenRec->redisplay_queued)
+ {
+ /* No update needed. Stop the timer. */
+
+ screenRec->redisplay_timer_set = FALSE;
+ return 0;
+ }
+
+ screenRec->redisplay_queued = FALSE;
+
+ /* Mark that we should redisplay before waiting for I/O next time */
+ screenRec->redisplay_expired = TRUE;
+
+ /* Reinstall the timer immediately, so we get as close to our
+ redisplay interval as possible. */
+
+ return REDISPLAY_DELAY;
+}
+
+void
+RootlessQueueRedisplay (ScreenPtr pScreen)
+{
+ RootlessScreenRec *screenRec = SCREENREC (pScreen);
+
+ screenRec->redisplay_queued = TRUE;
+
+ if (screenRec->redisplay_timer_set)
+ return;
+
+ screenRec->redisplay_timer = TimerSet (screenRec->redisplay_timer,
+ 0, REDISPLAY_DELAY,
+ redisplay_callback, screenRec);
+ screenRec->redisplay_timer_set = TRUE;
+}
+
+/* Call this function when it might be a good idea to flush updates.
+ Note that it will unlock window buffers! */
+Bool
+RootlessMayRedisplay (ScreenPtr pScreen)
+{
+ RootlessScreenRec *screenRec = SCREENREC (pScreen);
+
+ if (!screenRec->redisplay_queued)
+ return FALSE;
+
+ /* If the timer has fired, or it's been long enough since the last
+ update, redisplay everything now. */
+
+ if (!screenRec->redisplay_expired)
+ {
+ CARD32 now = GetTimeInMillis ();
+
+ if (screenRec->last_redisplay + REDISPLAY_MAX_DELAY >= now)
+ return FALSE;
+ }
+
+ if (screenRec->redisplay_timer_set)
+ {
+ TimerCancel (screenRec->redisplay_timer);
+ screenRec->redisplay_timer_set = FALSE;
+ }
+
+ RootlessRedisplayScreen (screenRec->pScreen);
+ screenRec->redisplay_expired = FALSE;
+
+ return TRUE;
+}
+
+/* Flush drawing before blocking on select(). */
+static void
+RootlessBlockHandler(pointer pbdata, OSTimePtr pTimeout, pointer pReadmask)
+{
+ ScreenPtr pScreen = pbdata;
+ RootlessScreenRec *screenRec = SCREENREC (pScreen);
+
+ if (screenRec->redisplay_expired)
+ {
+ screenRec->redisplay_expired = FALSE;
+
+ if (screenRec->colormap_changed)
+ {
+ RootlessFlushScreenColormaps (screenRec->pScreen);
+ screenRec->colormap_changed = FALSE;
+ }
+
+ RootlessRedisplayScreen (screenRec->pScreen);
+ }
+}
+
+static void
+RootlessWakeupHandler(pointer data, int i, pointer LastSelectMask)
+{
+}
+
+static Bool
+RootlessAllocatePrivates(ScreenPtr pScreen)
+{
+ RootlessScreenRec *s;
+ static unsigned int rootlessGeneration = -1;
+
+ if (rootlessGeneration != serverGeneration) {
+ rootlessScreenPrivateIndex = AllocateScreenPrivateIndex();
+ if (rootlessScreenPrivateIndex == -1) return FALSE;
+ rootlessGCPrivateIndex = AllocateGCPrivateIndex();
+ if (rootlessGCPrivateIndex == -1) return FALSE;
+ rootlessWindowPrivateIndex = AllocateWindowPrivateIndex();
+ if (rootlessWindowPrivateIndex == -1) return FALSE;
+ rootlessGeneration = serverGeneration;
+ }
+
+ /* no allocation needed for screen privates */
+ if (!AllocateGCPrivate(pScreen, rootlessGCPrivateIndex,
+ sizeof(RootlessGCRec)))
+ return FALSE;
+ if (!AllocateWindowPrivate(pScreen, rootlessWindowPrivateIndex, 0))
+ return FALSE;
+
+ s = xalloc(sizeof(RootlessScreenRec));
+ if (! s) return FALSE;
+ SCREENREC(pScreen) = s;
+
+ s->pixmap_data = NULL;
+ s->pixmap_data_size = 0;
+
+ s->redisplay_timer = NULL;
+ s->redisplay_timer_set = FALSE;
+
+ return TRUE;
+}
+
+static void
+RootlessWrap(ScreenPtr pScreen)
+{
+ RootlessScreenRec *s = (RootlessScreenRec*)
+ pScreen->devPrivates[rootlessScreenPrivateIndex].ptr;
+
+#define WRAP(a) \
+ if (pScreen->a) { \
+ s->a = pScreen->a; \
+ } else { \
+ RL_DEBUG_MSG("null screen fn " #a "\n"); \
+ s->a = NULL; \
+ } \
+ pScreen->a = Rootless##a
+
+ WRAP(CreateScreenResources);
+ WRAP(CloseScreen);
+ WRAP(CreateGC);
+ WRAP(PaintWindowBackground);
+ WRAP(PaintWindowBorder);
+ WRAP(CopyWindow);
+ WRAP(GetImage);
+ WRAP(SourceValidate);
+ WRAP(CreateWindow);
+ WRAP(DestroyWindow);
+ WRAP(RealizeWindow);
+ WRAP(UnrealizeWindow);
+ WRAP(ReparentWindow);
+ WRAP(MoveWindow);
+ WRAP(PositionWindow);
+ WRAP(ResizeWindow);
+ WRAP(RestackWindow);
+ WRAP(ChangeBorderWidth);
+ WRAP(MarkOverlappedWindows);
+ WRAP(ValidateTree);
+ WRAP(ChangeWindowAttributes);
+ WRAP(InstallColormap);
+ WRAP(UninstallColormap);
+ WRAP(StoreColors);
+
+#ifdef SHAPE
+ WRAP(SetShape);
+#endif
+
+#ifdef RENDER
+ {
+ /* Composite and Glyphs don't use normal screen wrapping */
+ PictureScreenPtr ps = GetPictureScreen(pScreen);
+ s->Composite = ps->Composite;
+ ps->Composite = rootlessComposite;
+ s->Glyphs = ps->Glyphs;
+ ps->Glyphs = RootlessGlyphs;
+ }
+#endif
+
+ // WRAP(ClearToBackground); fixme put this back? useful for shaped wins?
+ // WRAP(RestoreAreas); fixme put this back?
+
+#undef WRAP
+}
+
+Bool
+RootlessSetupScreen(int index, ScreenPtr pScreen)
+{
+ RootlessScreenRec *s;
+
+ /* Add replacements for fb screen functions */
+ pScreen->PaintWindowBackground = RootlessPaintWindow;
+ pScreen->PaintWindowBorder = RootlessPaintWindow;
+
+#ifdef RENDER
+ {
+ PictureScreenPtr ps = GetPictureScreen(pScreen);
+ ps->Composite = RootlessComposite;
+ }
+#endif
+
+ if (!RootlessAllocatePrivates(pScreen))
+ return FALSE;
+
+ s = ((RootlessScreenRec*)
+ pScreen->devPrivates[rootlessScreenPrivateIndex].ptr);
+
+ s->pScreen = pScreen;
+ RootlessWrap(pScreen);
+
+ if (!RegisterBlockAndWakeupHandlers (RootlessBlockHandler,
+ RootlessWakeupHandler,
+ (pointer) pScreen))
+ {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+void
+RootlessUpdateRooted (Bool state)
+{
+ int i;
+
+ if (!state)
+ {
+ for (i = 0; i < screenInfo.numScreens; i++)
+ RootlessDisableRoot (screenInfo.screens[i]);
+ }
+ else
+ {
+ for (i = 0; i < screenInfo.numScreens; i++)
+ RootlessEnableRoot (screenInfo.screens[i]);
+ }
+}
--- /dev/null
+/*
+ * Calculate window clip lists for rootless mode
+ *
+ * This file is very closely based on mivaltree.c.
+ */
+ /* $XFree86: xc/programs/Xserver/hw/darwin/quartz/rootlessValTree.c,v 1.2 2002/06/18 19:43:04 torrey Exp $ */
+
+/*
+ * mivaltree.c --
+ * Functions for recalculating window clip lists. Main function
+ * is miValidateTree.
+ *
+
+Copyright 1987, 1988, 1989, 1998 The Open Group
+
+All Rights Reserved.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+ *
+ * Copyright 1987, 1988, 1989 by
+ * Digital Equipment Corporation, Maynard, Massachusetts,
+ *
+ * All Rights Reserved
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose and without fee is hereby granted,
+ * provided that the above copyright notice appear in all copies and that
+ * both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of Digital not be
+ * used in advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission.
+ *
+ * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+ * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ *
+ ******************************************************************/
+
+/* The panoramix components contained the following notice */
+/****************************************************************
+* *
+* Copyright (c) Digital Equipment Corporation, 1991, 1997 *
+* *
+* All Rights Reserved. Unpublished rights reserved under *
+* the copyright laws of the United States. *
+* *
+* The software contained on this media is proprietary to *
+* and embodies the confidential technology of Digital *
+* Equipment Corporation. Possession, use, duplication or *
+* dissemination of the software and media is authorized only *
+* pursuant to a valid written license from Digital Equipment *
+* Corporation. *
+* *
+* RESTRICTED RIGHTS LEGEND Use, duplication, or disclosure *
+* by the U.S. Government is subject to restrictions as set *
+* forth in Subparagraph (c)(1)(ii) of DFARS 252.227-7013, *
+* or in FAR 52.227-19, as applicable. *
+* *
+*****************************************************************/
+
+ /*
+ * Aug '86: Susan Angebranndt -- original code
+ * July '87: Adam de Boor -- substantially modified and commented
+ * Summer '89: Joel McCormack -- so fast you wouldn't believe it possible.
+ * In particular, much improved code for window mapping and
+ * circulating.
+ * Bob Scheifler -- avoid miComputeClips for unmapped windows,
+ * valdata changes
+ */
+#include "X.h"
+#include "scrnintstr.h"
+#include "validate.h"
+#include "windowstr.h"
+#include "mi.h"
+#include "regionstr.h"
+#include "mivalidate.h"
+
+#include "globals.h"
+
+#ifdef SHAPE
+/*
+ * Compute the visibility of a shaped window
+ */
+int
+RootlessShapedWindowIn (pScreen, universe, bounding, rect, x, y)
+ ScreenPtr pScreen;
+ RegionPtr universe, bounding;
+ BoxPtr rect;
+ register int x, y;
+{
+ BoxRec box;
+ register BoxPtr boundBox;
+ int nbox;
+ Bool someIn, someOut;
+ register int t, x1, y1, x2, y2;
+
+ nbox = REGION_NUM_RECTS (bounding);
+ boundBox = REGION_RECTS (bounding);
+ someIn = someOut = FALSE;
+ x1 = rect->x1;
+ y1 = rect->y1;
+ x2 = rect->x2;
+ y2 = rect->y2;
+ while (nbox--)
+ {
+ if ((t = boundBox->x1 + x) < x1)
+ t = x1;
+ box.x1 = t;
+ if ((t = boundBox->y1 + y) < y1)
+ t = y1;
+ box.y1 = t;
+ if ((t = boundBox->x2 + x) > x2)
+ t = x2;
+ box.x2 = t;
+ if ((t = boundBox->y2 + y) > y2)
+ t = y2;
+ box.y2 = t;
+ if (box.x1 > box.x2)
+ box.x2 = box.x1;
+ if (box.y1 > box.y2)
+ box.y2 = box.y1;
+ switch (RECT_IN_REGION(pScreen, universe, &box))
+ {
+ case rgnIN:
+ if (someOut)
+ return rgnPART;
+ someIn = TRUE;
+ break;
+ case rgnOUT:
+ if (someIn)
+ return rgnPART;
+ someOut = TRUE;
+ break;
+ default:
+ return rgnPART;
+ }
+ boundBox++;
+ }
+ if (someIn)
+ return rgnIN;
+ return rgnOUT;
+}
+#endif
+
+#define HasParentRelativeBorder(w) (!(w)->borderIsPixel && \
+ HasBorder(w) && \
+ (w)->backgroundState == ParentRelative)
+
+
+/*
+ *-----------------------------------------------------------------------
+ * RootlessComputeClips --
+ * Recompute the clipList, borderClip, exposed and borderExposed
+ * regions for pParent and its children. Only viewable windows are
+ * taken into account.
+ *
+ * Results:
+ * None.
+ *
+ * Side Effects:
+ * clipList, borderClip, exposed and borderExposed are altered.
+ * A VisibilityNotify event may be generated on the parent window.
+ *
+ *-----------------------------------------------------------------------
+ */
+static void
+RootlessComputeClips (pParent, pScreen, universe, kind, exposed)
+ register WindowPtr pParent;
+ register ScreenPtr pScreen;
+ register RegionPtr universe;
+ VTKind kind;
+ RegionPtr exposed; /* for intermediate calculations */
+{
+ int dx,
+ dy;
+ RegionRec childUniverse;
+ register WindowPtr pChild;
+ int oldVis, newVis;
+ BoxRec borderSize;
+ RegionRec childUnion;
+ Bool overlap;
+ RegionPtr borderVisible;
+ Bool resized;
+ /*
+ * Figure out the new visibility of this window.
+ * The extent of the universe should be the same as the extent of
+ * the borderSize region. If the window is unobscured, this rectangle
+ * will be completely inside the universe (the universe will cover it
+ * completely). If the window is completely obscured, none of the
+ * universe will cover the rectangle.
+ */
+ borderSize.x1 = pParent->drawable.x - wBorderWidth(pParent);
+ borderSize.y1 = pParent->drawable.y - wBorderWidth(pParent);
+ dx = (int) pParent->drawable.x + (int) pParent->drawable.width + wBorderWidth(pParent);
+ if (dx > 32767)
+ dx = 32767;
+ borderSize.x2 = dx;
+ dy = (int) pParent->drawable.y + (int) pParent->drawable.height + wBorderWidth(pParent);
+ if (dy > 32767)
+ dy = 32767;
+ borderSize.y2 = dy;
+
+ oldVis = pParent->visibility;
+ switch (RECT_IN_REGION( pScreen, universe, &borderSize))
+ {
+ case rgnIN:
+ newVis = VisibilityUnobscured;
+ break;
+ case rgnPART:
+ newVis = VisibilityPartiallyObscured;
+#ifdef SHAPE
+ {
+ RegionPtr pBounding;
+
+ if ((pBounding = wBoundingShape (pParent)))
+ {
+ switch (RootlessShapedWindowIn (pScreen, universe,
+ pBounding, &borderSize,
+ pParent->drawable.x,
+ pParent->drawable.y))
+ {
+ case rgnIN:
+ newVis = VisibilityUnobscured;
+ break;
+ case rgnOUT:
+ newVis = VisibilityFullyObscured;
+ break;
+ }
+ }
+ }
+#endif
+ break;
+ default:
+ newVis = VisibilityFullyObscured;
+ break;
+ }
+
+ pParent->visibility = newVis;
+ if (oldVis != newVis &&
+ ((pParent->eventMask | wOtherEventMasks(pParent)) & VisibilityChangeMask))
+ SendVisibilityNotify(pParent);
+
+ dx = pParent->drawable.x - pParent->valdata->before.oldAbsCorner.x;
+ dy = pParent->drawable.y - pParent->valdata->before.oldAbsCorner.y;
+
+ /*
+ * avoid computations when dealing with simple operations
+ */
+
+ switch (kind) {
+ case VTMap:
+ case VTStack:
+ case VTUnmap:
+ break;
+ case VTMove:
+ if ((oldVis == newVis) &&
+ ((oldVis == VisibilityFullyObscured) ||
+ (oldVis == VisibilityUnobscured)))
+ {
+ pChild = pParent;
+ while (1)
+ {
+ if (pChild->viewable)
+ {
+ if (pChild->visibility != VisibilityFullyObscured)
+ {
+ REGION_TRANSLATE( pScreen, &pChild->borderClip,
+ dx, dy);
+ REGION_TRANSLATE( pScreen, &pChild->clipList,
+ dx, dy);
+ pChild->drawable.serialNumber = NEXT_SERIAL_NUMBER;
+ if (pScreen->ClipNotify)
+ (* pScreen->ClipNotify) (pChild, dx, dy);
+
+ }
+ if (pChild->valdata)
+ {
+ REGION_INIT(pScreen,
+ &pChild->valdata->after.borderExposed,
+ NullBox, 0);
+ if (HasParentRelativeBorder(pChild))
+ {
+ REGION_SUBTRACT(pScreen,
+ &pChild->valdata->after.borderExposed,
+ &pChild->borderClip,
+ &pChild->winSize);
+ }
+ REGION_INIT( pScreen, &pChild->valdata->after.exposed,
+ NullBox, 0);
+ }
+ if (pChild->firstChild)
+ {
+ pChild = pChild->firstChild;
+ continue;
+ }
+ }
+ while (!pChild->nextSib && (pChild != pParent))
+ pChild = pChild->parent;
+ if (pChild == pParent)
+ break;
+ pChild = pChild->nextSib;
+ }
+ return;
+ }
+ /* fall through */
+ default:
+ /*
+ * To calculate exposures correctly, we have to translate the old
+ * borderClip and clipList regions to the window's new location so there
+ * is a correspondence between pieces of the new and old clipping regions.
+ */
+ if (dx || dy)
+ {
+ /*
+ * We translate the old clipList because that will be exposed or copied
+ * if gravity is right.
+ */
+ REGION_TRANSLATE( pScreen, &pParent->borderClip, dx, dy);
+ REGION_TRANSLATE( pScreen, &pParent->clipList, dx, dy);
+ }
+ break;
+ case VTBroken:
+ REGION_EMPTY (pScreen, &pParent->borderClip);
+ REGION_EMPTY (pScreen, &pParent->clipList);
+ break;
+ }
+
+ borderVisible = pParent->valdata->before.borderVisible;
+ resized = pParent->valdata->before.resized;
+ REGION_INIT( pScreen, &pParent->valdata->after.borderExposed, NullBox, 0);
+ REGION_INIT( pScreen, &pParent->valdata->after.exposed, NullBox, 0);
+
+ /*
+ * Since the borderClip must not be clipped by the children, we do
+ * the border exposure first...
+ *
+ * 'universe' is the window's borderClip. To figure the exposures, remove
+ * the area that used to be exposed from the new.
+ * This leaves a region of pieces that weren't exposed before.
+ */
+
+ if (HasBorder (pParent))
+ {
+ if (borderVisible)
+ {
+ /*
+ * when the border changes shape, the old visible portions
+ * of the border will be saved by DIX in borderVisible --
+ * use that region and destroy it
+ */
+ REGION_SUBTRACT( pScreen, exposed, universe, borderVisible);
+ REGION_DESTROY( pScreen, borderVisible);
+ }
+ else
+ {
+ REGION_SUBTRACT( pScreen, exposed, universe, &pParent->borderClip);
+ }
+ if (HasParentRelativeBorder(pParent) && (dx || dy)) {
+ REGION_SUBTRACT( pScreen, &pParent->valdata->after.borderExposed,
+ universe,
+ &pParent->winSize);
+ } else {
+ REGION_SUBTRACT( pScreen, &pParent->valdata->after.borderExposed,
+ exposed, &pParent->winSize);
+ }
+
+ REGION_COPY( pScreen, &pParent->borderClip, universe);
+
+ /*
+ * To get the right clipList for the parent, and to make doubly sure
+ * that no child overlaps the parent's border, we remove the parent's
+ * border from the universe before proceeding.
+ */
+
+ REGION_INTERSECT( pScreen, universe, universe, &pParent->winSize);
+ }
+ else
+ REGION_COPY( pScreen, &pParent->borderClip, universe);
+
+ if ((pChild = pParent->firstChild) && pParent->mapped)
+ {
+ REGION_INIT(pScreen, &childUniverse, NullBox, 0);
+ REGION_INIT(pScreen, &childUnion, NullBox, 0);
+ if ((pChild->drawable.y < pParent->lastChild->drawable.y) ||
+ ((pChild->drawable.y == pParent->lastChild->drawable.y) &&
+ (pChild->drawable.x < pParent->lastChild->drawable.x)))
+ {
+ for (; pChild; pChild = pChild->nextSib)
+ {
+ if (pChild->viewable)
+ REGION_APPEND( pScreen, &childUnion, &pChild->borderSize);
+ }
+ }
+ else
+ {
+ for (pChild = pParent->lastChild; pChild; pChild = pChild->prevSib)
+ {
+ if (pChild->viewable)
+ REGION_APPEND( pScreen, &childUnion, &pChild->borderSize);
+ }
+ }
+ REGION_VALIDATE( pScreen, &childUnion, &overlap);
+
+ for (pChild = pParent->firstChild;
+ pChild;
+ pChild = pChild->nextSib)
+ {
+ if (pChild->viewable) {
+ /*
+ * If the child is viewable, we want to remove its extents
+ * from the current universe, but we only re-clip it if
+ * it's been marked.
+ */
+ if (pChild->valdata) {
+ /*
+ * Figure out the new universe from the child's
+ * perspective and recurse.
+ */
+ REGION_INTERSECT( pScreen, &childUniverse,
+ universe,
+ &pChild->borderSize);
+ RootlessComputeClips (pChild, pScreen, &childUniverse,
+ kind, exposed);
+ }
+ /*
+ * Once the child has been processed, we remove its extents
+ * from the current universe, thus denying its space to any
+ * other sibling.
+ */
+ if (overlap)
+ REGION_SUBTRACT( pScreen, universe, universe,
+ &pChild->borderSize);
+ }
+ }
+ if (!overlap)
+ REGION_SUBTRACT( pScreen, universe, universe, &childUnion);
+ REGION_UNINIT( pScreen, &childUnion);
+ REGION_UNINIT( pScreen, &childUniverse);
+ } /* if any children */
+
+ /*
+ * 'universe' now contains the new clipList for the parent window.
+ *
+ * To figure the exposure of the window we subtract the old clip from the
+ * new, just as for the border.
+ */
+
+ if (oldVis == VisibilityFullyObscured ||
+ oldVis == VisibilityNotViewable)
+ {
+ REGION_COPY( pScreen, &pParent->valdata->after.exposed, universe);
+ }
+ else if (newVis != VisibilityFullyObscured &&
+ newVis != VisibilityNotViewable)
+ {
+ REGION_SUBTRACT( pScreen, &pParent->valdata->after.exposed,
+ universe, &pParent->clipList);
+ }
+
+ /*
+ * One last thing: backing storage. We have to try to save what parts of
+ * the window are about to be obscured. We can just subtract the universe
+ * from the old clipList and get the areas that were in the old but aren't
+ * in the new and, hence, are about to be obscured.
+ */
+ if (pParent->backStorage && !resized)
+ {
+ REGION_SUBTRACT( pScreen, exposed, &pParent->clipList, universe);
+ (* pScreen->SaveDoomedAreas)(pParent, exposed, dx, dy);
+ }
+
+ /* HACK ALERT - copying contents of regions, instead of regions */
+ {
+ RegionRec tmp;
+
+ tmp = pParent->clipList;
+ pParent->clipList = *universe;
+ *universe = tmp;
+ }
+
+#ifdef NOTDEF
+ REGION_COPY( pScreen, &pParent->clipList, universe);
+#endif
+
+ pParent->drawable.serialNumber = NEXT_SERIAL_NUMBER;
+
+ if (pScreen->ClipNotify)
+ (* pScreen->ClipNotify) (pParent, dx, dy);
+}
+
+static void
+RootlessTreeObscured(pParent)
+ register WindowPtr pParent;
+{
+ register WindowPtr pChild;
+ register int oldVis;
+
+ pChild = pParent;
+ while (1)
+ {
+ if (pChild->viewable)
+ {
+ oldVis = pChild->visibility;
+ if (oldVis != (pChild->visibility = VisibilityFullyObscured) &&
+ ((pChild->eventMask | wOtherEventMasks(pChild)) & VisibilityChangeMask))
+ SendVisibilityNotify(pChild);
+ if (pChild->firstChild)
+ {
+ pChild = pChild->firstChild;
+ continue;
+ }
+ }
+ while (!pChild->nextSib && (pChild != pParent))
+ pChild = pChild->parent;
+ if (pChild == pParent)
+ break;
+ pChild = pChild->nextSib;
+ }
+}
+
+/*
+ *-----------------------------------------------------------------------
+ * RootlessMiValidateTree --
+ * Recomputes the clip list for pParent and all its inferiors.
+ *
+ * Results:
+ * Always returns 1.
+ *
+ * Side Effects:
+ * The clipList, borderClip, exposed, and borderExposed regions for
+ * each marked window are altered.
+ *
+ * Notes:
+ * This routine assumes that all affected windows have been marked
+ * (valdata created) and their winSize and borderSize regions
+ * adjusted to correspond to their new positions. The borderClip and
+ * clipList regions should not have been touched.
+ *
+ * The top-most level is treated differently from all lower levels
+ * because pParent is unchanged. For the top level, we merge the
+ * regions taken up by the marked children back into the clipList
+ * for pParent, thus forming a region from which the marked children
+ * can claim their areas. For lower levels, where the old clipList
+ * and borderClip are invalid, we can't do this and have to do the
+ * extra operations done in miComputeClips, but this is much faster
+ * e.g. when only one child has moved...
+ *
+ *-----------------------------------------------------------------------
+ */
+/*
+ Quartz version: used for validate from root in rootless mode.
+ We need to make sure top-level windows don't clip each other,
+ and that top-level windows aren't clipped to the root window.
+*/
+/*ARGSUSED*/
+// fixme this is ugly
+// Xprint/ValTree.c doesn't work, but maybe that method can?
+int
+RootlessMiValidateTree (pRoot, pChild, kind)
+ WindowPtr pRoot; /* Parent to validate */
+ WindowPtr pChild; /* First child of pRoot that was
+ * affected */
+ VTKind kind; /* What kind of configuration caused call */
+{
+ RegionRec childClip; /* The new borderClip for the current
+ * child */
+ RegionRec exposed; /* For intermediate calculations */
+ register ScreenPtr pScreen;
+ register WindowPtr pWin;
+
+ pScreen = pRoot->drawable.pScreen;
+ if (pChild == NullWindow)
+ pChild = pRoot->firstChild;
+
+ REGION_INIT(pScreen, &childClip, NullBox, 0);
+ REGION_INIT(pScreen, &exposed, NullBox, 0);
+
+ if (REGION_BROKEN (pScreen, &pRoot->clipList) &&
+ !REGION_BROKEN (pScreen, &pRoot->borderClip))
+ {
+ // fixme this might not work, but hopefully doesn't happen anyway.
+ kind = VTBroken;
+ REGION_EMPTY (pScreen, &pRoot->clipList);
+ ErrorF("ValidateTree: BUSTED!\n");
+ }
+
+ /*
+ * Recursively compute the clips for all children of the root.
+ * They don't clip against each other or the root itself, so
+ * childClip is always reset to that child's size.
+ */
+
+ for (pWin = pChild;
+ pWin != NullWindow;
+ pWin = pWin->nextSib)
+ {
+ if (pWin->viewable) {
+ if (pWin->valdata) {
+ REGION_COPY( pScreen, &childClip, &pWin->borderSize);
+ RootlessComputeClips (pWin, pScreen, &childClip, kind, &exposed);
+ } else if (pWin->visibility == VisibilityNotViewable) {
+ RootlessTreeObscured(pWin);
+ }
+ } else {
+ if (pWin->valdata) {
+ REGION_EMPTY( pScreen, &pWin->clipList);
+ if (pScreen->ClipNotify)
+ (* pScreen->ClipNotify) (pWin, 0, 0);
+ REGION_EMPTY( pScreen, &pWin->borderClip);
+ pWin->valdata = (ValidatePtr)NULL;
+ }
+ }
+ }
+
+ REGION_UNINIT( pScreen, &childClip);
+
+ /* The root is never clipped by its children, so nothing on the root
+ is ever exposed by moving or mapping its children. */
+ REGION_INIT( pScreen, &pRoot->valdata->after.exposed, NullBox, 0);
+ REGION_INIT( pScreen, &pRoot->valdata->after.borderExposed, NullBox, 0);
+
+ return 1;
+}
--- /dev/null
+/*
+ * Rootless window management
+ */
+/*
+ * Copyright (c) 2001 Greg Parker. All Rights Reserved.
+ * Copyright (c) 2002 Torrey T. Lyons. All Rights Reserved.
+ * Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name(s) of the above copyright
+ * holders shall not be used in advertising or otherwise to promote the sale,
+ * use or other dealings in this Software without prior written authorization.
+ */
+/* Portions of this file are based on fbwindow.c, which contains the
+ * following copyright:
+ *
+ * Copyright © 1998 Keith Packard
+ */
+/* $XFree86: xc/programs/Xserver/hw/darwin/quartz/rootlessWindow.c,v 1.11 2002/09/28 00:43:39 torrey Exp $ */
+
+#include "rootless-common.h"
+#include "rootless-window.h"
+#include "darwin.h"
+#include "Xplugin.h"
+#include "x-hash.h"
+#include "x-list.h"
+#define _APPLEWM_SERVER_
+#include "applewmstr.h"
+
+#include "fb.h"
+#include "propertyst.h"
+
+#ifdef PANORAMIX
+#include "panoramiX.h"
+#include "panoramiXsrv.h"
+#endif
+
+#include <X11/Xatom.h>
+#include <pthread.h>
+
+#define DEFINE_ATOM_HELPER(func,atom_name) \
+static Atom func (void) { \
+ static unsigned int generation; \
+ static Atom atom; \
+ if (generation != serverGeneration) { \
+ generation = serverGeneration; \
+ atom = MakeAtom (atom_name, strlen (atom_name), TRUE); \
+ } \
+ return atom; \
+}
+
+DEFINE_ATOM_HELPER (xa_native_screen_origin, "_NATIVE_SCREEN_ORIGIN")
+DEFINE_ATOM_HELPER (xa_native_window_id, "_NATIVE_WINDOW_ID")
+DEFINE_ATOM_HELPER (xa_apple_no_order_in, "_APPLE_NO_ORDER_IN")
+
+/* Maps xp_window_id -> AquaWindowRec */
+static x_hash_table *window_hash;
+static pthread_mutex_t window_hash_mutex;
+
+static Bool no_configure_window;
+static Bool windows_hidden;
+
+static const int normal_window_levels[AppleWMNumWindowLevels+1] = {
+ 0, 3, 4, 5, LONG_MIN + 30, LONG_MIN + 29,
+};
+static const int rooted_window_levels[AppleWMNumWindowLevels+1] = {
+ 202, 203, 204, 205, 201, 200
+};
+
+static inline xp_error
+configure_window (xp_window_id id, unsigned int mask,
+ const xp_window_changes *values)
+{
+ if (!no_configure_window)
+ return xp_configure_window (id, mask, values);
+ else
+ return XP_Success;
+}
+
+static inline unsigned long
+current_time_in_seconds (void)
+{
+ unsigned long t = 0;
+
+ t += currentTime.milliseconds / 1000;
+ t += currentTime.months * 4294967;
+
+ return t;
+}
+
+static inline Bool
+rootlessHasRoot (ScreenPtr pScreen)
+{
+ return WINREC (WindowTable[pScreen->myNum]) != NULL;
+}
+
+void
+RootlessNativeWindowStateChanged (xp_window_id id, unsigned int state)
+{
+ WindowPtr pWin;
+ RootlessWindowRec *winRec;
+
+ pWin = RootlessGetXWindow (id);
+ if (pWin == NULL)
+ return;
+
+ winRec = WINREC (pWin);
+ if (winRec == NULL)
+ return;
+
+ winRec->is_offscreen = (state & XP_WINDOW_STATE_OFFSCREEN) != 0;
+ winRec->is_obscured = (state & XP_WINDOW_STATE_OBSCURED) != 0;
+
+#ifdef ROOTLESS
+ pWin->rootlessUnhittable = winRec->is_offscreen;
+#endif
+}
+
+void
+RootlessNativeWindowMoved (xp_window_id id)
+{
+ WindowPtr pWin;
+ xp_box bounds;
+ int sx, sy;
+ XID vlist[2];
+ Mask mask;
+ ClientPtr client;
+
+ pWin = RootlessGetXWindow (id);
+ if (pWin == NULL)
+ return;
+
+ if (xp_get_window_bounds (id, &bounds) != Success)
+ return;
+
+ sx = dixScreenOrigins[pWin->drawable.pScreen->myNum].x + darwinMainScreenX;
+ sy = dixScreenOrigins[pWin->drawable.pScreen->myNum].y + darwinMainScreenY;
+
+ /* Fake up a ConfigureWindow packet to resize the window to the
+ current bounds. */
+
+ vlist[0] = (INT16) bounds.x1 - sx;
+ vlist[1] = (INT16) bounds.y1 - sy;
+ mask = CWX | CWY;
+
+ /* pretend we're the owner of the window! */
+ client = LookupClient (pWin->drawable.id, NullClient);
+
+ /* Don't want to do anything to the physical window (avoids
+ notification-response feedback loops) */
+
+ no_configure_window = TRUE;
+ ConfigureWindow (pWin, mask, vlist, client);
+ no_configure_window = FALSE;
+}
+
+/* Updates the _NATIVE_SCREEN_ORIGIN property on the given root window. */
+static void
+set_screen_origin (WindowPtr pWin)
+{
+ long data[2];
+
+ if (!IsRoot (pWin))
+ return;
+
+ /* FIXME: move this to an extension? */
+
+ data[0] = (dixScreenOrigins[pWin->drawable.pScreen->myNum].x
+ + darwinMainScreenX);
+ data[1] = (dixScreenOrigins[pWin->drawable.pScreen->myNum].y
+ + darwinMainScreenY);
+
+ ChangeWindowProperty (pWin, xa_native_screen_origin (), XA_INTEGER,
+ 32, PropModeReplace, 2, data, TRUE);
+}
+
+/* For now, don't create a physical window until either the window is
+ realized, or we really need it (e.g. to attach VRAM surfaces to).
+ Do reset the window size so it's not clipped by the root window. */
+Bool
+RootlessCreateWindow (WindowPtr pWin)
+{
+ Bool result;
+ RegionRec saveRoot;
+
+ SCREEN_UNWRAP (pWin->drawable.pScreen, CreateWindow);
+
+ if (!IsRoot (pWin))
+ {
+ /* win/border size set by DIX, not by wrapped CreateWindow, so
+ correct it here. Don't HUGE_ROOT when pWin is the root! */
+
+ HUGE_ROOT (pWin);
+ SetWinSize (pWin);
+ SetBorderSize (pWin);
+ }
+ else
+ {
+ set_screen_origin (pWin);
+ }
+
+ result = pWin->drawable.pScreen->CreateWindow (pWin);
+
+ if (pWin->parent)
+ NORMAL_ROOT (pWin);
+
+ SCREEN_WRAP (pWin->drawable.pScreen, CreateWindow);
+
+ return result;
+}
+
+/* Destroy the physical window associated with the given window */
+static void
+rootlessDestroyFrame (WindowPtr pWin, RootlessWindowRec *winRec)
+{
+ RootlessStopDrawing (pWin, FALSE);
+
+ pthread_mutex_lock (&window_hash_mutex);
+ x_hash_table_remove (window_hash, (void *) winRec->wid);
+ pthread_mutex_unlock (&window_hash_mutex);
+
+ xp_destroy_window (winRec->wid);
+
+ xfree (winRec);
+ WINREC (pWin) = NULL;
+}
+
+Bool
+RootlessDestroyWindow (WindowPtr pWin)
+{
+ RootlessWindowRec *winRec = WINREC(pWin);
+ Bool result;
+
+ if (winRec != NULL)
+ rootlessDestroyFrame (pWin, winRec);
+
+ /* winRec is gone now */
+
+ SCREEN_UNWRAP(pWin->drawable.pScreen, DestroyWindow);
+
+ result = pWin->drawable.pScreen->DestroyWindow (pWin);
+
+ SCREEN_WRAP(pWin->drawable.pScreen, DestroyWindow);
+
+ return result;
+}
+
+#ifdef SHAPE
+static Bool
+RootlessGetShape (WindowPtr pWin, RegionPtr pShape)
+{
+ if (wBoundingShape (pWin) == NULL)
+ return FALSE;
+
+ /* wBoundingShape is relative to *inner* origin of window.
+ Translate by borderWidth to get the outside-relative position. */
+
+ REGION_INIT (pScreen, pShape, NullBox, 0);
+ REGION_COPY (pScreen, pShape, wBoundingShape (pWin));
+ REGION_TRANSLATE (pScreen, pShape, pWin->borderWidth, pWin->borderWidth);
+
+ return TRUE;
+}
+
+/* boundingShape = outside border (like borderClip)
+ clipShape = inside border (like clipList)
+ Both are in window-local coordinates
+ We only care about boundingShape (FIXME true?)
+
+ RootlessReallySetShape is used in several places other than SetShape.
+ Most importantly, SetShape is often called on unmapped windows, so we
+ have to wait until the window is mapped to reshape the frame. */
+static void
+rootlessSetShape (WindowPtr pWin)
+{
+ RootlessWindowRec *winRec = WINREC (pWin);
+
+ RegionRec newShape;
+ RegionPtr pShape;
+ xp_window_changes wc;
+
+ if (winRec == NULL)
+ return;
+
+ RootlessStopDrawing (pWin, FALSE);
+
+ pShape = RootlessGetShape (pWin, &newShape) ? &newShape : NULL;
+
+ RL_DEBUG_MSG("reshaping...");
+ RL_DEBUG_MSG("numrects %d, extents %d %d %d %d\n",
+ REGION_NUM_RECTS(&newShape),
+ newShape.extents.x1, newShape.extents.y1,
+ newShape.extents.x2, newShape.extents.y2);
+
+ RootlessDisableUpdate (pWin);
+
+ if (pShape != NULL)
+ {
+ wc.shape_nrects = REGION_NUM_RECTS (pShape);
+ wc.shape_rects = REGION_RECTS (pShape);
+ }
+ else
+ {
+ wc.shape_nrects = -1;
+ wc.shape_rects = NULL;
+ }
+
+ wc.shape_tx = wc.shape_ty = 0;
+
+ configure_window (winRec->wid, XP_SHAPE, &wc);
+
+ if (pShape != NULL)
+ REGION_UNINIT(pScreen, &newShape);
+}
+
+void
+RootlessSetShape (WindowPtr pWin)
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+
+ SCREEN_UNWRAP (pScreen, SetShape);
+
+ pScreen->SetShape (pWin);
+
+ SCREEN_WRAP (pScreen, SetShape);
+
+ rootlessSetShape (pWin);
+}
+#endif
+
+/* Disallow ParentRelative background on top-level windows
+ because the root window doesn't really have the right background
+ and fb will try to draw on the root instead of on the window.
+ ParentRelative prevention is also in PaintWindowBackground/Border()
+ so it is no longer really needed here. */
+Bool
+RootlessChangeWindowAttributes (WindowPtr pWin, unsigned long vmask)
+{
+ Bool result;
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+
+ RL_DEBUG_MSG("change window attributes start\n");
+
+ SCREEN_UNWRAP (pScreen, ChangeWindowAttributes);
+
+ result = pScreen->ChangeWindowAttributes (pWin, vmask);
+
+ SCREEN_WRAP (pScreen, ChangeWindowAttributes);
+
+ if (WINREC (pWin) != NULL)
+ {
+ /* disallow ParentRelative background state */
+
+ if (pWin->backgroundState == ParentRelative)
+ {
+ XID pixel = 0;
+ ChangeWindowAttributes (pWin, CWBackPixel, &pixel, serverClient);
+ }
+ }
+
+ RL_DEBUG_MSG("change window attributes end\n");
+ return result;
+}
+
+/* This is a hook for when DIX moves or resizes a window.
+ Update the frame position now. (x, y) are *inside* position.
+ After this, mi and fb are expecting the pixmap to be at the new location. */
+Bool
+RootlessPositionWindow (WindowPtr pWin, int x, int y)
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ RootlessWindowRec *winRec = WINREC (pWin);
+ Bool result;
+
+ RL_DEBUG_MSG("positionwindow start (win 0x%x)\n", pWin);
+
+ if (winRec != NULL)
+ {
+ if (winRec->is_drawing)
+ {
+ /* Reset frame's pixmap and move it to the new position. */
+ int bw = wBorderWidth (pWin);
+
+ winRec->pixmap->devPrivate.ptr = winRec->data;
+ TranslatePixmapBase (winRec->pixmap, - (x - bw), - (y - bw));
+ }
+ }
+
+ SCREEN_UNWRAP (pScreen, PositionWindow);
+
+ result = pScreen->PositionWindow (pWin, x, y);
+
+ SCREEN_WRAP(pScreen, PositionWindow);
+
+ RL_DEBUG_MSG("positionwindow end\n");
+ return result;
+}
+
+/* Initialize some basic attributes of the frame. Note that winRec
+ may already have valid data in it, so don't overwrite anything
+ valuable. */
+static void
+rootlessInitializeFrame (WindowPtr pWin, RootlessWindowRec *winRec)
+{
+ DrawablePtr d = &pWin->drawable;
+ int bw = wBorderWidth (pWin);
+
+ winRec->win = pWin;
+
+ winRec->x = d->x - bw;
+ winRec->y = d->y - bw;
+ winRec->width = d->width + 2*bw;
+ winRec->height = d->height + 2*bw;
+ winRec->borderWidth = bw;
+}
+
+static void
+rootlessSetNativeProperty (RootlessWindowRec *winRec)
+{
+ xp_error err;
+ unsigned int native_id;
+ long data;
+
+ err = xp_get_native_window (winRec->wid, &native_id);
+ if (err == Success)
+ {
+ /* FIXME: move this to an extension? */
+
+ data = native_id;
+ ChangeWindowProperty (winRec->win, xa_native_window_id (),
+ XA_INTEGER, 32, PropModeReplace, 1, &data, TRUE);
+ }
+}
+
+static xp_error
+rootlessColormapCallback (void *data, int first_color,
+ int n_colors, uint32_t *colors)
+{
+ return (RootlessResolveColormap (data, first_color, n_colors, colors)
+ ? XP_Success : XP_BadMatch);
+}
+
+/* If the given window doesn't have a physical window associated with it,
+ attempt to create one. If that's unsuccessful, return null. */
+static RootlessWindowRec *
+rootlessEnsureFrame (WindowPtr pWin)
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ RootlessWindowRec *winRec;
+ RegionRec shape;
+ RegionPtr pShape = NULL;
+
+ xp_window_changes wc;
+ unsigned int mask;
+ xp_error err;
+ int sx, sy;
+
+ if (WINREC (pWin) != NULL)
+ return WINREC (pWin);
+
+ if (pWin->drawable.class != InputOutput)
+ return NULL;
+
+ winRec = xalloc (sizeof(RootlessWindowRec));
+
+ if (!winRec)
+ return NULL;
+
+ rootlessInitializeFrame (pWin, winRec);
+
+ winRec->is_drawing = FALSE;
+ winRec->pixmap = NULL;
+ winRec->wid = 0;
+ winRec->is_update_disabled = FALSE;
+ winRec->is_reorder_pending = FALSE;
+ winRec->level = !IsRoot (pWin) ? 0 : AppleWMNumWindowLevels;
+ WINREC(pWin) = winRec;
+
+#ifdef SHAPE
+ if (RootlessGetShape (pWin, &shape))
+ pShape = &shape;
+#endif
+
+ sx = dixScreenOrigins[pScreen->myNum].x + darwinMainScreenX;
+ sy = dixScreenOrigins[pScreen->myNum].y + darwinMainScreenY;
+
+ mask = 0;
+
+ wc.x = sx + winRec->x;
+ wc.y = sy + winRec->y;
+ wc.width = winRec->width;
+ wc.height = winRec->height;
+ wc.bit_gravity = XP_GRAVITY_NONE;
+ mask |= XP_BOUNDS;
+
+ if (pWin->drawable.depth == 8)
+ {
+ wc.depth = XP_DEPTH_INDEX8;
+ wc.colormap = rootlessColormapCallback;
+ wc.colormap_data = pScreen;
+ mask |= XP_COLORMAP;
+ }
+ else if (pWin->drawable.depth == 15)
+ wc.depth = XP_DEPTH_RGB555;
+ else if (pWin->drawable.depth == 24)
+ wc.depth = XP_DEPTH_ARGB8888;
+ else
+ wc.depth = XP_DEPTH_NIL;
+ mask |= XP_DEPTH;
+
+ if (pShape != NULL)
+ {
+ wc.shape_nrects = REGION_NUM_RECTS (pShape);
+ wc.shape_rects = REGION_RECTS (pShape);
+ wc.shape_tx = wc.shape_ty = 0;
+ mask |= XP_SHAPE;
+ }
+
+ if (!rootlessHasRoot (pScreen))
+ wc.window_level = normal_window_levels[winRec->level];
+ else
+ wc.window_level = rooted_window_levels[winRec->level];
+ mask |= XP_WINDOW_LEVEL;
+
+ err = xp_create_window (mask, &wc, &winRec->wid);
+
+ if (err != Success)
+ {
+ xfree (winRec);
+ return NULL;
+ }
+
+ if (window_hash == NULL)
+ {
+ window_hash = x_hash_table_new (NULL, NULL, NULL, NULL);
+ pthread_mutex_init (&window_hash_mutex, NULL);
+ }
+
+ pthread_mutex_lock (&window_hash_mutex);
+ x_hash_table_insert (window_hash, (void *) winRec->wid, winRec);
+ pthread_mutex_unlock (&window_hash_mutex);
+
+ rootlessSetNativeProperty (winRec);
+
+ if (pShape != NULL)
+ REGION_UNINIT (pScreen, &shape);
+
+ return winRec;
+}
+
+/* The frame is usually created here and not in CreateWindow so that
+ windows do not eat memory until they are realized. */
+Bool
+RootlessRealizeWindow(WindowPtr pWin)
+{
+ Bool result = FALSE;
+ RegionRec saveRoot;
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ XID pixel;
+
+ RL_DEBUG_MSG("realizewindow start (win 0x%x)\n", pWin);
+
+ if (IsTopLevel (pWin) && pWin->drawable.class == InputOutput)
+ {
+ RootlessWindowRec *winRec;
+
+ winRec = rootlessEnsureFrame (pWin);
+ if (winRec == NULL)
+ return NULL;
+
+ winRec->is_reorder_pending = TRUE;
+
+ /* Disallow ParentRelative background state on top-level windows.
+ This might have been set before the window was mapped. */
+
+ if (pWin->backgroundState == ParentRelative)
+ {
+ pixel = 0;
+ ChangeWindowAttributes (pWin, CWBackPixel, &pixel, serverClient);
+ }
+ }
+
+ if (!IsRoot(pWin)) HUGE_ROOT(pWin);
+ SCREEN_UNWRAP (pScreen, RealizeWindow);
+
+ result = pScreen->RealizeWindow (pWin);
+
+ SCREEN_WRAP (pScreen, RealizeWindow);
+ if (!IsRoot(pWin)) NORMAL_ROOT(pWin);
+
+ RL_DEBUG_MSG("realizewindow end\n");
+ return result;
+}
+
+void
+RootlessEnableRoot (ScreenPtr pScreen)
+{
+ WindowPtr pRoot;
+ pRoot = WindowTable[pScreen->myNum];
+
+ rootlessEnsureFrame (pRoot);
+ (*pScreen->ClearToBackground) (pRoot, 0, 0, 0, 0, TRUE);
+ RootlessReorderWindow (pRoot);
+}
+
+void
+RootlessDisableRoot (ScreenPtr pScreen)
+{
+ WindowPtr pRoot;
+ RootlessWindowRec *winRec;
+
+ pRoot = WindowTable[pScreen->myNum];
+ winRec = WINREC (pRoot);
+
+ if (winRec != NULL)
+ {
+ rootlessDestroyFrame (pRoot, winRec);
+ DeleteProperty (pRoot, xa_native_window_id ());
+ }
+}
+
+void
+RootlessHideAllWindows (void)
+{
+ int i;
+ ScreenPtr pScreen;
+ WindowPtr pWin;
+ RootlessWindowRec *winRec;
+ xp_window_changes wc;
+
+ if (windows_hidden)
+ return;
+
+ windows_hidden = TRUE;
+
+ for (i = 0; i < screenInfo.numScreens; i++)
+ {
+ pScreen = screenInfo.screens[i];
+ pWin = WindowTable[i];
+ if (pScreen == NULL || pWin == NULL)
+ continue;
+
+ for (pWin = pWin->firstChild; pWin != NULL; pWin = pWin->nextSib)
+ {
+ if (!pWin->realized)
+ continue;
+
+ RootlessStopDrawing (pWin, FALSE);
+
+ winRec = WINREC (pWin);
+ if (winRec != NULL)
+ {
+ wc.stack_mode = XP_UNMAPPED;
+ wc.sibling = 0;
+ configure_window (winRec->wid, XP_STACKING, &wc);
+ }
+ }
+ }
+}
+
+void
+RootlessShowAllWindows (void)
+{
+ int i;
+ ScreenPtr pScreen;
+ WindowPtr pWin;
+ RootlessWindowRec *winRec;
+
+ if (!windows_hidden)
+ return;
+
+ windows_hidden = FALSE;
+
+ for (i = 0; i < screenInfo.numScreens; i++)
+ {
+ pScreen = screenInfo.screens[i];
+ pWin = WindowTable[i];
+ if (pScreen == NULL || pWin == NULL)
+ continue;
+
+ for (pWin = pWin->firstChild; pWin != NULL; pWin = pWin->nextSib)
+ {
+ if (!pWin->realized)
+ continue;
+
+ winRec = rootlessEnsureFrame (pWin);
+ if (winRec == NULL)
+ continue;
+
+ RootlessReorderWindow (pWin);
+ }
+
+ RootlessScreenExpose (pScreen);
+ }
+}
+
+void
+RootlessSetWindowLevel (WindowPtr pWin, int level)
+{
+ RootlessWindowRec *winRec;
+ xp_window_changes wc;
+
+ winRec = WINREC (pWin);
+ if (!IsTopLevel (pWin) || winRec == NULL || winRec->level == level)
+ return;
+
+ RootlessStopDrawing (pWin, FALSE);
+
+ winRec->level = level;
+
+ if (!rootlessHasRoot (pWin->drawable.pScreen))
+ wc.window_level = normal_window_levels[level];
+ else
+ wc.window_level = rooted_window_levels[level];
+
+ configure_window (winRec->wid, XP_WINDOW_LEVEL, &wc);
+}
+
+/* Return the id of the physical window displaying the given window. If
+ CREATE is true and the window has no frame, attempt to create one. */
+xp_window_id
+RootlessGetPhysicalWindow (WindowPtr pWin, Bool create)
+{
+ RootlessWindowRec *winRec;
+
+ if (TopLevelParent (pWin) == NULL)
+ return 0;
+
+ winRec = WINREC (pWin);
+
+ if (winRec == NULL && create && !IsRoot (pWin)
+ && pWin->drawable.class == InputOutput)
+ {
+ rootlessEnsureFrame (pWin);
+ winRec = WINREC (pWin);
+ }
+
+ if (winRec == NULL)
+ return 0;
+
+ return winRec->wid;
+}
+
+/* Given the id of a physical window, try to find the top-level (or root)
+ X window that it represents. */
+WindowPtr
+RootlessGetXWindow (xp_window_id wid)
+{
+ RootlessWindowRec *winRec;
+
+ if (window_hash == NULL)
+ return NULL;
+
+ winRec = x_hash_table_lookup (window_hash, (void *) wid, NULL);
+
+ return winRec != NULL ? winRec->win : NULL;
+}
+
+/* Number is an appkit window number. Returns true if X is displaying
+ a window with that number. */
+int
+RootlessKnowsWindowNumber (int number)
+{
+ Bool ret;
+ xp_window_id wid;
+
+ /* need to lock, since this function can be called by any thread */
+
+ if (window_hash == NULL)
+ return FALSE;
+
+ pthread_mutex_lock (&window_hash_mutex);
+
+ if (xp_lookup_native_window (number, &wid))
+ ret = RootlessGetXWindow (wid) != NULL;
+ else
+ ret = FALSE;
+
+ pthread_mutex_unlock (&window_hash_mutex);
+
+ return ret;
+}
+
+Bool
+RootlessUnrealizeWindow (WindowPtr pWin)
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ RootlessWindowRec *winRec = WINREC(pWin);
+ xp_window_changes wc;
+ Bool result;
+
+ RL_DEBUG_MSG("unrealizewindow start\n");
+
+ if (winRec != NULL)
+ {
+ RootlessStopDrawing (pWin, FALSE);
+
+ wc.stack_mode = XP_UNMAPPED;
+ wc.sibling = 0;
+
+ configure_window (winRec->wid, XP_STACKING, &wc);
+
+ winRec->unrealize_time = current_time_in_seconds ();
+ winRec->is_reorder_pending = FALSE;
+
+ RootlessReenableUpdate (pWin);
+ }
+
+ SCREEN_UNWRAP (pScreen, UnrealizeWindow);
+
+ result = pScreen->UnrealizeWindow (pWin);
+
+ SCREEN_WRAP (pScreen, UnrealizeWindow);
+
+ RL_DEBUG_MSG ("unrealizewindow end\n");
+ return result;
+}
+
+void
+RootlessReparentWindow (WindowPtr pWin, WindowPtr pPriorParent)
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ RootlessWindowRec *winRec = WINREC (pWin);
+
+ WindowPtr pTopWin;
+
+ if (IsRoot (pWin) || IsRoot (pWin->parent)
+ || IsTopLevel (pWin) || winRec == NULL)
+ {
+ return;
+ }
+
+ /* If the window is moving upwards towards the root has a frame,
+ we want to try to move it onto its new toplevel parent. If we
+ can't do that, we'll just have to jettison it.. */
+
+ pTopWin = TopLevelParent (pWin);
+ assert (pTopWin != pWin);
+
+ pWin->rootlessUnhittable = FALSE;
+
+ DeleteProperty (pWin, xa_native_window_id ());
+
+ if (WINREC (pTopWin) != NULL)
+ {
+ /* We're screwed. */
+ rootlessDestroyFrame (pWin, winRec);
+ }
+ else
+ {
+ xp_window_changes wc;
+ int sx, sy;
+
+ if (!pTopWin->realized && pWin->realized)
+ {
+ wc.stack_mode = XP_UNMAPPED;
+ wc.sibling = 0;
+
+ RootlessStopDrawing (pWin, FALSE);
+ configure_window (winRec->wid, XP_STACKING, &wc);
+ }
+
+ /* Switch the frame record from one to the other. */
+
+ WINREC (pWin) = NULL;
+ WINREC (pTopWin) = winRec;
+
+ rootlessInitializeFrame (pTopWin, winRec);
+ rootlessSetShape (pTopWin);
+
+ sx = dixScreenOrigins[pScreen->myNum].x + darwinMainScreenX;
+ sy = dixScreenOrigins[pScreen->myNum].y + darwinMainScreenY;
+
+ wc.x = sx + winRec->x;
+ wc.y = sy + winRec->y;
+ wc.width = winRec->width;
+ wc.height = winRec->height;
+ wc.bit_gravity = XP_GRAVITY_NONE;
+
+ RootlessStopDrawing (pWin, FALSE);
+ configure_window (winRec->wid, XP_BOUNDS, &wc);
+
+ rootlessSetNativeProperty (winRec);
+
+ if (pTopWin->realized && !pWin->realized)
+ winRec->is_reorder_pending = TRUE;
+ }
+}
+
+/* Reorder the window associated with the given frame so that it's
+ physically above the window below it in the X stacking order. */
+void
+RootlessReorderWindow (WindowPtr pWin)
+{
+ RootlessWindowRec *winRec = WINREC (pWin);
+
+ if (pWin->realized && winRec != NULL
+ && !winRec->is_reorder_pending && !windows_hidden)
+ {
+ WindowPtr newPrevW;
+ RootlessWindowRec *newPrev;
+ xp_window_changes wc;
+ Atom atom;
+ PropertyPtr prop;
+
+ /* quartz-wm sets the _APPLE_NO_ORDER_IN property on windows
+ that are being genie-restored from the Dock. We want them to
+ be mapped but remain ordered-out until the animation
+ completes (when the Dock will order them in) */
+
+ atom = xa_apple_no_order_in ();
+ for (prop = wUserProps (pWin); prop != NULL; prop = prop->next)
+ {
+ if (prop->propertyName == atom && prop->type == atom)
+ return;
+ }
+
+ RootlessStopDrawing (pWin, FALSE);
+
+ if (IsRoot (pWin))
+ {
+ wc.stack_mode = XP_MAPPED_BELOW;
+ wc.sibling = 0;
+ }
+ else
+ {
+ /* Find the next window above this one that has a mapped frame. */
+
+ newPrevW = pWin->prevSib;
+ while (newPrevW
+ && (WINREC (newPrevW) == NULL || !newPrevW->realized))
+ {
+ newPrevW = newPrevW->prevSib;
+ }
+
+ newPrev = newPrevW != NULL ? WINREC (newPrevW) : NULL;
+
+ /* Then either stack ourselves below it if it exists, or raise
+ ourselves above everything otherwise. */
+
+ if (newPrev == NULL)
+ {
+ wc.stack_mode = XP_MAPPED_ABOVE;
+ wc.sibling = 0;
+ }
+ else
+ {
+ if (newPrev->is_reorder_pending)
+ {
+ newPrev->is_reorder_pending = FALSE;
+ RootlessReorderWindow (newPrevW);
+ }
+
+ wc.stack_mode = XP_MAPPED_BELOW;
+ wc.sibling = newPrev->wid;
+ }
+ }
+
+ configure_window (winRec->wid, XP_STACKING, &wc);
+ }
+}
+
+void
+RootlessRestackWindow (WindowPtr pWin, WindowPtr pOldNextSib)
+{
+ RegionRec saveRoot;
+ RootlessWindowRec *winRec = WINREC (pWin);
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+
+ RL_DEBUG_MSG("restackwindow start\n");
+ if (winRec != NULL)
+ RL_DEBUG_MSG("restack top level \n");
+
+ HUGE_ROOT(pWin);
+ SCREEN_UNWRAP(pScreen, RestackWindow);
+
+ if (pScreen->RestackWindow != NULL)
+ pScreen->RestackWindow (pWin, pOldNextSib);
+
+ SCREEN_WRAP(pScreen, RestackWindow);
+ NORMAL_ROOT(pWin);
+
+ if (winRec != NULL && pWin->viewable)
+ RootlessReorderWindow (pWin);
+
+ RL_DEBUG_MSG("restackwindow end\n");
+}
+
+/*
+ * Specialized window copy procedures
+ */
+
+/* Globals needed during window resize and move. */
+static pointer gResizeDeathBits = NULL;
+static int gResizeDeathCount;
+static PixmapPtr gResizeDeathPix[2];
+static BoxRec gResizeDeathBounds[2];
+static CopyWindowProcPtr gResizeOldCopyWindowProc = NULL;
+
+/* CopyWindow () that doesn't do anything. For MoveWindow() of
+ top-level windows. */
+static void
+RootlessNoCopyWindow (WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
+{
+ /* Some code expects the region to be translated */
+
+ int dx = ptOldOrg.x - pWin->drawable.x;
+ int dy = ptOldOrg.y - pWin->drawable.y;
+
+ REGION_TRANSLATE (pWin->drawable.pScreen, prgnSrc, -dx, -dy);
+}
+
+/* CopyWindow used during ResizeWindow for gravity moves. (from fbCopyWindow)
+ The original always draws on the root pixmap (which we don't have).
+ Instead, draw on the parent window's pixmap.
+ Resize version: the old location's pixels are in gResizeCopyWindowSource */
+static void
+RootlessResizeCopyWindow (WindowPtr pWin, DDXPointRec ptOldOrg,
+ RegionPtr prgnSrc)
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ RegionRec rgnDst;
+ int dx, dy;
+
+ RL_DEBUG_MSG("resizecopywindowFB start (win 0x%x)\n", pWin);
+
+ /* Don't unwrap pScreen->CopyWindow.
+ The bogus rewrap with RootlessCopyWindow causes a crash if
+ CopyWindow is called again during the same resize. */
+
+ if (gResizeDeathCount == 0)
+ return;
+
+ RootlessStartDrawing (pWin);
+
+ dx = ptOldOrg.x - pWin->drawable.x;
+ dy = ptOldOrg.y - pWin->drawable.y;
+ REGION_TRANSLATE (pScreen, prgnSrc, -dx, -dy);
+ REGION_INIT (pScreen, &rgnDst, NullBox, 0);
+ REGION_INTERSECT (pScreen, &rgnDst, &pWin->borderClip, prgnSrc);
+
+ if (gResizeDeathCount == 1)
+ {
+ /* Simple case, we only have a single source pixmap. */
+
+ fbCopyRegion (&gResizeDeathPix[0]->drawable,
+ &pScreen->GetWindowPixmap(pWin)->drawable, 0,
+ &rgnDst, dx, dy, fbCopyWindowProc, 0, 0);
+ }
+ else
+ {
+ int i;
+ RegionRec clip, clipped;
+
+ /* More complex case, N source pixmaps (usually two). So we
+ intersect the destination with each source and copy those bits. */
+
+ for (i = 0; i < gResizeDeathCount; i++)
+ {
+ REGION_INIT (pScreen, &clip, gResizeDeathBounds + 0, 1);
+ REGION_INIT (pScreen, &clipped, NullBox, 0);
+ REGION_INTERSECT (pScreen, &rgnDst, &clip, &clipped);
+
+ fbCopyRegion (&gResizeDeathPix[i]->drawable,
+ &pScreen->GetWindowPixmap(pWin)->drawable, 0,
+ &clipped, dx, dy, fbCopyWindowProc, 0, 0);
+
+ REGION_UNINIT (pScreen, &clipped);
+ REGION_UNINIT (pScreen, &clip);
+ }
+ }
+
+ /* Don't update - resize will update everything */
+ REGION_UNINIT (pScreen, &rgnDst);
+
+ fbValidateDrawable (&pWin->drawable);
+
+ RL_DEBUG_MSG("resizecopywindowFB end\n");
+}
+
+/* Update *new* location of window. Old location is redrawn with
+ PaintWindowBackground/Border. Cloned from fbCopyWindow
+ The original always draws on the root pixmap (which we don't have).
+ Instead, draw on the parent window's pixmap. */
+void
+RootlessCopyWindow (WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ RootlessWindowRec *winRec;
+ WindowPtr top;
+
+ RegionRec rgnDst;
+ int dx, dy;
+ BoxPtr extents;
+ unsigned int area;
+
+ RL_DEBUG_MSG("copywindowFB start (win 0x%x)\n", pWin);
+
+ top = TopLevelParent (pWin);
+ if (top == NULL)
+ {
+ RL_DEBUG_MSG("no parent\n");
+ return;
+ }
+
+ winRec = WINREC(top);
+ if (winRec == NULL)
+ {
+ RL_DEBUG_MSG("not framed\n");
+ return;
+ }
+
+ SCREEN_UNWRAP (pScreen, CopyWindow);
+
+ dx = ptOldOrg.x - pWin->drawable.x;
+ dy = ptOldOrg.y - pWin->drawable.y;
+ REGION_TRANSLATE (pScreen, prgnSrc, -dx, -dy);
+
+ REGION_INIT (pScreen, &rgnDst, NullBox, 0);
+ REGION_INTERSECT (pScreen, &rgnDst, &pWin->borderClip, prgnSrc);
+
+ extents = REGION_EXTENTS (pScreen, &rgnDst);
+ area = (extents->x2 - extents->x1) * (extents->y2 - extents->y1);
+
+ if (area > xp_scroll_area_threshold)
+ {
+ /* Move region to window local coords */
+ REGION_TRANSLATE (pScreen, &rgnDst, -winRec->x, -winRec->y);
+
+ RootlessStopDrawing (pWin, FALSE);
+
+ xp_copy_window (winRec->wid, winRec->wid,
+ REGION_NUM_RECTS (&rgnDst),
+ REGION_RECTS (&rgnDst), dx, dy);
+ }
+ else
+ {
+ RootlessStartDrawing (pWin);
+
+ fbCopyRegion ((DrawablePtr) pWin, (DrawablePtr) pWin,
+ 0, &rgnDst, dx, dy, fbCopyWindowProc, 0, 0);
+
+ /* prgnSrc has been translated to dst position */
+ RootlessDamageRegion(pWin, prgnSrc);
+ }
+
+ REGION_UNINIT (pScreen, &rgnDst);
+ fbValidateDrawable (&pWin->drawable);
+
+ SCREEN_WRAP (pScreen, CopyWindow);
+
+ RL_DEBUG_MSG("copywindowFB end\n");
+}
+
+/*
+ * Window resize procedures
+ */
+
+enum {
+ WIDTH_SMALLER = 1,
+ HEIGHT_SMALLER = 2,
+};
+
+/* Compute which directions the window is resizing in. */
+static inline unsigned int
+resize_code (int oldX, int oldY, int oldW, int oldH,
+ int newX, int newY, int newW, int newH)
+{
+ unsigned int code = 0;
+
+ /* These comparisons were chosen to avoid setting bits when the sizes
+ are the same. (So the fastest case automatically gets taken when
+ dimensions are unchanging.) */
+
+ if (newW < oldW)
+ code |= WIDTH_SMALLER;
+
+ if (newH < oldH)
+ code |= HEIGHT_SMALLER;
+
+ return code;
+}
+
+static inline unsigned int
+resize_weighting (int oldX1, int oldY1, int oldX2, int oldY2, int oldBW,
+ int newX1, int newY1, int newX2, int newY2, int newBW)
+{
+ /* Choose gravity to avoid local copies. Do that by looking for
+ a corner that doesn't move _relative to the screen_ */
+
+ if (newBW != oldBW)
+ return XP_GRAVITY_NONE;
+
+ if (newX1 == oldX1 && newY1 == oldY1)
+ return XP_GRAVITY_NORTH_WEST;
+ else if (newX1 == oldX1 && newY2 == oldY2)
+ return XP_GRAVITY_SOUTH_WEST;
+ else if (newX2 == oldX2 && newY2 == oldY2)
+ return XP_GRAVITY_SOUTH_EAST;
+ else if (newX2 == oldX2 && newY1 == oldY1)
+ return XP_GRAVITY_NORTH_EAST;
+ else
+ return XP_GRAVITY_NONE;
+}
+
+/* Resize the given window to its new position and size. */
+static void
+resize_frame (ScreenPtr pScreen, WindowPtr pWin,
+ RootlessWindowRec *winRec, int gravity)
+{
+ int sx, sy;
+ xp_window_changes wc;
+
+ sx = dixScreenOrigins[pScreen->myNum].x + darwinMainScreenX;
+ sy = dixScreenOrigins[pScreen->myNum].y + darwinMainScreenY;
+
+ wc.x = sx + winRec->x;
+ wc.y = sy + winRec->y;
+ wc.width = winRec->width;
+ wc.height = winRec->height;
+ wc.bit_gravity = gravity;
+
+ /* It's unlikely that being async will save us anything here.
+ But it can't hurt. */
+
+ configure_window (winRec->wid, XP_BOUNDS, &wc);
+}
+
+/* Prepare to resize a top-level window. The old window's pixels are
+ saved and the implementation is told to change the window size.
+ (x,y,w,h) is outer frame of window (outside border) */
+static Bool
+StartFrameResize (WindowPtr pWin, Bool gravity,
+ int oldX, int oldY, int oldW, int oldH, int oldBW,
+ int newX, int newY, int newW, int newH, int newBW)
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ RootlessWindowRec *winRec = WINREC(pWin);
+ Bool need_window_source = FALSE, resize_after = FALSE;
+
+ BoxRec rect, copy_rect;
+ int oldX2, newX2;
+ int oldY2, newY2;
+ unsigned int weight;
+
+ oldX2 = oldX + oldW, newX2 = newX + newW;
+ oldY2 = oldY + oldH, newY2 = newY + newH;
+
+ /* Decide which resize weighting to use */
+ weight = resize_weighting (oldX, oldY, oldW, oldH, oldBW,
+ newX, newY, newW, newH, newBW);
+
+ /* Compute intersection between old and new rects */
+ rect.x1 = max(oldX, newX);
+ rect.y1 = max(oldY, newY);
+ rect.x2 = min(oldX2, newX2);
+ rect.y2 = min(oldY2, newY2);
+
+ RL_DEBUG_MSG("RESIZE TOPLEVEL WINDOW with gravity %i ", gravity);
+ RL_DEBUG_MSG("%d %d %d %d %d %d %d %d %d %d\n",
+ oldX, oldY, oldW, oldH, oldBW,
+ newX, newY, newW, newH, newBW);
+
+ RootlessDisableUpdate (pWin);
+ RootlessRedisplay (pWin);
+
+ /* If gravity is true, then we need to have a way of recovering all
+ the original bits in the window for when X rearranges the contents
+ based on the various gravity settings. The obvious way is to just
+ snapshot the entire backing store before resizing it, but that
+ it slow on large windows.
+
+ So the optimization here is to use CG's resize weighting options
+ to allow us to reason about what is left in the backing store
+ after the resize. We can then only copy what won't be there after
+ the resize, and do a two-stage copy operation.
+
+ Most of these optimizations are only applied when the top-left
+ corner of the window is fixed, since that's the common case. They
+ could probably be extended with some thought. */
+
+ gResizeDeathCount = 0;
+
+ if (gravity && weight == XP_GRAVITY_NORTH_WEST)
+ {
+ unsigned int code;
+
+ /* Top left corner is anchored. We never need to copy the
+ entire window. */
+
+ need_window_source = TRUE;
+
+ code = resize_code (oldX, oldY, oldW, oldH,
+ newX, newY, newW, newH);
+
+ if (((code ^ (code >> 1)) & 1) == 0)
+ {
+ /* Both dimensions are either getting larger, or both
+ are getting smaller. No need to copy anything. */
+
+ if (code == (WIDTH_SMALLER | HEIGHT_SMALLER))
+ {
+ /* Since the window is getting smaller, we can do gravity
+ repair on it with it's current size, then resize it
+ afterwards. */
+
+ resize_after = TRUE;
+ }
+
+ gResizeDeathCount = 1;
+ }
+ else
+ {
+ unsigned int copy_rowbytes, Bpp;
+
+ /* We can get away with a partial copy. 'rect' is the
+ intersection between old and new bounds, so copy
+ everything to the right of or below the intersection. */
+
+ RootlessStartDrawing (pWin);
+
+ if (code == WIDTH_SMALLER)
+ {
+ copy_rect.x1 = rect.x2;
+ copy_rect.y1 = rect.y1;
+ copy_rect.x2 = oldX2;
+ copy_rect.y2 = oldY2;
+ }
+ else if (code == HEIGHT_SMALLER)
+ {
+ copy_rect.x1 = rect.x1;
+ copy_rect.y1 = rect.y2;
+ copy_rect.x2 = oldX2;
+ copy_rect.y2 = oldY2;
+ }
+ else
+ abort ();
+
+ Bpp = winRec->win->drawable.bitsPerPixel / 8;
+ copy_rowbytes = (((copy_rect.x2 - copy_rect.x1) * Bpp) + 31) & ~31;
+ gResizeDeathBits = xalloc (copy_rowbytes
+ * (copy_rect.y2 - copy_rect.y1));
+
+ xp_copy_bytes ((copy_rect.x2 - copy_rect.x1) * Bpp,
+ copy_rect.y2 - copy_rect.y1, ((char *) winRec->data)
+ + ((copy_rect.y1 - oldY) * winRec->rowbytes)
+ + (copy_rect.x1 - oldX) * Bpp, winRec->rowbytes,
+ gResizeDeathBits, copy_rowbytes);
+
+ gResizeDeathBounds[1] = copy_rect;
+ gResizeDeathPix[1]
+ = GetScratchPixmapHeader(pScreen, copy_rect.x2 - copy_rect.x1,
+ copy_rect.y2 - copy_rect.y1,
+ winRec->win->drawable.depth,
+ winRec->win->drawable.bitsPerPixel,
+ winRec->rowbytes,
+ (void *) gResizeDeathBits);
+
+ TranslatePixmapBase (gResizeDeathPix[1],
+ -copy_rect.x1, -copy_rect.y1);
+
+ gResizeDeathCount = 2;
+ }
+ }
+ else if (gravity)
+ {
+ /* The general case. Just copy everything. */
+
+ RootlessStartDrawing (pWin);
+
+ gResizeDeathBits = xalloc(winRec->rowbytes * winRec->height);
+
+ memcpy(gResizeDeathBits, winRec->data,
+ winRec->rowbytes * winRec->height);
+
+ gResizeDeathBounds[0] = (BoxRec) {oldX, oldY, oldX2, oldY2};
+ gResizeDeathPix[0]
+ = GetScratchPixmapHeader(pScreen, winRec->width,
+ winRec->height,
+ winRec->win->drawable.depth,
+ winRec->win->drawable.bitsPerPixel,
+ winRec->rowbytes,
+ (void *) gResizeDeathBits);
+
+ TranslatePixmapBase (gResizeDeathPix[0], -oldX, -oldY);
+ gResizeDeathCount = 1;
+ }
+
+ RootlessStopDrawing (pWin, FALSE);
+
+ winRec->x = newX;
+ winRec->y = newY;
+ winRec->width = newW;
+ winRec->height = newH;
+ winRec->borderWidth = newBW;
+
+ /* Unless both dimensions are getting smaller, Resize the frame
+ before doing gravity repair */
+
+ if (!resize_after)
+ resize_frame (pScreen, pWin, winRec, weight);
+
+ RootlessStartDrawing(pWin);
+
+ /* If necessary, create a source pixmap pointing at the current
+ window bits. */
+
+ if (need_window_source)
+ {
+ gResizeDeathBounds[0] = (BoxRec) {oldX, oldY, oldX2, oldY2};
+ gResizeDeathPix[0]
+ = GetScratchPixmapHeader (pScreen, oldW, oldH,
+ winRec->win->drawable.depth,
+ winRec->win->drawable.bitsPerPixel,
+ winRec->rowbytes, winRec->data);
+
+ TranslatePixmapBase (gResizeDeathPix[0], -oldX, -oldY);
+ }
+
+ /* Use custom CopyWindow when moving gravity bits around
+ ResizeWindow assumes the old window contents are in the same
+ pixmap, but here they're in deathPix instead. */
+
+ if (gravity)
+ {
+ gResizeOldCopyWindowProc = pScreen->CopyWindow;
+ pScreen->CopyWindow = RootlessResizeCopyWindow;
+ }
+
+ /* If we can't rely on the window server preserving the bits we
+ need in the position we need, copy the pixels in the
+ intersection from src to dst. ResizeWindow assumes these pixels
+ are already present when making gravity adjustments. pWin
+ currently has new-sized pixmap but is in old position.
+
+ FIXME: border width change! (?) */
+
+ if (gravity && weight == XP_GRAVITY_NONE)
+ {
+ PixmapPtr src, dst;
+
+ assert (gResizeDeathCount == 1);
+
+ src = gResizeDeathPix[0];
+ dst = pScreen->GetWindowPixmap(pWin);
+
+ RL_DEBUG_MSG("Resize copy rect %d %d %d %d\n",
+ rect.x1, rect.y1, rect.x2, rect.y2);
+
+ /* rect is the intersection of the old location and new location */
+ if (BOX_NOT_EMPTY(rect) && src != NULL && dst != NULL)
+ {
+ int dx, dy;
+
+ /* The window drawable still has the old frame position, which
+ means that DST doesn't actually point at the origin of our
+ physical backing store when adjusted by the drawable.x,y
+ position. So sneakily adjust it temporarily while copying.. */
+
+ dx = newX - oldX;
+ dy = newY - oldY;
+ TranslatePixmapBase (dst, -dx, -dy);
+
+ fbCopyWindowProc(&src->drawable, &dst->drawable, NULL,
+ &rect, 1, 0, 0, FALSE, FALSE, 0, 0);
+
+ TranslatePixmapBase (dst, dx, dy);
+ }
+ }
+
+ return resize_after;
+}
+
+static void
+FinishFrameResize (WindowPtr pWin, Bool gravity, int oldX, int oldY,
+ unsigned int oldW, unsigned int oldH, unsigned int oldBW,
+ int newX, int newY, unsigned int newW, unsigned int newH,
+ unsigned int newBW, Bool resize_now)
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ RootlessWindowRec *winRec = WINREC(pWin);
+ BoxRec box;
+ int i;
+
+ RootlessStopDrawing (pWin, FALSE);
+
+ if (resize_now)
+ {
+ unsigned int weight;
+
+ /* We didn't resize anything earlier, so do it now, now that
+ we've finished gravitating the bits. */
+
+ weight = resize_weighting (oldX, oldY, oldW, oldH, oldBW,
+ newX, newY, newW, newH, newBW);
+
+ resize_frame (pScreen, pWin, winRec, weight);
+ }
+
+ /* Redraw everything. FIXME: there must be times when we don't need
+ to do this. Perhaps when top-left weighting and no gravity? */
+
+ box.x1 = 0;
+ box.y1 = 0;
+ box.x2 = winRec->width;
+ box.y2 = winRec->height;
+
+ xp_mark_window (winRec->wid, 1, &box, 0, 0);
+
+ for (i = 0; i < 2; i++)
+ {
+ if (gResizeDeathPix[i] != NULL)
+ {
+ FreeScratchPixmapHeader (gResizeDeathPix[i]);
+ gResizeDeathPix[i] = NULL;
+ }
+ }
+
+ if (gResizeDeathBits != NULL)
+ {
+ xfree (gResizeDeathBits);
+ gResizeDeathBits = NULL;
+ }
+
+ if (gravity)
+ pScreen->CopyWindow = gResizeOldCopyWindowProc;
+}
+
+/* If kind==VTOther, window border is resizing (and borderWidth is
+ already changed!!@#$) This case works like window resize, not move. */
+void
+RootlessMoveWindow (WindowPtr pWin, int x, int y, WindowPtr pSib, VTKind kind)
+{
+ RootlessWindowRec *winRec = WINREC(pWin);
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ CopyWindowProcPtr oldCopyWindowProc = NULL;
+
+ int oldX = 0, oldY = 0;
+ unsigned int oldW = 0, oldH = 0, oldBW = 0;
+ int newX = 0, newY = 0;
+ unsigned int newW = 0, newH = 0, newBW = 0;
+
+ Bool resize_after = FALSE;
+ RegionRec saveRoot;
+
+ RL_DEBUG_MSG("movewindow start \n");
+
+ if (winRec != NULL)
+ {
+ if (kind == VTMove)
+ {
+ oldX = winRec->x;
+ oldY = winRec->y;
+ RootlessRedisplay (pWin);
+ RootlessStartDrawing (pWin);
+ }
+ else
+ {
+ RL_DEBUG_MSG("movewindow border resizing ");
+
+ oldBW = winRec->borderWidth;
+ oldX = winRec->x;
+ oldY = winRec->y;
+ oldW = winRec->width;
+ oldH = winRec->height;
+
+ newBW = wBorderWidth (pWin);
+ newX = x;
+ newY = y;
+ newW = pWin->drawable.width + 2*newBW;
+ newH = pWin->drawable.height + 2*newBW;
+
+ resize_after = StartFrameResize (pWin, FALSE,
+ oldX, oldY, oldW, oldH, oldBW,
+ newX, newY, newW, newH, newBW);
+ }
+ }
+
+ HUGE_ROOT (pWin);
+ SCREEN_UNWRAP (pScreen, MoveWindow);
+
+ oldCopyWindowProc = pScreen->CopyWindow;
+
+ if (winRec != NULL)
+ pScreen->CopyWindow = RootlessNoCopyWindow;
+
+ pScreen->MoveWindow (pWin, x, y, pSib, kind);
+
+ if (winRec != NULL)
+ pScreen->CopyWindow = oldCopyWindowProc;
+
+ NORMAL_ROOT (pWin);
+ SCREEN_WRAP (pScreen, MoveWindow);
+
+ if (winRec != NULL)
+ {
+ if (kind == VTMove)
+ {
+ xp_window_changes wc;
+ int sx, sy;
+
+ RootlessStopDrawing (pWin, FALSE);
+
+ winRec->x = x;
+ winRec->y = y;
+
+ sx = dixScreenOrigins[pScreen->myNum].x + darwinMainScreenX;
+ sy = dixScreenOrigins[pScreen->myNum].y + darwinMainScreenY;
+
+ wc.x = sx + winRec->x;
+ wc.y = sy + winRec->y;
+
+ configure_window (winRec->wid, XP_ORIGIN, &wc);
+ }
+ else
+ {
+ FinishFrameResize (pWin, FALSE, oldX, oldY, oldW, oldH, oldBW,
+ newX, newY, newW, newH, newBW, resize_after);
+ }
+ }
+
+ RL_DEBUG_MSG("movewindow end\n");
+}
+
+
+/* Note: (x, y, w, h) as passed to this procedure don't match the frame
+ definition. (x,y) is corner of very outer edge, *outside* border
+ w,h is width and height *inside* border, *ignoring* border width
+ The rect (x, y, w, h) doesn't mean anything. (x, y, w+2*bw, h+2*bw)
+ is total rect (x+bw, y+bw, w, h) is inner rect */
+void
+RootlessResizeWindow (WindowPtr pWin, int x, int y,
+ unsigned int w, unsigned int h, WindowPtr pSib)
+{
+ RootlessWindowRec *winRec = WINREC(pWin);
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ RegionRec saveRoot;
+
+ int oldX = 0, oldY = 0;
+ unsigned int oldW = 0, oldH = 0, oldBW = 0;
+ int newX = 0, newY = 0;
+ unsigned int newW = 0, newH = 0, newBW = 0;
+
+ Bool resize_after = FALSE;
+
+ RL_DEBUG_MSG("resizewindow start (win 0x%x)\n", pWin);
+
+ if (winRec != NULL)
+ {
+ oldBW = winRec->borderWidth;
+ oldX = winRec->x;
+ oldY = winRec->y;
+ oldW = winRec->width;
+ oldH = winRec->height;
+
+ newBW = oldBW;
+ newX = x;
+ newY = y;
+ newW = w + 2*newBW;
+ newH = h + 2*newBW;
+
+ resize_after = StartFrameResize (pWin, TRUE,
+ oldX, oldY, oldW, oldH, oldBW,
+ newX, newY, newW, newH, newBW);
+ }
+
+ HUGE_ROOT (pWin);
+ SCREEN_UNWRAP (pScreen, ResizeWindow);
+
+ if (!IsRoot (pWin))
+ {
+ pScreen->ResizeWindow (pWin, x, y, w, h, pSib);
+ }
+ else
+ {
+ BoxRec box;
+
+ /* mi won't resize the root. So do it ourselves... */
+
+ pWin->drawable.x = x;
+ pWin->drawable.y = y;
+ pWin->drawable.width = w;
+ pWin->drawable.height = h;
+
+ box.x1 = x; box.y1 = y;
+ box.x2 = x + w; box.y2 = y + h;
+ REGION_UNINIT (pScreen, &pWin->winSize);
+ REGION_INIT (pScreen, &pWin->winSize, &box, 1);
+ REGION_COPY (pScreen, &pWin->borderSize, &pWin->winSize);
+ REGION_COPY (pScreen, &pWin->clipList, &pWin->winSize);
+ REGION_COPY (pScreen, &pWin->borderClip, &pWin->winSize);
+
+ miSendExposures (pWin, &pWin->borderClip,
+ pWin->drawable.x, pWin->drawable.y);
+ }
+
+ SCREEN_WRAP (pScreen, ResizeWindow);
+ NORMAL_ROOT (pWin);
+
+ if (winRec != NULL)
+ {
+ FinishFrameResize (pWin, TRUE, oldX, oldY, oldW, oldH, oldBW,
+ newX, newY, newW, newH, newBW, resize_after);
+ }
+
+ RL_DEBUG_MSG("resizewindow end\n");
+}
+
+void
+RootlessRepositionWindow (WindowPtr pWin)
+{
+ RootlessWindowRec *winRec = WINREC (pWin);
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ xp_window_changes wc;
+ int sx, sy;
+
+ if (IsRoot (pWin))
+ set_screen_origin (pWin);
+
+ if (winRec == NULL)
+ return;
+
+ RootlessStopDrawing (pWin, FALSE);
+
+ sx = dixScreenOrigins[pScreen->myNum].x + darwinMainScreenX;
+ sy = dixScreenOrigins[pScreen->myNum].y + darwinMainScreenY;
+
+ wc.x = sx + winRec->x;
+ wc.y = sy + winRec->y;
+
+ if (!rootlessHasRoot (pScreen))
+ wc.window_level = normal_window_levels[winRec->level];
+ else
+ wc.window_level = rooted_window_levels[winRec->level];
+
+ configure_window (winRec->wid, XP_ORIGIN | XP_WINDOW_LEVEL, &wc);
+
+ RootlessReorderWindow (pWin);
+}
+
+void
+RootlessFlushWindowColormap (WindowPtr pWin)
+{
+ RootlessWindowRec *winRec = WINREC (pWin);
+ xp_window_changes wc;
+
+ if (winRec == NULL)
+ return;
+
+ RootlessStopDrawing (pWin, FALSE);
+
+ /* This is how we tell xp that the colormap may have changed. */
+
+ wc.colormap = rootlessColormapCallback;
+ wc.colormap_data = pWin->drawable.pScreen;
+
+ configure_window (winRec->wid, XP_COLORMAP, &wc);
+}
+
+/* Set the Pixmaps on all ParentRelative windows up the ancestor chain. */
+static void
+SetPixmapOfAncestors (WindowPtr pWin)
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ WindowPtr topWin = TopLevelParent (pWin);
+ RootlessWindowRec *topWinRec = WINREC (topWin);
+ XID pixel;
+
+ while (pWin->backgroundState == ParentRelative)
+ {
+ if (pWin == topWin)
+ {
+ /* disallow ParentRelative background state on top level */
+
+ pixel = 0;
+ ChangeWindowAttributes(pWin, CWBackPixel, &pixel, serverClient);
+
+ RL_DEBUG_MSG("Cleared ParentRelative on 0x%x.\n", pWin);
+ break;
+ }
+
+ pWin = pWin->parent;
+ pScreen->SetWindowPixmap (pWin, topWinRec->pixmap);
+ }
+}
+
+/* RootlessPaintWindowBackground
+ Paint the window background while filling in the alpha channel
+ with all on. */
+void
+RootlessPaintWindowBackground (WindowPtr pWin, RegionPtr pRegion, int what)
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+
+ SCREEN_UNWRAP (pScreen, PaintWindowBackground);
+
+ RL_DEBUG_MSG("paintwindowbackground start (win 0x%x, framed %i)\n",
+ pWin, IsFramedWindow(pWin));
+
+ if (IsFramedWindow (pWin))
+ {
+ /* Don't bother trying to paint the surface background.. */
+ rootlessNoDRIDrawing++;
+
+ RootlessStartDrawing (pWin);
+ RootlessDamageRegion (pWin, pRegion);
+
+ /* For ParentRelative windows, we have to make sure the window
+ pixmap is set correctly all the way up the ancestor chain. */
+
+ if (pWin->backgroundState == ParentRelative)
+ SetPixmapOfAncestors (pWin);
+
+ pScreen->PaintWindowBackground (pWin, pRegion, what);
+
+ rootlessNoDRIDrawing--;
+ }
+
+ SCREEN_WRAP (pScreen, PaintWindowBackground);
+
+ RL_DEBUG_MSG("paintwindowbackground end\n");
+}
+
+
+/* RootlessPaintWindowBorder
+ Paint the window border while filling in the alpha channel with all on. */
+void
+RootlessPaintWindowBorder (WindowPtr pWin, RegionPtr pRegion, int what)
+{
+ SCREEN_UNWRAP (pWin->drawable.pScreen, PaintWindowBorder);
+
+ RL_DEBUG_MSG("paintwindowborder start (win 0x%x)\n", pWin);
+
+ if (IsFramedWindow (pWin))
+ {
+ RootlessStartDrawing (pWin);
+ RootlessDamageRegion (pWin, pRegion);
+
+ /* For ParentRelative windows with tiled borders, we have to make
+ sure the window pixmap is set correctly all the way up the
+ ancestor chain. */
+
+ if (!pWin->borderIsPixel && pWin->backgroundState == ParentRelative)
+ SetPixmapOfAncestors (pWin);
+ }
+
+ pWin->drawable.pScreen->PaintWindowBorder (pWin, pRegion, what);
+
+ SCREEN_WRAP (pWin->drawable.pScreen, PaintWindowBorder);
+
+ RL_DEBUG_MSG("paintwindowborder end\n");
+}
+
+
+/* FIXME: untested!
+ pWin inside corner stays the same; pWin->drawable.[xy] stays the same
+ frame moves and resizes */
+void
+RootlessChangeBorderWidth (WindowPtr pWin, unsigned int width)
+{
+ RegionRec saveRoot;
+ Bool resize_after = FALSE;
+
+ RL_DEBUG_MSG("change border width\n");
+
+ if ((int) width != wBorderWidth (pWin))
+ {
+ RootlessWindowRec *winRec = WINREC(pWin);
+
+ int oldX = 0, oldY = 0, newX = 0, newY = 0;
+ unsigned int oldW = 0, oldH = 0, oldBW = 0;
+ unsigned int newW = 0, newH = 0, newBW = 0;
+
+ if (winRec != NULL)
+ {
+ oldBW = winRec->borderWidth;
+ oldX = winRec->x;
+ oldY = winRec->y;
+ oldW = winRec->width;
+ oldH = winRec->height;
+
+ newBW = width;
+ newX = pWin->drawable.x - newBW;
+ newY = pWin->drawable.y - newBW;
+ newW = pWin->drawable.width + 2*newBW;
+ newH = pWin->drawable.height + 2*newBW;
+
+ resize_after = StartFrameResize (pWin, FALSE,
+ oldX, oldY, oldW, oldH, oldBW,
+ newX, newY, newW, newH, newBW);
+ }
+
+ HUGE_ROOT (pWin);
+ SCREEN_UNWRAP (pWin->drawable.pScreen, ChangeBorderWidth);
+
+ pWin->drawable.pScreen->ChangeBorderWidth (pWin, width);
+
+ SCREEN_WRAP (pWin->drawable.pScreen, ChangeBorderWidth);
+ NORMAL_ROOT (pWin);
+
+ if (winRec != NULL)
+ {
+ FinishFrameResize (pWin, FALSE, oldX, oldY, oldW, oldH, oldBW,
+ newX, newY, newW, newH, newBW, resize_after);
+ }
+ }
+
+ RL_DEBUG_MSG("change border width end\n");
+}
+
+/*
+ * RootlessFillRegionTiled
+ * Fill using a tile while leaving the alpha channel untouched.
+ * Based on fbfillRegionTiled.
+ */
+static void
+RootlessFillRegionTiled(
+ DrawablePtr pDrawable,
+ RegionPtr pRegion,
+ PixmapPtr pTile)
+{
+ FbBits *dst;
+ FbStride dstStride;
+ int dstBpp;
+ int dstXoff, dstYoff;
+ FbBits *tile;
+ FbStride tileStride;
+ int tileBpp;
+ int tileXoff, tileYoff; /* XXX assumed to be zero */
+ int tileWidth, tileHeight;
+ int n = REGION_NUM_RECTS(pRegion);
+ BoxPtr pbox = REGION_RECTS(pRegion);
+ int xRot = pDrawable->x;
+ int yRot = pDrawable->y;
+ FbBits planeMask;
+
+#ifdef PANORAMIX
+ if(!noPanoramiXExtension)
+ {
+ int index = pDrawable->pScreen->myNum;
+ if(&WindowTable[index]->drawable == pDrawable)
+ {
+ xRot -= panoramiXdataPtr[index].x;
+ yRot -= panoramiXdataPtr[index].y;
+ }
+ }
+#endif
+ fbGetDrawable (pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff);
+ fbGetDrawable (&pTile->drawable, tile, tileStride, tileBpp,
+ tileXoff, tileYoff);
+ tileWidth = pTile->drawable.width;
+ tileHeight = pTile->drawable.height;
+ xRot += dstXoff;
+ yRot += dstYoff;
+ planeMask = FB_ALLONES & ~RootlessAlphaMask(dstBpp);
+
+ while (n--)
+ {
+ fbTile (dst + (pbox->y1 + dstYoff) * dstStride,
+ dstStride,
+ (pbox->x1 + dstXoff) * dstBpp,
+ (pbox->x2 - pbox->x1) * dstBpp,
+ pbox->y2 - pbox->y1,
+ tile,
+ tileStride,
+ tileWidth * dstBpp,
+ tileHeight,
+ GXcopy,
+ planeMask,
+ dstBpp,
+ xRot * dstBpp,
+ yRot - pbox->y1);
+ pbox++;
+ }
+}
+
+/*
+ * RootlessPaintWindow
+ * Paint the window while filling in the alpha channel with all on.
+ * We can't use fbPaintWindow because it zeros the alpha channel.
+ */
+void
+RootlessPaintWindow(
+ WindowPtr pWin,
+ RegionPtr pRegion,
+ int what)
+{
+ switch (what) {
+ case PW_BACKGROUND:
+
+ switch (pWin->backgroundState) {
+ case None:
+ break;
+ case ParentRelative:
+ do {
+ pWin = pWin->parent;
+ } while (pWin->backgroundState == ParentRelative);
+ (*pWin->drawable.pScreen->PaintWindowBackground)(pWin, pRegion,
+ what);
+ break;
+ case BackgroundPixmap:
+ RootlessFillRegionTiled (&pWin->drawable,
+ pRegion,
+ pWin->background.pixmap);
+ break;
+ case BackgroundPixel:
+ {
+ Pixel pixel = pWin->background.pixel |
+ RootlessAlphaMask(pWin->drawable.bitsPerPixel);
+ fbFillRegionSolid (&pWin->drawable, pRegion, 0,
+ fbReplicatePixel (pixel,
+ pWin->drawable.bitsPerPixel));
+ break;
+ }
+ }
+ break;
+ case PW_BORDER:
+ if (pWin->borderIsPixel)
+ {
+ Pixel pixel = pWin->border.pixel |
+ RootlessAlphaMask(pWin->drawable.bitsPerPixel);
+ fbFillRegionSolid (&pWin->drawable, pRegion, 0,
+ fbReplicatePixel (pixel,
+ pWin->drawable.bitsPerPixel));
+ }
+ else
+ {
+ WindowPtr pBgWin;
+ for (pBgWin = pWin; pBgWin->backgroundState == ParentRelative;
+ pBgWin = pBgWin->parent);
+
+ RootlessFillRegionTiled (&pBgWin->drawable,
+ pRegion,
+ pWin->border.pixmap);
+ }
+ break;
+ }
+ fbValidateDrawable (&pWin->drawable);
+}
--- /dev/null
+/*
+ * Rootless window management
+ *
+ * Greg Parker gparker@cs.stanford.edu
+ */
+
+/* Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
+
+ Permission is hereby granted, free of charge, to any person
+ obtaining a copy of this software and associated documentation files
+ (the "Software"), to deal in the Software without restriction,
+ including without limitation the rights to use, copy, modify, merge,
+ publish, distribute, sublicense, and/or sell copies of the Software,
+ and to permit persons to whom the Software is furnished to do so,
+ subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT
+ HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ DEALINGS IN THE SOFTWARE.
+
+ Except as contained in this notice, the name(s) of the above
+ copyright holders shall not be used in advertising or otherwise to
+ promote the sale, use or other dealings in this Software without
+ prior written authorization. */
+
+/* $XFree86: xc/programs/Xserver/hw/darwin/quartz/rootlessWindow.h,v 1.2 2002/04/03 00:06:32 torrey Exp $ */
+
+#ifndef _ROOTLESSWINDOW_H
+#define _ROOTLESSWINDOW_H
+
+#include "rootless-common.h"
+
+Bool RootlessCreateWindow(WindowPtr pWin);
+Bool RootlessDestroyWindow(WindowPtr pWin);
+
+#ifdef SHAPE
+void RootlessSetShape(WindowPtr pWin);
+#endif // SHAPE
+
+Bool RootlessChangeWindowAttributes(WindowPtr pWin, unsigned long vmask);
+Bool RootlessPositionWindow(WindowPtr pWin, int x, int y);
+Bool RootlessRealizeWindow(WindowPtr pWin);
+Bool RootlessUnrealizeWindow(WindowPtr pWin);
+void RootlessReparentWindow(WindowPtr pWin, WindowPtr pPriorParent);
+void RootlessRestackWindow(WindowPtr pWin, WindowPtr pOldNextSib);
+void RootlessCopyWindow(WindowPtr pWin,DDXPointRec ptOldOrg,RegionPtr prgnSrc);
+void RootlessMoveWindow(WindowPtr pWin,int x,int y,WindowPtr pSib,VTKind kind);
+void RootlessResizeWindow(WindowPtr pWin, int x, int y,
+ unsigned int w, unsigned int h, WindowPtr pSib);
+void RootlessPaintWindowBackground(WindowPtr pWin, RegionPtr pRegion,
+ int what);
+void RootlessPaintWindowBorder(WindowPtr pWin, RegionPtr pRegion,
+ int what);
+void RootlessChangeBorderWidth(WindowPtr pWin, unsigned int width);
+void RootlessPaintWindow(WindowPtr pWin, RegionPtr pRegion, int what);
+
+#endif
--- /dev/null
+/*
+ * External interface to generic rootless mode
+ *
+ * Greg Parker gparker@cs.stanford.edu March 3, 2001
+ */
+
+/* Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
+
+ Permission is hereby granted, free of charge, to any person
+ obtaining a copy of this software and associated documentation files
+ (the "Software"), to deal in the Software without restriction,
+ including without limitation the rights to use, copy, modify, merge,
+ publish, distribute, sublicense, and/or sell copies of the Software,
+ and to permit persons to whom the Software is furnished to do so,
+ subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT
+ HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ DEALINGS IN THE SOFTWARE.
+
+ Except as contained in this notice, the name(s) of the above
+ copyright holders shall not be used in advertising or otherwise to
+ promote the sale, use or other dealings in this Software without
+ prior written authorization. */
+
+/* $XFree86: xc/programs/Xserver/hw/darwin/quartz/rootless.h,v 1.2 2002/08/28 06:41:26 torrey Exp $ */
+
+#ifndef _ROOTLESS_H
+#define _ROOTLESS_H
+
+#include "mi.h"
+#include "gcstruct.h"
+
+#include "Xplugin.h"
+
+/* Initialize rootless mode on the given screen. */
+extern Bool RootlessSetupScreen(int index, ScreenPtr pScreen);
+
+extern void RootlessUpdateScreenPixmap (ScreenPtr pScreen);
+
+extern xp_window_id RootlessGetPhysicalWindow (WindowPtr pWin, Bool create);
+extern WindowPtr RootlessGetXWindow (xp_window_id wid);
+
+extern int RootlessKnowsWindowNumber (int number);
+
+extern void RootlessDisableUpdate (WindowPtr pWin);
+extern void RootlessReenableUpdate (WindowPtr pWin);
+
+extern void RootlessUpdateRooted (Bool state);
+extern void RootlessHideAllWindows (void);
+extern void RootlessShowAllWindows (void);
+
+#endif /* _ROOTLESS_H */
--- /dev/null
+dumpkeymap
+dumpkeymap.1.html
+dumpkeymap._man
+Makefile
--- /dev/null
+XCOMM $XFree86: xc/programs/Xserver/hw/darwin/utils/Imakefile,v 1.3 2000/12/01 19:47:38 dawes Exp $
+
+ SRCS = dumpkeymap.c
+ OBJS = dumpkeymap.o
+EXTRA_LOAD_FLAGS = -framework IOKit
+
+AllTarget(ProgramTargetName(dumpkeymap))
+
+SimpleProgramTarget(dumpkeymap)
+
--- /dev/null
+dumpkeymap - Diagnostic dump and detailed description of .keymapping files
+Version 4
+
+Copyright (C)1999,2000 by Eric Sunshine <sunshine@sunshineco.com>
+Eric Sunshine, 1 December 2000
+
+OVERVIEW
+========
+This package contains the diagnostic utility dumpkeymap, as well as highly
+detailed documentation describing the internal layout of the Apple/NeXT
+.keymapping file.
+
+The dumpkeymap utility displays detailed information about each .keymapping
+file mentioned on the command-line. On Apple and NeXT platforms, if no
+.keymapping files are mentioned on the command-line, then it will instead
+dissect the key mapping currently in use by the WindowServer and AppKit.
+
+Documentation includes a thorough and detailed description of the internal
+layout of the .keymapping file, as well as an explanation of how to interpret
+the output of dumpkeymap.
+
+The complete set of documentation is available for perusal via dumpkeymap's
+manual page (dumpkeymap.1), as well as via the command-line options described
+below.
+
+ --help
+ Usage summary.
+ --help-keymapping
+ Detailed discussion of the internal format of a .keymapping file.
+ --help-output
+ Explanation of dumpkeymap's output.
+ --help-files
+ List of key mapping-related files and directories.
+ --help-diagnostics
+ Explanation of diagnostic messages.
+
+Once the manual page is been installed, documentation can also be accessed
+with the Unix `man' command:
+
+ % man dumpkeymap
+
+
+COMPILATION
+===========
+MacOS/X, Darwin
+
+ cc -Wall -o dumpkeymap dumpkeymap.c -framework IOKit
+
+MacOS/X DP4 (Developer Preview 4)
+
+ cc -Wall -o dumpkeymap dumpkeymap.c -FKernel -framework IOKit
+
+MacOS/X Server, OpenStep, NextStep
+
+ cc -Wall -o dumpkeymap dumpkeymap.c
+
+By default, dumpkeymap is configured to interface with the HID driver (Apple)
+or event-status driver (NeXT), thus allowing it to dump the key mapping which
+is currently in use by the WindowServer and AppKit. However, these facilities
+are specific to Apple/NeXT. In order to build dumpkeymap for non-Apple/NeXT
+platforms, you must define the DUMPKEYMAP_FILE_ONLY flag when compiling the
+program. This flag inhibits use of the HID and event-status drivers and
+configures dumpkeymap to work strictly with raw key mapping files.
+
+For example, to compile for Linux:
+
+ gcc -Wall -DDUMPKEYMAP_FILE_ONLY -o dumpkeymap dumpkeymap.c
+
+
+INSTALLATION
+============
+Install the dumpkeymap executable image in a location mentioned in the PATH
+environment variable. Typicall locations for executable files are:
+
+ /usr/local/bin
+ $(HOME)/bin
+
+Install the manual page, dumpkeymap.1, in the `man1' subdirectory one of the
+standard manual page locations or in any other location mentioned by the
+MANPATH environment variable.
+
+Typical locations for manual pages on most Unix platforms are:
+
+ /usr/local/man/man1
+
+Typical locations for manual pages on MacOS/X, Darwin, and MacOS/X Server are:
+
+ /usr/local/man/man1
+ /Local/Documentation/ManPages/man1
+ /Network/Documentation/ManPages/man1
+
+Typical locations for manual pages on OpenStep and NextStep are:
+
+ /usr/local/man/man1
+ /LocalLibrary/Documentation/ManPages/man1
+ /LocalDeveloper/Documentation/ManPages/man1
+
+
+CONCLUSION
+==========
+This program and its accompanying documentation were written by Eric Sunshine
+and are copyright (C)1999,2000 by Eric Sunshine <sunshine@sunshineco.com>.
+
+The implementation of dumpkeymap is based upon information gathered on
+September 3, 1997 by Eric Sunshine <sunshine@sunshineco.com> and Paul S.
+McCarthy <zarnuk@zarnuk.com> during an effort to reverse engineer the format
+of the NeXT .keymapping file.
+
+
+
+$XFree86: xc/programs/Xserver/hw/darwin/utils/README.txt,v 1.2 2000/12/05 21:18:34 dawes Exp $
--- /dev/null
+// $XFree86: xc/programs/Xserver/hw/darwin/utils/dumpkeymap.c,v 1.3 2000/12/05 21:18:34 dawes Exp $
+//=============================================================================
+//
+// Copyright (C) 1999,2000 by Eric Sunshine <sunshine@sunshineco.com>
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+// 3. The name of the author may not be used to endorse or promote products
+// derived from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+// NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+//=============================================================================
+//-----------------------------------------------------------------------------
+// dumpkeymap.c
+//
+// Prints a textual representation of each Apple/NeXT .keymapping file
+// mentioned on the command-line. If no files are mentioned and if the
+// local machine is an Apple or NeXT installation, then the key mapping
+// currently in use by the WindowServer and the AppKit is printed
+// instead.
+//
+// Invoke dumpkeymap with one of the options listed below in order to
+// view detailed documentation about .keymapping files and the use of
+// this program.
+//
+// --help: Usage summary.
+// --help-keymapping: Detailed discussion of the internal format of a
+// .keymapping file.
+// --help-output: Explanation of dumpkeymap's output.
+// --help-files: List of key mapping-related files and directories.
+// --help-diagnostics: Explanation of diagnostic messages.
+//
+// COMPILATION INSTRUCTIONS
+//
+// MacOS/X, Darwin
+// cc -Wall -o dumpkeymap dumpkeymap.c -framework IOKit
+//
+// MacOS/X DP4 (Developer Preview 4)
+// cc -Wall -o dumpkeymap dumpkeymap.c -FKernel -framework IOKit
+//
+// MacOS/X Server, OpenStep, NextStep
+// cc -Wall -o dumpkeymap dumpkeymap.c
+//
+// By default, dumpkeymap is configured to interface with the HID driver
+// (Apple) or event-status driver (NeXT), thus allowing it to dump the
+// key mapping which is currently in use by the WindowServer and AppKit.
+// However, these facilities are specific to Apple/NeXT. In order to
+// build dumpkeymap for non-Apple/NeXT platforms, you must define the
+// DUMPKEYMAP_FILE_ONLY flag when compiling the program. This flag
+// inhibits use of the HID and event-status drivers and configures
+// dumpkeymap to work strictly with raw key mapping files.
+//
+// For example, to compile for Linux:
+// gcc -Wall -DDUMPKEYMAP_FILE_ONLY -o dumpkeymap dumpkeymap.c
+//
+// CONCLUSION
+//
+// This program and its accompanying documentation were written by Eric
+// Sunshine and are copyright (C)1999,2000 by Eric Sunshine
+// <sunshine@sunshineco.com>.
+//
+// The implementation of dumpkeymap is based upon information gathered
+// on September 3, 1997 by Eric Sunshine <sunshine@sunshineco.com> and
+// Paul S. McCarthy <zarnuk@zarnuk.com> during an effort to reverse
+// engineer the format of the NeXT .keymapping file.
+//
+// HISTORY
+//
+// v4 2000/12/01 Eric Sunshine <sunshine@sunshineco.com>
+// Updated manual page to work with `rman', the `man' to `HTML'
+// translator. Unfortunately, however, rman is missing important
+// roff features such as diversions, indentation, and tab stops,
+// and is also hideously buggy, so getting the manual to work with
+// rman required quite a few work-arounds.
+// The manual page has now been tested with nroff (plain text), troff
+// (PostScript, etc.), groff (PostScript), and rman (HTML, etc.)
+//
+// v3 2000/11/28 Eric Sunshine <sunshine@sunshineco.com>
+// Considerably expanded the documentation.
+// Augmented the existing description of .keymapping internals.
+// Added these new documentation topics:
+// - Output: Very important section describing how to interpret
+// the output of dumpkeymap.
+// - Files: Lists files and directories related to key mappings.
+// - Diagnostics: Explains diagnostic messages issued by
+// dumpkeymap.
+// Created a manual page (dumpkeymap.1) which contains the complete
+// set of documentation for key mapping files and dumpkeymap.
+// Added command-line options (--help, --help-keymapping,
+// --help-output, --help-files, --help-diagnostics) which allow
+// access to all key mapping documentation. Previously the
+// description of the internal layout of a .keymapping file was
+// only available as source code comments.
+// Added --version option.
+// Ported to non-Apple/NeXT platforms. Defining the pre-processor
+// flag DUMPKEYMAP_FILE_ONLY at compilation time inhibits use of
+// Apple/NeXT-specific API.
+// Added a README file.
+//
+// v2 2000/11/13 Eric Sunshine <sunshine@sunshineco.com>
+// Converted from C++ to plain-C.
+// Now parses and takes into account the "number-size" flag stored
+// with each key map. This flag indicates the size, in bytes, of
+// all remaining numeric values in the mapping. Updated all code
+// to respect this flag. (Previously, the purpose of this field
+// was unknown, and it was thus denoted as
+// `KeyMapping::fill[2]'.)
+// Updated all documentation; especially the "KEY MAPPING
+// DESCRIPTION" section. Added discussion of the "number-size"
+// flag and revamped all structure definitions to use the generic
+// data type `number' instead of `uchar' or 'byte'. Clarified
+// several sections of the documentation and added missing
+// discussions about type definitions and the relationship of
+// `interface' and `handler_id' to .keymapping and .keyboard
+// files.
+// Updated compilation instructions to include directions for all
+// platforms on which this program might be built.
+// Now published under the formal BSD license rather than a
+// home-grown license.
+//
+// v1 1999/09/08 Eric Sunshine <sunshine@sunshineco.com>
+// Created.
+//-----------------------------------------------------------------------------
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#if !defined(DUMPKEYMAP_FILE_ONLY)
+#include <drivers/event_status_driver.h>
+#endif
+
+#define PROG_NAME "dumpkeymap"
+#define PROG_VERSION "4"
+#define AUTHOR_NAME "Eric Sunshine"
+#define AUTHOR_EMAIL "sunshine@sunshineco.com"
+#define AUTHOR_INFO AUTHOR_NAME " <" AUTHOR_EMAIL ">"
+#define COPYRIGHT "Copyright (C) 1999,2000 by " AUTHOR_INFO
+
+typedef unsigned char byte;
+typedef unsigned short word;
+typedef unsigned int natural;
+typedef unsigned long dword;
+typedef dword number;
+
+#define ASCII_SET 0x00
+#define BIND_FUNCTION 0xfe
+#define BIND_SPECIAL 0xff
+
+#define OPT_SWITCH(X) { char const* switched_str__=(X); if (0) {
+#define OPT_CASE(X,Y) } else if (strcmp(switched_str__,(#X)) == 0 || \
+ strcmp(switched_str__,(#Y)) == 0) {
+#define OPT_DEFAULT } else {
+#define OPT_SWITCH_END }}
+
+//-----------------------------------------------------------------------------
+// Translation Tables
+//-----------------------------------------------------------------------------
+static char const* const SPECIAL_CODE[] =
+ {
+ "sound-up",
+ "sound-down",
+ "brightness-up",
+ "brightness-down",
+ "alpha-lock",
+ "help",
+ "power",
+ "secondary-up-arrow",
+ "secondary-down-arrow"
+ };
+#define N_SPECIAL_CODE (sizeof(SPECIAL_CODE) / sizeof(SPECIAL_CODE[0]))
+
+static char const* const MODIFIER_CODE[] =
+ {
+ "alpha-lock",
+ "shift",
+ "control",
+ "alternate",
+ "command",
+ "keypad",
+ "help"
+ };
+#define N_MODIFIER_CODE (sizeof(MODIFIER_CODE) / sizeof(MODIFIER_CODE[0]))
+
+static char const* const MODIFIER_MASK[] =
+ {
+ "-----", // R = carriage-return
+ "----L", // A = alternate
+ "---S-", // C = control
+ "---SL", // S = shift
+ "--C--", // L = alpha-lock
+ "--C-L",
+ "--CS-",
+ "--CSL",
+ "-A---",
+ "-A--L",
+ "-A-S-",
+ "-A-SL",
+ "-AC--",
+ "-AC-L",
+ "-ACS-",
+ "-ACSL",
+ "R----",
+ "R---L",
+ "R--S-",
+ "R--SL",
+ "R-C--",
+ "R-C-L",
+ "R-CS-",
+ "R-CSL",
+ "RA---",
+ "RA--L",
+ "RA-S-",
+ "RA-SL",
+ "RAC--",
+ "RAC-L",
+ "RACS-",
+ "RACSL",
+ };
+#define N_MODIFIER_MASK (sizeof(MODIFIER_MASK) / sizeof(MODIFIER_MASK[0]))
+
+#define FUNCTION_KEY_FIRST 0x20
+static char const* const FUNCTION_KEY[] =
+ {
+ "F1", // 0x20
+ "F2", // 0x21
+ "F3", // 0x22
+ "F4", // 0x23
+ "F5", // 0x24
+ "F6", // 0x25
+ "F7", // 0x26
+ "F8", // 0x27
+ "F9", // 0x28
+ "F10", // 0x29
+ "F11", // 0x2a
+ "F12", // 0x2b
+ "insert", // 0x2c
+ "delete", // 0x2d
+ "home", // 0x2e
+ "end", // 0x2f
+ "page up", // 0x30
+ "page down", // 0x31
+ "print screen", // 0x32
+ "scroll lock", // 0x33
+ "pause", // 0x34
+ "sys-request", // 0x35
+ "break", // 0x36
+ "reset (HIL)", // 0x37
+ "stop (HIL)", // 0x38
+ "menu (HIL)", // 0x39
+ "user (HIL)", // 0x3a
+ "system (HIL)", // 0x3b
+ "print (HIL)", // 0x3c
+ "clear line (HIL)", // 0x3d
+ "clear display (HIL)", // 0x3e
+ "insert line (HIL)", // 0x3f
+ "delete line (HIL)", // 0x40
+ "insert char (HIL)", // 0x41
+ "delete char (HIL)", // 0x42
+ "prev (HIL)", // 0x43
+ "next (HIL)", // 0x44
+ "select (HIL)", // 0x45
+ };
+#define N_FUNCTION_KEY (sizeof(FUNCTION_KEY) / sizeof(FUNCTION_KEY[0]))
+
+
+//-----------------------------------------------------------------------------
+// Data Stream Object
+// Can be configured to treat embedded "numbers" as being composed of
+// either 1, 2, or 4 bytes, apiece.
+//-----------------------------------------------------------------------------
+typedef struct _DataStream
+ {
+ byte const* data;
+ byte const* data_end;
+ natural number_size; // Size in bytes of a "number" in the stream.
+ } DataStream;
+
+static DataStream* new_data_stream( byte const* data, int size )
+ {
+ DataStream* s = (DataStream*)malloc( sizeof(DataStream) );
+ s->data = data;
+ s->data_end = data + size;
+ s->number_size = 1; // Default to byte-sized numbers.
+ return s;
+ }
+
+static void destroy_data_stream( DataStream* s )
+ {
+ free(s);
+ }
+
+static int end_of_stream( DataStream* s )
+ {
+ return (s->data >= s->data_end);
+ }
+
+static void expect_nbytes( DataStream* s, int nbytes )
+ {
+ if (s->data + nbytes > s->data_end)
+ {
+ fputs( "Insufficient data in keymapping data stream.\n", stderr );
+ exit(-1);
+ }
+ }
+
+static byte get_byte( DataStream* s )
+ {
+ expect_nbytes( s, 1 );
+ return *s->data++;
+ }
+
+static word get_word( DataStream* s )
+ {
+ word hi, lo;
+ expect_nbytes( s, 2 );
+ hi = *s->data++;
+ lo = *s->data++;
+ return ((hi << 8) | lo);
+ }
+
+static dword get_dword( DataStream* s )
+ {
+ dword b1, b2, b3, b4;
+ expect_nbytes( s, 4 );
+ b4 = *s->data++;
+ b3 = *s->data++;
+ b2 = *s->data++;
+ b1 = *s->data++;
+ return ((b4 << 24) | (b3 << 16) | (b2 << 8) | b1);
+ }
+
+static number get_number( DataStream* s )
+ {
+ switch (s->number_size)
+ {
+ case 4: return get_dword(s);
+ case 2: return get_word(s);
+ default: return get_byte(s);
+ }
+ }
+
+
+//-----------------------------------------------------------------------------
+// Translation Utility Functions
+//-----------------------------------------------------------------------------
+static char const* special_code_desc( number n )
+ {
+ if (n < N_SPECIAL_CODE)
+ return SPECIAL_CODE[n];
+ else
+ return "invalid";
+ }
+
+static char const* modifier_code_desc( number n )
+ {
+ if (n < N_MODIFIER_CODE)
+ return MODIFIER_CODE[n];
+ else
+ return "invalid";
+ }
+
+static char const* modifier_mask_desc( number n )
+ {
+ if (n < N_MODIFIER_MASK)
+ return MODIFIER_MASK[n];
+ else
+ return "?????";
+ }
+
+static char const* function_key_desc( number n )
+ {
+ if (n >= FUNCTION_KEY_FIRST && n < N_FUNCTION_KEY + FUNCTION_KEY_FIRST)
+ return FUNCTION_KEY[ n - FUNCTION_KEY_FIRST ];
+ else
+ return "unknown";
+ }
+
+static number bits_set( number mask )
+ {
+ number n = 0;
+ for ( ; mask != 0; mask >>= 1)
+ if ((mask & 0x01) != 0)
+ n++;
+ return n;
+ }
+
+
+//-----------------------------------------------------------------------------
+// Unparse a list of Modifier records.
+//-----------------------------------------------------------------------------
+static void unparse_modifiers( DataStream* s )
+ {
+ number nmod = get_number(s); // Modifier count
+ printf( "MODIFIERS [%lu]\n", nmod );
+ while (nmod-- > 0)
+ {
+ number nscan;
+ number const code = get_number(s);
+ printf( "%s:", modifier_code_desc(code) );
+ nscan = get_number(s);
+ while (nscan-- > 0)
+ printf( " 0x%02x", (natural)get_number(s) );
+ putchar( '\n' );
+ }
+ putchar( '\n' );
+ }
+
+
+//-----------------------------------------------------------------------------
+// Unparse a list of Character records.
+//-----------------------------------------------------------------------------
+typedef void (*UnparseSpecialFunc)( number code );
+
+static void unparse_char_codes(
+ DataStream* s, number ncodes, UnparseSpecialFunc unparse_special )
+ {
+ if (ncodes != 0)
+ {
+ while (ncodes-- > 0)
+ {
+ number const char_set = get_number(s);
+ number const code = get_number(s);
+ putchar(' ');
+ switch (char_set)
+ {
+ case ASCII_SET:
+ {
+ int const c = (int)code;
+ if (isprint(c))
+ printf( "\"%c\"", c );
+ else if (code < ' ')
+ printf( "\"^%c\"", c + '@' );
+ else
+ printf( "%02x", c );
+ break;
+ }
+ case BIND_FUNCTION:
+ printf( "[%s]", function_key_desc(code) );
+ break;
+ case BIND_SPECIAL:
+ unparse_special( code );
+ break;
+ default:
+ printf( "%02x/%02x", (natural)char_set, (natural)code );
+ break;
+ }
+ }
+ }
+ }
+
+
+//-----------------------------------------------------------------------------
+// Unparse a list of scan code bindings.
+//-----------------------------------------------------------------------------
+static void unparse_key_special( number code )
+ {
+ printf( "{seq#%lu}", code );
+ }
+
+static void unparse_characters( DataStream* s )
+ {
+ number const NOT_BOUND = 0xff;
+ number const nscans = get_number(s);
+ number scan;
+ printf( "CHARACTERS [%lu]\n", nscans );
+ for (scan = 0; scan < nscans; scan++)
+ {
+ number const mask = get_number(s);
+ printf( "scan 0x%02x: ", (natural)scan );
+ if (mask == NOT_BOUND)
+ fputs( "not-bound\n", stdout );
+ else
+ {
+ number const bits = bits_set( mask );
+ number const codes = 1 << bits;
+ printf( "%s ", modifier_mask_desc(mask) );
+ unparse_char_codes( s, codes, unparse_key_special );
+ putchar( '\n' );
+ }
+ }
+ putchar( '\n' );
+ }
+
+
+//-----------------------------------------------------------------------------
+// Unparse a list of key sequences.
+//-----------------------------------------------------------------------------
+static void unparse_sequence_special( number code )
+ {
+ printf( "{%s}", (code == 0 ? "unmodify" : modifier_code_desc(code)) );
+ }
+
+static void unparse_sequences( DataStream* s )
+ {
+ number const nseqs = get_number(s);
+ number seq;
+ printf( "SEQUENCES [%lu]\n", nseqs );
+ for (seq = 0; seq < nseqs; seq++)
+ {
+ number const nchars = get_number(s);
+ printf( "sequence %lu:", seq );
+ unparse_char_codes( s, nchars, unparse_sequence_special );
+ putchar( '\n' );
+ }
+ putchar( '\n' );
+ }
+
+
+//-----------------------------------------------------------------------------
+// Unparse a list of special keys.
+//-----------------------------------------------------------------------------
+static void unparse_specials( DataStream* s )
+ {
+ number nspecials = get_number(s);
+ printf( "SPECIALS [%lu]\n", nspecials );
+ while (nspecials-- > 0)
+ {
+ number const special = get_number(s);
+ number const scan = get_number(s);
+ printf( "%s: 0x%02x\n", special_code_desc(special), (natural)scan );
+ }
+ putchar( '\n' );
+ }
+
+
+//-----------------------------------------------------------------------------
+// Unparse the number-size flag.
+//-----------------------------------------------------------------------------
+static void unparse_numeric_size( DataStream* s )
+ {
+ word const numbers_are_shorts = get_word(s);
+ s->number_size = numbers_are_shorts ? 2 : 1;
+ }
+
+
+//-----------------------------------------------------------------------------
+// Unparse an entire key map.
+//-----------------------------------------------------------------------------
+static void unparse_keymap_data( DataStream* s )
+ {
+ unparse_numeric_size(s);
+ unparse_modifiers(s);
+ unparse_characters(s);
+ unparse_sequences(s);
+ unparse_specials(s);
+ }
+
+
+//-----------------------------------------------------------------------------
+// Unparse the active key map.
+//-----------------------------------------------------------------------------
+#if !defined(DUMPKEYMAP_FILE_ONLY)
+static int unparse_active_keymap( void )
+ {
+ int rc = 1;
+ NXEventHandle const h = NXOpenEventStatus();
+ if (h == 0)
+ fputs( "Unable to open event status driver.\n", stderr );
+ else
+ {
+ NXKeyMapping km;
+ km.size = NXKeyMappingLength(h);
+ if (km.size <= 0)
+ fprintf( stderr, "Bad key mapping length (%d).\n", km.size );
+ else
+ {
+ km.mapping = (char*)malloc( km.size );
+ if (NXGetKeyMapping( h, &km ) == 0)
+ fputs( "Unable to get current key mapping.\n", stderr );
+ else
+ {
+ DataStream* stream =
+ new_data_stream( (byte const*)km.mapping, km.size );
+ fputs( "=============\nACTIVE KEYMAP\n=============\n\n",
+ stdout);
+ unparse_keymap_data( stream );
+ destroy_data_stream( stream );
+ rc = 0;
+ }
+ free( km.mapping );
+ }
+ NXCloseEventStatus(h);
+ }
+ return rc;
+ }
+#endif
+
+
+//-----------------------------------------------------------------------------
+// Unparse one key map from a keymapping file.
+//-----------------------------------------------------------------------------
+static void unparse_keymap( DataStream* s )
+ {
+ dword const interface = get_dword(s);
+ dword const handler_id = get_dword(s);
+ dword const map_size = get_dword(s);
+ printf( "interface: 0x%02lx\nhandler_id: 0x%02lx\nmap_size: %lu bytes\n\n",
+ interface, handler_id, map_size );
+ unparse_keymap_data(s);
+ }
+
+
+//-----------------------------------------------------------------------------
+// Check the magic number of a keymapping file.
+//-----------------------------------------------------------------------------
+static int check_magic_number( DataStream* s )
+ {
+ return (get_byte(s) == 'K' &&
+ get_byte(s) == 'Y' &&
+ get_byte(s) == 'M' &&
+ get_byte(s) == '1');
+ }
+
+
+//-----------------------------------------------------------------------------
+// Unparse all key maps within a keymapping file.
+//-----------------------------------------------------------------------------
+static int unparse_keymaps( DataStream* s )
+ {
+ int rc = 0;
+ if (check_magic_number(s))
+ {
+ int n = 1;
+ while (!end_of_stream(s))
+ {
+ printf( "---------\nKEYMAP #%d\n---------\n", n++ );
+ unparse_keymap(s);
+ }
+ }
+ else
+ {
+ fputs( "Bad magic number.\n", stderr );
+ rc = 1;
+ }
+ return rc;
+ }
+
+
+//-----------------------------------------------------------------------------
+// Unparse a keymapping file.
+//-----------------------------------------------------------------------------
+static int unparse_keymap_file( char const* const path )
+ {
+ int rc = 1;
+ FILE* file;
+ printf( "===========\nKEYMAP FILE\n===========\n%s\n\n", path );
+ file = fopen( path, "rb" );
+ if (file == 0)
+ perror( "Unable to open key mapping file" );
+ else
+ {
+ struct stat st;
+ if (fstat( fileno(file), &st ) != 0)
+ perror( "Unable to determine key mapping file size" );
+ else
+ {
+ byte* buffer = (byte*)malloc( st.st_size );
+ if (fread( buffer, st.st_size, 1, file ) != 1)
+ perror( "Unable to read key mapping file" );
+ else
+ {
+ DataStream* stream = new_data_stream(buffer, (int)st.st_size);
+ fclose( file ); file = 0;
+ rc = unparse_keymaps( stream );
+ destroy_data_stream( stream );
+ }
+ free( buffer );
+ }
+ if (file != 0)
+ fclose( file );
+ }
+ return rc;
+ }
+
+
+//-----------------------------------------------------------------------------
+// Handle the case when no documents are mentioned on the command-line. For
+// Apple/NeXT platforms, dump the currently active key mapping; else display
+// an error message.
+//-----------------------------------------------------------------------------
+static int handle_empty_document_list( void )
+ {
+#if !defined(DUMPKEYMAP_FILE_ONLY)
+ return unparse_active_keymap();
+#else
+ fputs( "ERROR: Must specify at least one .keymapping file.\n\n", stderr );
+ return 1;
+#endif
+ }
+
+
+//-----------------------------------------------------------------------------
+// Print a detailed description of the internal layout of a key mapping.
+//-----------------------------------------------------------------------------
+static void print_internal_layout_info( FILE* f )
+ {
+ fputs(
+"What follows is a detailed descriptions of the internal layout of an\n"
+"Apple/NeXT .keymapping file.\n"
+"\n"
+"Types and Data\n"
+"--------------\n"
+"The following type definitions are employed throughout this discussion:\n"
+"\n"
+" typedef unsigned char byte;\n"
+" typedef unsigned short word;\n"
+" typedef unsigned long dword;\n"
+"\n"
+"Additionally, the type definition `number' is used generically to indicate\n"
+"a numeric value. The actual size of the `number' type may be one or two\n"
+"bytes depending upon how the data is stored in the key map. Although most\n"
+"key maps use byte-sized numeric values, word-sized values are also allowed.\n"
+"\n"
+"Multi-byte values in a key mapping file are stored in big-endian byte\n"
+"order.\n"
+"\n"
+"Key Mapping File and Device Mapping\n"
+"-----------------------------------\n"
+"A key mapping file begins with a magic-number and continues with a variable\n"
+"number of device-specific key mappings.\n"
+"\n"
+" struct KeyMappingFile {\n"
+" char magic_number[4]; // `KYM1'\n"
+" DeviceMapping maps[...]; // Variable number of maps\n"
+" };\n"
+"\n"
+" struct DeviceMapping {\n"
+" dword interface; // Interface type\n"
+" dword handler_id; // Interface subtype\n"
+" dword map_size; // Byte count of `map' (below)\n"
+" KeyMapping map;\n"
+" };\n"
+"\n"
+"The value of `interface' represents a family of keyboard device types\n"
+"(such as Intel PC, ADB, NeXT, Sun Type5, etc.), and is generally\n"
+"specified as one of the constant values NX_EVS_DEVICE_INTERFACE_ADB,\n"
+"NX_EVS_DEVICE_INTERFACE_ACE, etc., which are are defined in IOHIDTypes.h on\n"
+"MacOS/X and Darwin, and in ev_types.h on MacOS/X Server, OpenStep, and\n"
+"NextStep.\n"
+"\n"
+"The value of `handler_id' represents a specific keyboard layout within the\n"
+"much broader `interface' family. For instance, for a 101-key Intel PC\n"
+"keyboard (of type NX_EVS_DEVICE_INTERFACE_ACE) the `handler_id' is '0',\n"
+"whereas for a 102-key keyboard it is `1'.\n"
+"\n"
+"Together, `interface' and `handler_id' identify the exact keyboard hardware\n"
+"to which this mapping applies. Programs which display a visual\n"
+"representation of a keyboard layout, match `interface' and `handler_id'\n"
+"from the .keymapping file against the `interface' and `handler_id' values\n"
+"found in each .keyboard file.\n"
+"\n"
+"Key Mapping\n"
+"-----------\n"
+"A key mapping completely defines the relationship of all scan codes with\n"
+"their associated functionality. A KeyMapping structure is embedded within\n"
+"the DeviceMapping structure in a KeyMappingFile. The key mapping currently\n"
+"in use by the WindowServer and AppKit is also represented by a KeyMapping\n"
+"structure, and can be referred to directly by calling NXGetKeyMapping() and\n"
+"accessing the `mapping' data member of the returned NXKeyMapping structure.\n"
+"\n"
+" struct KeyMapping {\n"
+" word number_size; // 0=1 byte, non-zero=2 bytes\n"
+" number num_modifier_groups; // Modifier groups\n"
+" ModifierGroup modifier_groups[...];\n"
+" number num_scan_codes; // Scan groups\n"
+" ScanGroup scan_table[...];\n"
+" number num_sequence_lists; // Sequence lists\n"
+" Sequence sequence_lists[...];\n"
+" number num_special_keys; // Special keys\n"
+" SpecialKey special_key[...];\n"
+" };\n"
+"\n"
+"The `number_size' flag determines the size, in bytes, of all remaining\n"
+"numeric values (denoted by the type definition `number') within the key\n"
+"mapping. If its value is zero, then numbers are represented by a single\n"
+"byte. If it is non-zero, then numbers are represented by a word (two\n"
+"bytes).\n"
+"\n"
+"Modifier Group\n"
+"--------------\n"
+"A modifier group defines all scan codes which map to a particular type of\n"
+"modifier, such as `shift', `control', etc.\n"
+"\n"
+" enum Modifier {\n"
+" ALPHALOCK = 0,\n"
+" SHIFT,\n"
+" CONTROL,\n"
+" ALTERNATE,\n"
+" COMMAND,\n"
+" KEYPAD,\n"
+" HELP\n"
+" };\n"
+"\n"
+" struct ModifierGroup {\n"
+" number modifier; // A Modifier constant\n"
+" number num_scan_codes;\n"
+" number scan_codes[...]; // Variable number of scan codes\n"
+" };\n"
+"\n"
+"The scan_codes[] array contains a list of all scan codes which map to the\n"
+"specified modifier. The `shift', `command', and `alternate' modifiers are\n"
+"frequently mapped to two different scan codes, apiece, since these\n"
+"modifiers often appear on both the left and right sides of the keyboard.\n"
+"\n"
+"Scan Group\n"
+"----------\n"
+"There is one ScanGroup for each scan code generated by the given keyboard.\n"
+"This number is given by KeyMapping::num_scan_codes. The first scan group\n"
+"represents hardware scan code 0, the second represents scan code 1, etc.\n"
+"\n"
+" enum ModifierMask {\n"
+" ALPHALOCK_MASK = 1 << 0,\n"
+" SHIFT_MASK = 1 << 1,\n"
+" CONTROL_MASK = 1 << 2,\n"
+" ALTERNATE_MASK = 1 << 3,\n"
+" CARRIAGE_RETURN_MASK = 1 << 4\n"
+" };\n"
+" #define NOT_BOUND 0xff\n"
+"\n"
+" struct ScanGroup {\n"
+" number mask;\n"
+" Character characters[...];\n"
+" };\n"
+"\n"
+"For each scan code, `mask' defines which modifier combinations generate\n"
+"characters. If `mask' is NOT_BOUND (0xff) then then this scan code does\n"
+"not generate any characters ever, and its characters[] array is zero\n"
+"length. Otherwise, the characters[] array contains one Character record\n"
+"for each modifier combination.\n"
+"\n"
+"The number of records in characters[] is determined by computing (1 <<\n"
+"bits_set_in_mask). In other words, if mask is zero, then zero bits are\n"
+"set, so characters[] contains only one record. If `mask' is (SHIFT_MASK |\n"
+"CONTROL_MASK), then two bits are set, so characters[] contains four\n"
+"records.\n"
+"\n"
+"The first record always represents the character which is generated by that\n"
+"key when no modifiers are active. The remaining records represent\n"
+"characters generated by the various modifier combinations. Using the\n"
+"example with the `shift' and `control' masks set, record two would\n"
+"represent the character with the `shift' modifier active; record three, the\n"
+"`control' modifier active; and record four, both the `shift' and `control'\n"
+"modifiers active.\n"
+"\n"
+"As a special case, ALPHALOCK_MASK implies SHIFT_MASK, though only\n"
+"ALPHALOCK_MASK appears in `mask'. In this case the same character is\n"
+"generated for both the `shift' and `alpha-lock' modifiers, but only needs\n"
+"to appear once in the characters[] array.\n"
+"\n"
+"CARRIAGE_RETURN_MASK does not actually refer to a modifier key. Instead,\n"
+"it is used to distinguish the scan code which is given the special\n"
+"pseudo-designation of `carriage return' key. Typically, this mask appears\n"
+"solo in a ScanGroup record and only the two Character records for control-M\n"
+"and control-C follow. This flag may be a throwback to an earlier time or\n"
+"may be specially interpreted by the low-level keyboard driver, but its\n"
+"purpose is otherwise enigmatic.\n"
+"Character\n"
+"---------\n"
+"Each Character record indicates the character generated when this key is\n"
+"pressed, as well as the character set which contains the character. Well\n"
+"known character sets are `ASCII' and `Symbol'. The character set can also\n"
+"be one of the meta values FUNCTION_KEY or KEY_SEQUENCE. If it is\n"
+"FUNCTION_KEY then `char_code' represents a generally well-known function\n"
+"key such as those enumerated by FunctionKey. If the character set is\n"
+"KEY_SEQUENCE then `char_code' represents a zero-base index into\n"
+"KeyMapping::sequence_lists[].\n"
+"\n"
+" enum CharacterSet {\n"
+" ASCII = 0x00,\n"
+" SYMBOL = 0x01,\n"
+" ...\n"
+" FUNCTION_KEY = 0xfe,\n"
+" KEY_SEQUENCE = 0xff\n"
+" };\n"
+"\n"
+" struct Character {\n"
+" number set; // CharacterSet of generated character\n"
+" number char_code; // Actual character generated\n"
+" };\n"
+"\n"
+" enum FunctionKey {\n"
+" F1 = 0x20, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12,\n"
+" INSERT, DELETE, HOME, END, PAGE_UP, PAGE_DOWN, PRINT_SCREEN,\n"
+" SCROLL_LOCK, PAUSE, SYS_REQUEST, BREAK, RESET, STOP, MENU, USER,\n"
+" SYSTEM, PRINT, CLEAR_LINE, CLEAR_DISPLAY, INSERT_LINE,\n"
+" DELETE_LINE, INSERT_CHAR, DELETE_CHAR, PREV, NEXT, SELECT\n"
+" };\n"
+"\n"
+"Sequence\n"
+"--------\n"
+"When Character::set contains the meta value KEY_SEQUENCE, the scan code is\n"
+"bound to a sequence of keys rather than a single character. A sequence is\n"
+"a series of modifiers and characters which are automatically generated when\n"
+"the associated key is depressed.\n"
+"\n"
+" #define MODIFIER_KEY 0xff\n"
+"\n"
+" struct Sequence {\n"
+" number num_chars;\n"
+" Character characters[...];\n"
+" };\n"
+"\n"
+"Each generated Character is represented as previously described, with the\n"
+"exception that MODIFIER_KEY may appear in place of KEY_SEQUENCE. When the\n"
+"value of Character::set is MODIFIER_KEY then Character::char_code\n"
+"represents a modifier key rather than an actual character. If the modifier\n"
+"represented by `char_code' is non-zero, then it indicates that the\n"
+"associated modifier key has been depressed. In this case, the value is one\n"
+"of the constants enumerated by Modifier (SHIFT, CONTROL, ALTERNATE, etc.).\n"
+"If the value is zero then it means that the modifier keys have been\n"
+"released.\n"
+"\n"
+"Special Key\n"
+"-----------\n"
+"A special key is one which is scanned directly by the Mach kernel rather\n"
+"than by the WindowServer. In general, events are not generated for special\n"
+"keys.\n"
+"\n"
+" enum SpecialKeyType {\n"
+" VOLUME_UP = 0,\n"
+" VOLUME_DOWN,\n"
+" BRIGHTNESS_UP,\n"
+" BRIGHTNESS_DOWN,\n"
+" ALPHA_LOCK,\n"
+" HELP,\n"
+" POWER,\n"
+" SECONDARY_ARROW_UP,\n"
+" SECONDARY_ARROW_DOWN\n"
+" };\n"
+"\n"
+" struct SpecialKey {\n"
+" number type; // A SpecialKeyType constant\n"
+" number scan_code; // Actual scan code\n"
+" };\n"
+"\n", f );
+ }
+
+
+//-----------------------------------------------------------------------------
+// Print an explanation of the output generated by this program.
+//-----------------------------------------------------------------------------
+static void print_output_info( FILE* f )
+ {
+ fputs(
+"What follows is an explanation and description of the various pieces of\n"
+"information emitted by dumpkeymap.\n"
+"\n"
+"For a more thorough discussion of any particular piece of information\n"
+"described here, refer to the detailed description of the internal layout of\n"
+"a key mapping given by the --help-layout option.\n"
+"\n"
+"Conventions\n"
+"-----------\n"
+"Depending upon context, some numeric values are displayed in decimal\n"
+"notation, whereas others are displayed in hexadecimal notation.\n"
+"Hexadecimal numbers are denoted by a `0x' prefix (for instance, `0x7b'),\n"
+"except when explicitly noted otherwise.\n"
+"\n"
+"Key Mapping Source\n"
+"------------------\n"
+"The first piece of information presented about a particular key mapping is\n"
+"the source from which the data was gleaned. For a .keymapping file, the\n"
+"title `KEYMAP FILE' is emitted along with the path and name of the file in\n"
+"question. For the key mapping currently in use by the WindowServer and\n"
+"AppKit, the title `ACTIVE KEYMAP' is emitted instead.\n"
+"\n"
+"Device Information\n"
+"------------------\n"
+"Each .keymapping file may contain one or more raw key mappings. For\n"
+"example, a file which maps keys to a Dvorak-style layout might contain raw\n"
+"mappings for Intel PC, ADB, NeXT, and Sun Type5 keyboards.\n"
+"\n"
+"For each raw mapping, the following information is emitted:\n"
+"\n"
+" o The title `KEYMAP' along with the mapping's relative position in the\n"
+" .keymapping file.\n"
+" o The `interface' identifier.\n"
+" o The `handler_id' sub-identifier.\n"
+" o The size of the raw mapping resource counted in bytes.\n"
+"\n"
+"The `interface' and `handler_id' values, taken together, define a specific\n"
+"keyboard device. A .keyboard file, which describes the visual layout of a\n"
+"keyboard, also contains `interface' and `handler_id' identifiers. The\n"
+".keyboard file corresponding to a particular key mapping can be found by\n"
+"matching the `interface' and `handler_id' values from each resource.\n"
+"\n"
+"Modifiers\n"
+"---------\n"
+"Each mapping may contain zero or more modifier records which associate\n"
+"hardware scan codes with modifier descriptions such as `shift', `control',\n"
+"`alternate', etc. The title `MODIFIERS' is printed along with the count of\n"
+"modifier records which follow. For each modifier record, the modifier's\n"
+"name is printed along with a list of scan codes, in hexadecimal format,\n"
+"which generate that modifier value. For example:\n"
+"\n"
+" MODIFIERS [4]\n"
+" alternate: 0x1d 0x60\n"
+" control: 0x3a\n"
+" keypad: 0x52 0x53 ... 0x63 0x62\n"
+" shift: 0x2a 0x36\n"
+"\n"
+"Characters\n"
+"----------\n"
+"Each mapping may contain zero or more character records which associate\n"
+"hardware scan codes with the actual characters generated by those scan\n"
+"codes in the presence or absence of various modifier combinations. The\n"
+"title `CHARACTERS' is printed along with the count of character records\n"
+"which follow. Here is a highly abbreviated example:\n"
+"\n"
+" CHARACTERS [9]\n"
+" scan 0x00: -AC-L \"a\" \"A\" \"^A\" \"^A\" ca c7 \"^A\" \"^A\"\n"
+" scan 0x07: -AC-L \"x\" \"X\" \"^X\" \"^X\" 01/b4 01/ce \"^X\" \"^X\"\n"
+" scan 0x0a: ---S- \"<\" \">\"\n"
+" scan 0x13: -ACS- \"2\" \"@\" \"^@\" \"^@\" b2 b3 \"^@\" \"^@\"\n"
+" scan 0x24: R---- \"^M\" \"^C\"\n"
+" scan 0x3e: ----- [F4]\n"
+" scan 0x4a: ----- [page up]\n"
+" scan 0x60: ----- {seq#3}\n"
+" scan 0x68: not-bound\n"
+"\n"
+"For each record, the hexadecimal value of the hardware scan code is\n"
+"printed, followed by a list of modifier flag combinations and the actual\n"
+"characters generated by this scan code with and without modifiers applied.\n"
+"\n"
+"The modifier flags field is composed of a combination of single letter\n"
+"representations of the various modifier types. The letters stand for:\n"
+"\n"
+" L - alpha-lock\n"
+" S - shift\n"
+" C - control\n"
+" A - alternate\n"
+" R - carriage-return\n"
+"\n"
+"As a special case, the `alpha-lock' flag also implies the `shift' flag, so\n"
+"these two flags never appear together in the same record.\n"
+"\n"
+"The combination of modifier flags determines the meaning and number of\n"
+"fields which follow. The first field after the modifier flags always\n"
+"represents the character that will be generated if no modifier keys are\n"
+"depressed. The remaining fields represent characters generated by the\n"
+"various modifier combinations. The order of the fields follows this\n"
+"general pattern:\n"
+"\n"
+" o The character generated by this scan code when no modifiers are in\n"
+" effect is listed first.\n"
+"\n"
+" o If the `L' or `S' flag is active, then the shifted character\n"
+" generated by this scan code is listed next.\n"
+"\n"
+" o If the `C' flag is active, then the control-character generated by\n"
+" this scan code is listed next. Furthermore, if the `L' or `S' flag\n"
+" is also active, then the shifted control-character is listed after\n"
+" that.\n"
+"\n"
+" o If the `A' flag is active, then the alternate-character generated by\n"
+" this scan code is listed next. Furthermore, if the `L' or `S' flag\n"
+" is active, then the shifted alternate-character is listed after that.\n"
+" If the `C' flag is also active, then the alternate-control-character\n"
+" is listed next. Finally, if the `C' and `L' or `C' and `S' flags are\n"
+" also active, then the shifted alternate-control-character is listed.\n"
+"\n"
+"The `R' flag does not actually refer to a modifier key. Instead, it is\n"
+"used to distinguish the scan code which is given the special\n"
+"pseudo-designation of `carriage return' key. Typically, this mask appears\n"
+"solo and only the two fields for control-M and control-C follow. This flag\n"
+"may be a throwback to an earlier time or may be specially interpreted by\n"
+"the low-level keyboard driver, but its purpose is otherwise enigmatic.\n"
+"\n"
+"Recalling the example from above, the following fields can be identified:\n"
+"\n"
+" scan 0x00: -AC-L \"a\" \"A\" \"^A\" \"^A\" ca c7 \"^A\" \"^A\"\n"
+"\n"
+" o Lower-case `a' is generated when no modifiers are active.\n"
+" o Upper-case `A' is generated when `shift' or `alpha-lock' are active.\n"
+" o Control-A is generated when `control' is active.\n"
+" o Control-A is generated when `control' and `shift' are active.\n"
+" o The character represented by the hexadecimal code 0xca is generated\n"
+" when `alternate' is active.\n"
+" o The character represented by 0xc7 is generated when `alternate' and\n"
+" `shift' (or `alpha-lock') are active.\n"
+" o Control-A is generated when `alternate' and `control' are active.\n"
+" o Control-A is generated when `alternate', `control' and `shift' (or\n"
+" `alpha-lock') are active.\n"
+"\n"
+"The notation used to represent a particular generated character varies.\n"
+"\n"
+" o Printable ASCII characters are quoted, as in \"x\" or \"X\".\n"
+"\n"
+" o Control-characters are quoted and prefixed with `^', as in \"^X\".\n"
+"\n"
+" o Characters with values greater than 127 (0x7f) are displayed as\n"
+" hexadecimal values without the `0x' prefix.\n"
+"\n"
+" o Characters in a non-ASCII character set (such as `Symbol') are\n"
+" displayed as two hexadecimal numbers separated by a slash, as in\n"
+" `01/4a'. The first number is the character set's identification code\n"
+" (such as `01' for the `Symbol' set), and the second number is the\n"
+" value of the generated character.\n"
+"\n"
+" o Non-printing special function characters are displayed with the\n"
+" function's common name enclosed in brackets, as in `[page up]' or\n"
+" `[F4]'.\n"
+"\n"
+" o If the binding represents a key sequence rather than a single\n"
+" character, then the sequence's identification number is enclosed in\n"
+" braces, as in `{seq#3}'.\n"
+"\n"
+"Recalling a few examples from above, the following interpretations can be\n"
+"made:\n"
+"\n"
+" scan 0x07: -AC-L \"x\" \"X\" \"^X\" \"^X\" 01/b4 01/ce \"^X\" \"^X\"\n"
+" scan 0x3e: ----- [F4]\n"
+" scan 0x4a: ----- [page up]\n"
+" scan 0x60: ----- {seq#3}\n"
+"\n"
+" o \"x\" and \"X\" are printable ASCII characters.\n"
+" o \"^X\" is a control-character.\n"
+" o `01/b4' and `01/ce' represent the character codes 0xb4 and 0xce in\n"
+" the `Symbol' character set.\n"
+" o Scan code 0x3e generates function-key `F4', and scan code 0x4a\n"
+" generates function-key `page up'.\n"
+" o Scan code 0x60 is bound to key sequence #3.\n"
+"\n"
+"Finally, if a scan code is not bound to any characters, then it is\n"
+"annotated with the label `not-bound', as with example scan code 0x68 from\n"
+"above.\n"
+"\n"
+"Sequences\n"
+"---------\n"
+"A scan code (modified and unmodified) can be bound to a key sequence rather\n"
+"than generating a single character or acting as a modifier. When it is\n"
+"bound to a key sequence, a series of character invocations and modifier\n"
+"actions are automatically generated rather than a single keystroke.\n"
+"\n"
+"Each mapping may contain zero or more key sequence records. The title\n"
+"`SEQUENCES' is printed along with the count of sequence records which\n"
+"follow. For example:\n"
+"\n"
+" SEQUENCES [3]\n"
+" sequence 0: \"f\" \"o\" \"o\"\n"
+" sequence 1: {alternate} \"b\" \"a\" \"r\" {unmodify}\n"
+" sequence 2: [home] \"b\" \"a\" \"z\"\n"
+"\n"
+"The notation used to represent the sequence of generated characters is\n"
+"identical to the notation already described in the `Characters' section\n"
+"above, with the exception that modifier actions may be interposed between\n"
+"generated characters. Such modifier actions are represented by the\n"
+"modifier's name enclosed in braces. The special name `{unmodify}'\n"
+"indicates the release of the modifier keys.\n"
+"\n"
+"Thus, the sequences in the above example can be interpreted as follows:\n"
+"\n"
+" o Sequence #0 generates `foo'.\n"
+" o Sequence #1 invokes the `alternate' modifier, generates `bar', and\n"
+" then releases `alternate'.\n"
+" o Sequence #2 invokes the `home' key and then generates `baz'. In a\n"
+" text editor, this would probably result in `baz' being prepended to\n"
+" the line of text on which the cursor resides.\n"
+"\n"
+"Special Keys\n"
+"------------\n"
+"Certain keyboards feature keys which perform some type of special purpose\n"
+"function rather than generating a character or acting as a modifier. For\n"
+"instance, Apple keyboards often contain a `power' key, and NeXT keyboards\n"
+"have historically featured screen brightness and volume control keys.\n"
+"\n"
+"Each mapping may contain zero or more special-key records which associate\n"
+"hardware scan codes with such special purpose functions. The title\n"
+"`SPECIALS' is printed along with the count of records which follow. For\n"
+"each record, the special function's name is printed along with a list of\n"
+"scan codes, in hexadecimal format, which are bound to that function. For\n"
+"example:\n"
+"\n"
+" SPECIALS [6]\n"
+" alpha-lock: 0x39\n"
+" brightness-down: 0x79\n"
+" brightness-up: 0x74\n"
+" power: 0x7f\n"
+" sound-down: 0x77\n"
+" sound-up: 0x73\n"
+"\n", f );
+ }
+
+
+//-----------------------------------------------------------------------------
+// Print a summary of the various files and directories which are related to
+// key mappings.
+//-----------------------------------------------------------------------------
+static void print_files_info( FILE* f )
+ {
+ fputs(
+"This is a summary of the various files and directories which are related to\n"
+"key mappings.\n"
+"\n"
+"*.keymapping\n"
+" A key mapping file which precisely defines the relationship of all\n"
+" hardware-specific keyboard scan-codes with their associated\n"
+" functionality.\n"
+"\n"
+"*.keyboard\n"
+" A file describing the physical layout of keys on a particular type of\n"
+" keyboard. Each `key' token in this file defines the position and shape\n"
+" of the key on the keyboard, as well as the associated scan code which\n"
+" that key generates. A .keymapping file, on the other hand, defines the\n"
+" characters which are generated by a particular scan code depending upon\n"
+" the state of the various modifier keys (such as shift, control, etc.).\n"
+" The `interface' and `handler_id' values from a .keymapping file are\n"
+" matched against those in each .keyboard file in order to associate a\n"
+" particular .keyboard file with a key mapping. Various GUI programs use\n"
+" the .keyboard file to display a visual representation of a keyboard for\n"
+" the user. Since these files are just plain text, they can be easily\n"
+" viewed and interpreted without the aid of a specialized program, thus\n"
+" dumpkeymap leaves these files alone.\n"
+"\n"
+"/System/Library/Keyboards\n"
+"/Network/Library/Keyboards\n"
+"/Local/Library/Keyboards\n"
+"/Library/Keyboards\n"
+" Repositories for .keymapping and .keyboard files for MacOS/X, Darwin,\n"
+" and MacOS/X Server.\n"
+"\n"
+"/NextLibrary/Keyboards\n"
+"/LocalLibrary/Keyboards\n"
+" Repositories for .keymapping and .keyboard files for OpenStep and\n"
+" NextStep.\n"
+"\n"
+"$(HOME)/Library/Keyboards\n"
+" Repository for personal .keymapping and .keyboard files.\n"
+"\n", f );
+ }
+
+
+//-----------------------------------------------------------------------------
+// Print a list of the various diagnostic messages which may be emitted.
+//-----------------------------------------------------------------------------
+static void print_diagnostics_info( FILE* f )
+ {
+ fputs(
+"The following diagnostic messages may be issued to the standard error\n"
+"stream.\n"
+"\n"
+"Unrecognized option.\n"
+" An unrecognized option was specified on the command-line. Invoke\n"
+" dumpkeymap with the --help option to view a list of valid options.\n"
+"\n"
+"Insufficient data in keymapping data stream.\n"
+" The key mapping file or data stream is corrupt. Either the file has\n"
+" been incorrectly truncated or a field, such as those which indicates\n"
+" the number of variable records which follow, contains a corrupt value.\n"
+"\n"
+"The following diagnostic messages have significance only when trying to\n"
+"print .keymapping files mentioned on the command-line.\n"
+"\n"
+"Bad magic number.\n"
+" The mentioned file is not a .keymapping file. The file's content does\n"
+" not start with the string `KYM1'.\n"
+"\n"
+"Unable to open key mapping file.\n"
+" The call to fopen() failed; probably because the specified path is\n"
+" invalid or dumpkeymap does not have permission to read the file.\n"
+"\n"
+"Unable to determine key mapping file size.\n"
+" The call to fstat() failed, thus memory can not be allocated for\n"
+" loading the file.\n"
+"\n"
+"Unable to read key mapping file.\n"
+" The call to fread() failed.\n"
+"\n"
+"The following diagnostic messages have significance only when trying to\n"
+"print the currently active key mapping when no .keymapping files have been\n"
+"mentioned on the command-line.\n"
+"\n"
+"Unable to open event status driver.\n"
+" The call to NXOpenEventStatus() failed.\n"
+"\n"
+"Bad key mapping length.\n"
+" The call to NXKeyMappingLength() returned a bogus value.\n"
+"\n"
+"Unable to get current key mapping.\n"
+" The call to NXGetKeyMapping() failed.\n"
+"\n"
+"The following diagnostic messages have significance only when using\n"
+"dumpkeymap on a non-Apple/NeXT platform.\n"
+"\n"
+"Must specify at least one .keymapping file.\n"
+" No .keymapping files were mentioned on the command-line. On\n"
+" non-Apple/NeXT platforms, there is no concept of a currently active\n"
+" .keymapping file, so at least one file must be mentioned on the\n"
+" command-line.\n"
+"\n", f );
+ }
+
+
+//-----------------------------------------------------------------------------
+// Print warranty.
+//-----------------------------------------------------------------------------
+static void print_warranty( FILE* f )
+ {
+ fputs(
+"This software is provided by the author `AS IS' and any express or implied\n"
+"WARRANTIES, including, but not limited to, the implied warranties of\n"
+"MERCHANTABILITY and FITNESS FOR A PARTICULAR PURPOSE are DISCLAIMED. In NO\n"
+"EVENT shall the author be LIABLE for any DIRECT, INDIRECT, INCIDENTAL,\n"
+"SPECIAL, EXEMPLARY, or CONSEQUENTIAL damages (including, but not limited\n"
+"to, procurement of substitute goods or services; loss of use, data, or\n"
+"profits; or business interruption) however caused and on any theory of\n"
+"liability, whether in contract, strict liability, or tort (including\n"
+"negligence or otherwise) arising in any way out of the use of this\n"
+"software, even if advised of the possibility of such damage.\n"
+"\n", f );
+ }
+
+
+//-----------------------------------------------------------------------------
+// Print this program's version number.
+//-----------------------------------------------------------------------------
+static void print_version( FILE* f )
+ {
+ fputs( "Version " PROG_VERSION " (built " __DATE__ ")\n\n", f );
+ }
+
+
+//-----------------------------------------------------------------------------
+// Print a usage summary.
+//-----------------------------------------------------------------------------
+static void print_usage( FILE* f )
+ {
+ fputs(
+"Usage: dumpkeymap [options] [-] [file ...]\n"
+"\n"
+"Prints a textual representation of each Apple/NeXT .keymapping file\n"
+"mentioned on the command-line. If no files are mentioned and if the local\n"
+"machine is an Apple or NeXT installation, then the key mapping currently in\n"
+"use by the WindowServer and the AppKit is printed instead.\n"
+"\n"
+"Options:\n"
+" -h --help\n"
+" Display general program instructions and option summary.\n"
+"\n"
+" -k --help-keymapping\n"
+" Display a detailed description of the internal layout of a\n"
+" .keymapping file.\n"
+"\n"
+" -o --help-output\n"
+" Display an explanation of the output generated by dumpkeymap when\n"
+" dissecting a .keymapping file.\n"
+"\n"
+" -f --help-files\n"
+" Display a summary of the various files and directories which are\n"
+" related to key mappings.\n"
+"\n"
+" -d --help-diagnostics\n"
+" Display a list of the various diagnostic messages which may be\n"
+" emitted by dumpkeymap.\n"
+"\n"
+" -v --version\n"
+" Display the dumpkeymap version number and warranty information.\n"
+"\n"
+" - --\n"
+" Inhibit processing of options at this point in the argument list.\n"
+" An occurrence of `-' or `--' in the argument list causes all\n"
+" following arguments to be treated as file names even if an argument\n"
+" begins with a `-' character.\n"
+"\n", f );
+ }
+
+
+//-----------------------------------------------------------------------------
+// Print an informational banner.
+//-----------------------------------------------------------------------------
+static void print_banner( FILE* f )
+ {
+ fputs( "\n" PROG_NAME " v" PROG_VERSION " by " AUTHOR_INFO "\n"
+ COPYRIGHT "\n\n", f );
+ }
+
+
+//-----------------------------------------------------------------------------
+// Process command-line arguments. Examine options first; collecting files
+// along the way. If all is well, process collected file list.
+//-----------------------------------------------------------------------------
+int main( int const argc, char const* const argv[] )
+ {
+ int rc = 0, i, nfiles = 0, more_options = 1, process_files = 1;
+ int* files = (int*)calloc( argc - 1, sizeof(int) );
+ print_banner( stdout );
+
+ for (i = 1; i < argc; i++)
+ {
+ char const* const s = argv[i];
+ if (!more_options || *s != '-')
+ files[ nfiles++ ] = i;
+ else
+ {
+ OPT_SWITCH(s)
+ OPT_CASE(-,--)
+ more_options = 0;
+ OPT_CASE(-h,--help)
+ print_usage( stdout );
+ process_files = 0;
+ OPT_CASE(-k,--help-keymapping)
+ print_internal_layout_info( stdout );
+ process_files = 0;
+ OPT_CASE(-o,--help-output)
+ print_output_info( stdout );
+ process_files = 0;
+ OPT_CASE(-f,--help-files)
+ print_files_info( stdout );
+ process_files = 0;
+ OPT_CASE(-d,--help-diagnostics)
+ print_diagnostics_info( stdout );
+ process_files = 0;
+ OPT_CASE(-v,--version)
+ print_version( stdout );
+ print_warranty( stdout );
+ process_files = 0;
+ OPT_DEFAULT
+ fprintf( stderr, "ERROR: Unrecognized option: %s\n\n", s );
+ process_files = 0;
+ rc = 1;
+ OPT_SWITCH_END
+ }
+ }
+
+ if (process_files)
+ {
+ if (nfiles == 0)
+ rc = handle_empty_document_list();
+ else
+ for (i = 0; i < nfiles; i++)
+ rc |= unparse_keymap_file( argv[files[i]] );
+ }
+
+ free( files );
+ return rc;
+ }
--- /dev/null
+.ig
+//=============================================================================
+//
+// Manual page for `dumpkeymap'.
+//
+// Copyright (C) 1999,2000 by Eric Sunshine <sunshine@sunshineco.com>
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+// 3. The name of the author may not be used to endorse or promote products
+// derived from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+//=============================================================================
+//
+// $XFree86: xc/programs/Xserver/hw/darwin/utils/dumpkeymap.man,v 1.2 2000/12/05 21:18:34 dawes Exp $
+//
+..
+.ig
+//-----------------------------------------------------------------------------
+// Local identification information.
+//-----------------------------------------------------------------------------
+..
+.nr VE 4 \" Version number
+.TH DUMPKEYMAP 1 "v\n(VE \-\- 1 December 2000" "Version \n(VE"
+.de UP
+1 December 2000
+..
+.ig
+//-----------------------------------------------------------------------------
+// Annotation Macros
+// -----------------
+// Facilitate creation of annotated, non-filled blocks of text. An
+// annotated block is initiated with the `AS' macro. Each annotated,
+// non-filled line within the block must be introduced with the `AN' macro
+// which takes three arguments. The first argument is the detail text to
+// be annotated. The second is a string of spaces used to align the
+// annotations by certain (broken) roff interpreters which fail to
+// implement the proper set of roff commands (such as diversions,
+// indentation, and tab stops). It is assumed that the spaces will be
+// used with fixed-point font. The third argument is the annotation
+// itself. The block should be terminated with the `AE' macro. For all
+// roff interpreters which properly implement diversions, indentation, and
+// tab stops, all anotations within the block are automatically aligned at
+// the same horizontal position. This position is guaranteed to be just
+// to the right of the widest `AN' detail line. For broken roff
+// interpreters, such as `rman', the string of spaces from the second
+// argument are used to align the annotations. Finally, the `AZ' macro,
+// which takes a single argument, can be used to to insert a non-annotated
+// line into the block which does not play a part in the calculation of
+// the horizontal annotation alignment.
+//
+// Implementation Notes
+// --------------------
+// *1* These macros utilize a diversion (named `AD'). Since the prevailing
+// indentation is stored along with the diverted text, we must muck with
+// the indentation level in order to prevent the indentation from being
+// applied to the text a second time when `AD' is finally emitted.
+//
+// *2* Unfortunately, `.if' strips leading whitespace from following text, so
+// `AN' uses \& to preserve the whitespace.
+//
+// *3* This manual page has been tested for proper formatting with troff,
+// groff, nroff and rman (the `man' to `HTML' converter). Unfortunately,
+// rman fails to implement many useful features such as diversions,
+// indentation, and tab stops, and is also hideously buggy. Furthermore
+// it identifies itself as nroff and fails to provide any further
+// identification, so there is no way to create macros which specifically
+// work around its limitations. Following is a list of several bugs in
+// rman which the implementation of these macros must avoid:
+// o Fails with multi-line conditionals within macros.
+// o Fails on macro definition within multi-line conditionals.
+// o Fails when macro arguments are not delimited by exactly 1 space.
+// o String definition `.ds' ignores the value; uses empty "" instead.
+// As a consequence of these problems, the following macros are written
+// using a series of ugly single-line `.if' conditionals rather than the
+// more natural multi-line `.if' and `.ie' conditionals. Also, rman fails
+// to understand the common idiom of `.\"' to introduce a comment, which
+// is why all comments in this file are wrapped in ignore `.ig' blocks.
+//-----------------------------------------------------------------------------
+..
+.de AS
+.if t .nr AW 0
+.if t .nr AI \\n(.i
+.if t .in -\\n(AI
+.nf
+..
+.de AN
+.if t .if \w'\\$1'>\\n(AW .nr AW \w'\\$1'
+.if t .da AD
+.if t \\&\\$1\\t\\$3
+.if t .da
+.if n \\&\\$1 \\$2\\$3
+..
+.de AZ
+.if t .da AD
+\\$1
+.if t .da
+..
+.de AE
+.if t .in +\\n(AIu
+.if t .if \\n(AW .ta \\n(AWu+\w'\\(em'u
+.if t .AD
+.if t .DT
+.if t .rm AD
+.if t .rm AW
+.fi
+..
+.ig
+//-----------------------------------------------------------------------------
+// Bulleted list macros -- `BG' begins a bulleted list; `BU' delimits
+// bulleted entries; `BE' ends a bulleted list.
+//-----------------------------------------------------------------------------
+..
+.de BG
+.PP
+.RS
+..
+.de BU
+.HP
+\\(bu\\ \\c
+..
+.de BE
+.RE
+.PP
+..
+.ig
+//-----------------------------------------------------------------------------
+// Indented paragraph with stylized hanging tag macro. `TG' takes a single
+// argument and treats it as the hanging tag of the indented paragraph.
+// The tag is italicized in troff but not in nroff.
+//-----------------------------------------------------------------------------
+..
+.de TG
+.TP
+.ie t .I "\\$1"
+.el \\$1
+..
+.ig
+//-----------------------------------------------------------------------------
+// Manual page for `dumpkeymap'.
+//-----------------------------------------------------------------------------
+..
+.SH NAME
+dumpkeymap \- Dianostic dump of a .keymapping file
+.SH SYNOPSIS
+.B dumpkeymap
+.RI [ options "] [-] [" file "...]"
+.SH DESCRIPTION
+.I dumpkeymap
+prints a textual representation of each Apple/\c
+.SM NeXT
+.I .keymapping
+file mentioned on the command-line. If no files are mentioned and if the
+local machine is an Apple or
+.SM NeXT
+installation, then the key mapping currently in use by the WindowServer and the
+AppKit is printed instead.
+.SH OPTIONS
+.TP
+.B "\-h \-\^\-help"
+Display general program instructions and option summary.
+.TP
+.B "\-k \-\^\-help\-keymapping"
+Display a detailed description of the internal layout of a
+.I .keymapping
+file. This is the same information as that presented in the
+.I "Key Mapping Description"
+section of this document.
+.TP
+.B "\-o \-\^\-help\-output"
+Display an explanation of the output generated by
+.I dumpkeymap
+when dissecting a
+.I .keymapping
+file. This is the same information as that presented in the
+.I "Output Description"
+section of this document.
+.TP
+.B "\-f \-\^\-help\-files"
+Display a summary of the various files and directories which are related to
+key mappings. This is the same information as that presented in the
+.I "Files"
+section of this document.
+.TP
+.B "\-d \-\^\-help\-diagnostics"
+Display a list of the various diagnostic messages which may be emitted by
+.I dumpkeymap.
+This is the same information as that presented in the
+.I "Diagnostics"
+section of this document.
+.TP
+.B "\-v \-\^\-version"
+Display the
+.I dumpkeymap
+version number and warranty information.
+.TP
+.B "\- \-\^\-"
+Inhibit processing of options at this point in the argument list. An
+occurrence of `\-' or `\-\^\-' in the argument list causes all following
+arguments to be treated as file names even if an argument begins with a `\-'
+character.
+.SH "KEY MAPPING DESCRIPTION"
+The following sections describe, in complete detail, the format of a raw key
+mapping resource, as well as the format of the
+.I .keymapping
+file which encapsulates one or more raw mappings.
+.SH "Types and Data"
+The following type definitions are employed throughout this discussion:
+.PP
+.RS
+.AS
+.AZ "typedef unsigned char byte;"
+.AZ "typedef unsigned short word;"
+.AZ "typedef unsigned long dword;"
+.AE
+.RE
+.PP
+Additionally, the type definition
+.RI ` number '
+is used generically to
+indicate a numeric value. The actual size of the
+.RI ` number '
+type may be one or two bytes depending upon how the data is stored in the key
+map. Although most key maps use byte-sized numeric values, word-sized values
+are also allowed.
+.PP
+Multi-byte values in a key mapping file are stored in big-endian byte order.
+.SH "Key Mapping File and Device Mapping"
+A key mapping file begins with a magic-number and continues with a
+variable number of device-specific key mappings.
+.PP
+.RS
+.AS
+.AZ "struct KeyMappingFile {"
+.AN " char magic_number[4];" " " "// `KYM1'"
+.AN " DeviceMapping maps[...];" "" "// Variable number of maps"
+.AZ };
+.AE
+.PP
+.AS
+.AZ "struct DeviceMapping {"
+.AN " dword interface;" " " "// Interface type"
+.AN " dword handler_id;" "" "// Interface subtype"
+.AN " dword map_size;" " " "// Byte count of `map' (below)"
+.AN " KeyMapping map;"
+.AZ };
+.AE
+.RE
+.PP
+The value of `interface' represents a family of keyboard device types
+(such as Intel
+.SM "PC, ADB, NeXT,"
+Sun Type5, etc.), and is generally specified as one of the constant values
+.SM "NX_EVS_DEVICE_INTERFACE_ADB, NX_EVS_DEVICE_INTERFACE_ACE,"
+etc., which are are defined in IOHIDTypes.h on MacOS/X and Darwin, and in
+ev_types.h on MacOS/X Server, OpenStep, and NextStep.
+.PP
+The value of `handler_id' represents a specific keyboard layout within the
+much broader `interface' family. For instance, for a 101-key Intel
+.SM PC
+keyboard (of type
+.SM NX_EVS_DEVICE_INTERFACE_ACE\c
+) the `handler_id' is '0', whereas for a 102-key keyboard it is `1'.
+.PP
+Together, `interface' and `handler_id' identify the exact keyboard hardware to
+which this mapping applies. Programs which display a visual representation of
+a keyboard layout, match `interface' and `handler_id' from the
+.I .keymapping
+file against the `interface' and `handler_id' values found in each
+.I .keyboard
+file.
+.SH "Key Mapping"
+A key mapping completely defines the relationship of all scan codes with their
+associated functionality. A
+.I KeyMapping
+structure is embedded within the
+.I DeviceMapping
+structure in a
+.IR KeyMappingFile .
+The key mapping currently in use by the WindowServer and AppKit is also
+represented by a
+.I KeyMapping
+structure, and can be referred to directly by calling NXGetKeyMapping() and
+accessing the `mapping' data member of the returned
+.I NXKeyMapping
+structure.
+.PP
+.RS
+.AS
+.AZ "struct KeyMapping {"
+.AN " word number_size;" " " "// 0=1 byte, non-zero=2 bytes"
+.AN " number num_modifier_groups;" "" "// Modifier groups"
+.AZ " ModifierGroup modifier_groups[...];"
+.AN " number num_scan_codes;" " " "// Scan groups"
+.AN " ScanGroup scan_table[...];"
+.AN " number num_sequence_lists;" " " "// Sequence lists"
+.AN " Sequence sequence_lists[...];"
+.AN " number num_special_keys;" " " "// Special keys"
+.AN " SpecialKey special_key[...];"
+.AZ };
+.AE
+.RE
+.PP
+The `number_size' flag determines the size, in bytes, of all remaining numeric
+values (denoted by the type definition
+.RI ` number ')
+within the
+key mapping. If its value is zero, then numbers are represented by a single
+byte. If it is non-zero, then numbers are represented by a word (two bytes).
+.SH "Modifier Group"
+A modifier group defines all scan codes which map to a particular type of
+modifier, such as
+.IR shift ,
+.IR control ,
+etc.
+.PP
+.RS
+.AS
+.AZ "enum Modifier {"
+.AZ " ALPHALOCK = 0,"
+.AZ " SHIFT,"
+.AZ " CONTROL,"
+.AZ " ALTERNATE,"
+.AZ " COMMAND,"
+.AZ " KEYPAD,"
+.AZ " HELP"
+.AZ };
+.AE
+.PP
+.AS
+.AZ "struct ModifierGroup {"
+.AN " number modifier;" " " "// A Modifier constant"
+.AN " number num_scan_codes;"
+.AN " number scan_codes[...];" "" "// Variable number of scan codes"
+.AZ };
+.AE
+.RE
+.PP
+The scan_codes[] array contains a list of all scan codes which map to the
+specified modifier. The
+.IR shift ", " command ", and " alternate
+modifiers are frequently mapped to two different scan codes, apiece,
+since these modifiers often appear on both the left and right sides of
+the keyboard.
+.SH "Scan Group"
+There is one
+.I ScanGroup
+for each scan code generated by the given keyboard. This number is given by
+KeyMapping::num_scan_codes. The first scan group represents hardware scan
+code 0, the second represents scan code 1, etc.
+.PP
+.RS
+.AS
+.AZ "enum ModifierMask {"
+.AN " ALPHALOCK_MASK" " " "= 1 << 0,"
+.AN " SHIFT_MASK" " " "= 1 << 1,"
+.AN " CONTROL_MASK" " " "= 1 << 2,"
+.AN " ALTERNATE_MASK" " " "= 1 << 3,"
+.AN " CARRIAGE_RETURN_MASK" "" "= 1 << 4"
+.AZ };
+.AZ "#define NOT_BOUND 0xff"
+.AE
+.PP
+.AS
+.AZ "struct ScanGroup {"
+.AN " number mask;"
+.AN " Character characters[...];"
+.AZ };
+.AE
+.RE
+.PP
+For each scan code, `mask' defines which modifier combinations generate
+characters. If `mask' is
+.SM NOT_BOUND
+(0xff) then then this scan code does not generate any characters ever, and its
+characters[] array is zero length. Otherwise, the characters[] array contains
+one
+.I Character
+record for each modifier combination.
+.PP
+The number of records in characters[] is determined by computing (1 <<
+bits_set_in_mask). In other words, if mask is zero, then zero bits are set,
+so characters[] contains only one record. If `mask' is
+.SM "(SHIFT_MASK | CONTROL_MASK),"
+then two bits are set, so characters[] contains four records.
+.PP
+The first record always represents the character which is generated by that
+key when no modifiers are active. The remaining records represent characters
+generated by the various modifier combinations. Using the example with the
+.I shift
+and
+.I control
+masks set, record two would represent the character with the
+.I shift
+modifier active; record three, the
+.I control
+modifier active; and record four, both the
+.I shift
+and
+.I control
+modifiers active.
+.PP
+As a special case,
+.SM ALPHALOCK_MASK
+implies
+.SM SHIFT_MASK,
+though only
+.SM ALPHALOCK_MASK
+appears in `mask'. In this case the same character is generated for both the
+.I shift
+and
+.I alpha-lock
+modifiers, but only needs to appear once in the characters[] array.
+.PP
+.SM CARRIAGE_RETURN_MASK
+does not actually refer to a modifier key. Instead, it is used to
+distinguish the scan code which is given the special pseudo-designation of
+.I "carriage return"
+key. Typically, this mask appears solo in a
+.I ScanGroup
+record and only the two
+.I Character
+records for control-M and control-C follow. This flag may be a throwback to
+an earlier time or may be specially interpreted by the low-level keyboard
+driver, but its purpose is otherwise enigmatic.
+.SH Character
+Each
+.I Character
+record indicates the character generated when this key is pressed, as well as
+the character set which contains the character. Well known character sets are
+.SM `ASCII'
+and `Symbol'. The character set can also be one of the meta values
+.SM FUNCTION_KEY
+or
+.SM KEY_SEQUENCE.
+If it is
+.SM FUNCTION_KEY
+then `char_code' represents a generally well-known function key such as those
+enumerated by
+.I FunctionKey.
+If the character set is
+.SM KEY_SEQUENCE
+then `char_code' represents is a zero-base index into
+KeyMapping::sequence_lists[].
+.PP
+.RS
+.AS
+.AZ "enum CharacterSet {"
+.AN " ASCII" " " "= 0x00,"
+.AN " SYMBOL" " " "= 0x01,"
+.AN " ..."
+.AN " FUNCTION_KEY" "" "= 0xfe,"
+.AN " KEY_SEQUENCE" "" "= 0xff"
+.AZ };
+.AE
+.PP
+.AS
+.AZ "struct Character {"
+.AN " number set;" " " "// CharacterSet of generated character"
+.AN " number char_code;" "" "// Actual character generated"
+.AZ };
+.AE
+.PP
+.AS
+.AZ "enum FunctionKey {"
+.AZ " F1 = 0x20, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12,"
+.AZ " INSERT, DELETE, HOME, END, PAGE_UP, PAGE_DOWN, PRINT_SCREEN,"
+.AZ " SCROLL_LOCK, PAUSE, SYS_REQUEST, BREAK, RESET, STOP, MENU,"
+.AZ " USER, SYSTEM, PRINT, CLEAR_LINE, CLEAR_DISPLAY, INSERT_LINE,"
+.AZ " DELETE_LINE, INSERT_CHAR, DELETE_CHAR, PREV, NEXT, SELECT"
+.AZ };
+.AE
+.RE
+.SH Sequence
+When Character::set contains the meta value
+.SM KEY_SEQUENCE,
+the scan code is bound to a sequence of keys rather than a single character.
+A sequence is a series of modifiers and characters which are automatically
+generated when the associated key is depressed.
+.PP
+.RS
+.AS
+.AZ "#define MODIFIER_KEY 0xff"
+.AE
+.PP
+.AS
+.AZ "struct Sequence {"
+.AN " number num_chars;"
+.AN " Character characters[...];"
+.AZ };
+.AE
+.RE
+.PP
+Each generated
+.I Character
+is represented as previously described, with the exception that
+.SM MODIFIER_KEY
+may appear in place of
+.SM KEY_SEQUENCE.
+When the value of Character::set is
+.SM MODIFIER_KEY
+then Character::char_code represents a modifier key rather than an actual
+character. If the modifier represented by `char_code' is non-zero, then it
+indicates that the associated modifier key has been depressed. In this case,
+the value is one of the constants enumerated by
+.I Modifier
+(\c
+.SM "SHIFT, CONTROL, ALTERNATE,"
+etc.). If the value is zero then it means that the modifier keys have been
+released.
+.SH "Special Key"
+A special key is one which is scanned directly by the Mach kernel rather than
+by the WindowServer. In general, events are not generated for special keys.
+.PP
+.RS
+.AS
+.AZ "enum SpecialKeyType {"
+.AZ " VOLUME_UP = 0,"
+.AZ " VOLUME_DOWN,"
+.AZ " BRIGHTNESS_UP,"
+.AZ " BRIGHTNESS_DOWN,"
+.AZ " ALPHA_LOCK,"
+.AZ " HELP,"
+.AZ " POWER,"
+.AZ " SECONDARY_ARROW_UP,"
+.AZ " SECONDARY_ARROW_DOWN"
+.AZ };
+.AE
+.PP
+.AS
+.AZ "struct SpecialKey {"
+.AN " number type;" " " "// A SpecialKeyType constant"
+.AN " number scan_code;" "" "// Actual scan code"
+.AZ };
+.AE
+.RE
+.SH OUTPUT
+What follows is an explanation and description of the various pieces of
+information emitted by
+.I dumpkeymap.
+.PP
+For a more thorough discussion of any particular piece of information described
+here, refer to the detailed description of the internal layout of a key mapping
+provided by the
+.I "Key Mapping Description"
+section above.
+.SH Conventions
+Depending upon context, some numeric values are displayed in decimal
+notation, whereas others are displayed in hexadecimal notation.
+Hexadecimal numbers are denoted by a `0x' prefix (for instance, `0x7b'),
+except when explicitly noted otherwise.
+.SH "Key Mapping Source"
+The first piece of information presented about a particular key mapping is the
+source from which the data was gleaned. For a
+.I .keymapping
+file, the title
+.SM "`KEYMAP FILE'"
+is emitted along with the path and name of the file in question. For the key
+mapping currently in use by the WindowServer and AppKit, the title
+.SM "`ACTIVE KEYMAP'"
+is emitted instead.
+.SH "Device Information"
+Each
+.I .keymapping
+file may contain one or more raw key mappings. For example, a file which maps
+keys to a Dvorak-style layout might contain raw mappings for Intel
+.SM "PC, ADB, NeXT,"
+and Sun Type5 keyboards.
+.PP
+For each raw mapping, the following information is emitted:
+.BG
+.BU
+The title
+.SM `KEYMAP'
+along with the mapping's relative position in the
+.I .keymapping
+file.
+.BU
+The `interface' identifier.
+.BU
+The `handler_id' sub-identifier.
+.BU
+The size of the raw mapping resource counted in bytes.
+.BE
+The `interface' and `handler_id' values, taken together, define a specific
+keyboard device. A
+.I .keyboard
+file, which describes the visual layout of a keyboard, also contains
+`interface' and `handler_id' identifiers. The
+.I .keyboard
+file corresponding to a particular key mapping can be found by matching the
+`interface' and `handler_id' values from each resource.
+.SH Modifiers
+Each mapping may contain zero or more modifier records which associate hardware
+scan codes with modifier descriptions such as
+.I "shift, control, alternate,"
+etc. The title
+.SM `MODIFIERS'
+is printed along with the count of modifier records which follow. For each
+modifier record, the modifier's name is printed along with a list of scan
+codes, in hexadecimal format, which generate that modifier value. For example:
+.PP
+.RS
+.nf
+MODIFIERS [4]
+alternate: 0x1d 0x60
+control: 0x3a
+keypad: 0x52 0x53 ... 0x63 0x62
+shift: 0x2a 0x36
+.fi
+.RE
+.SH Characters
+Each mapping may contain zero or more character records which associate
+hardware scan codes with the actual characters generated by those scan
+codes in the presence or absence of various modifier combinations. The
+title
+.SM `CHARACTERS'
+is printed along with the count of character records which follow. Here is a
+highly abbreviated example:
+.PP
+.RS
+.nf
+CHARACTERS [9]
+scan 0x00: -AC-L "a" "A" "^A" "^A" ca c7 "^A" "^A"
+scan 0x07: -AC-L "x" "X" "^X" "^X" 01/b4 01/ce "^X" "^X"
+scan 0x0a: ---S- "<" ">"
+scan 0x13: -ACS- "2" "@" "^@" "^@" b2 b3 "^@" "^@"
+scan 0x24: R---- "^M" "^C"
+scan 0x3e: ----- [F4]
+scan 0x4a: ----- [page up]
+scan 0x60: ----- {seq#3}
+scan 0x68: not-bound
+.fi
+.RE
+.PP
+For each record, the hexadecimal value of the hardware scan code is printed,
+followed by a list of modifier flag combinations and the actual characters
+generated by this scan code with and without modifiers applied.
+.PP
+The modifier flags field is composed of a combination of single letter
+representations of the various modifier types. The letters stand for:
+.PP
+.RS
+.nf
+L \- alpha-lock
+S \- shift
+C \- control
+A \- alternate
+R \- carriage-return
+.fi
+.RE
+.PP
+As a special case, the
+.I alpha-lock
+flag also implies the
+.I shift
+flag, so these two flags never appear together in the same record.
+.PP
+The combination of modifier flags determines the meaning and number of fields
+which follow. The first field after the modifier flags always represents the
+character that will be generated if no modifier keys are depressed. The
+remaining fields represent characters generated by the various modifier
+combinations. The order of the fields follows this general pattern:
+.BG
+.BU
+The character generated by this scan code when no modifiers are in effect is
+listed first.
+.BU
+If the `L' or `S' flag is active, then the shifted character generated by this
+scan code is listed next.
+.BU
+If the `C' flag is active, then the control-character generated by this scan
+code is listed next. Furthermore, if the `L' or `S' flag is also active, then
+the shifted control-character is listed after that.
+.BU
+If the `A' flag is active, then the alternate-character generated by this scan
+code is listed next. Furthermore, if the `L' or `S' flag is active, then the
+shifted alternate-character is listed after that. If the `C' flag is also
+active, then the alternate-control-character is listed next. Finally, if the
+`C' and `L' or `C' and `S' flags are also active, then the shifted
+alternate-control-character is listed.
+.BE
+The `R' flag does not actually refer to a modifier key. Instead, it is used to
+distinguish the scan code which is given the special pseudo-designation of
+.I "carriage return"
+key. Typically, this mask appears solo and only the two fields for control-M
+and control-C follow. This flag may be a throwback to an earlier time or may
+be specially interpreted by the low-level keyboard driver, but its purpose is
+otherwise enigmatic.
+.PP
+Recalling the example from above, the following fields can be identified:
+.PP
+.RS
+.nf
+scan 0x00: -AC-L "a" "A" "^A" "^A" ca c7 "^A" "^A"
+.fi
+.RE
+.BG
+.BU
+Lower-case `a' is generated when no modifiers are active.
+.BU
+Upper-case `A' is generated when
+.IR shift " or " alpha-lock
+are active.
+.BU
+Control-A is generated when
+.I control
+is active.
+.BU
+Control-A is generated when
+.IR control " and " shift
+are active.
+.BU
+The character represented by the hexadecimal code 0xca is generated when
+.I alternate
+is active.
+.BU
+The character represented by 0xc7 is generated when
+.IR alternate " and " shift " (or " alpha-lock ") are active."
+.BU
+Control-A is generated when
+.IR alternate " and " control
+are active.
+.BU
+Control-A is generated when
+.IR "alternate, control" " and " shift " (or " alpha-lock ") are active."
+.BE
+The notation used to represent a particular generated character varies.
+.BG
+.BU
+Printable
+.SM ASCII
+characters are quoted, as in "x" or "X".
+.BU
+Control-characters are quoted and prefixed with `^', as in "^X".
+.BU
+Characters with values greater than 127 (0x7f) are displayed as hexadecimal
+values without the `0x' prefix.
+.BU
+Characters in a non-\c
+.SM ASCII
+character set (such as `Symbol') are displayed as two hexadecimal numbers
+separated by a slash, as in `01/4a'. The first number is the character set's
+identification code (such as `01' for the `Symbol' set), and the second number
+is the value of the generated character.
+.BU
+Non-printing special function characters are displayed with the function's
+common name enclosed in brackets, as in `[page up]' or `[F4]'.
+.BU
+If the binding represents a key sequence rather than a single character, then
+the sequence's identification number is enclosed in braces, as in `{seq#3}'.
+.BE
+Recalling a few examples from above, the following interpretations can be made:
+.PP
+.RS
+.nf
+scan 0x07: -AC-L "x" "X" "^X" "^X" 01/b4 01/ce "^X" "^X"
+scan 0x3e: ----- [F4]
+scan 0x4a: ----- [page up]
+scan 0x60: ----- {seq#3}
+.fi
+.RE
+.BG
+.BU
+"x" and "X" are printable
+.SM ASCII
+characters.
+.BU
+"^X" is a control-character.
+.BU
+`01/b4' and `01/ce' represent the character codes 0xb4 and 0xce in the `Symbol'
+character set.
+.BU
+Scan code 0x3e generates function-key `F4', and scan code 0x4a generates
+function-key `page up'.
+.BU
+Scan code 0x60 is bound to key sequence #3.
+.BE
+Finally, if a scan code is not bound to any characters, then it is annotated
+with the label `not-bound', as with example scan code 0x68 from above.
+.SH Sequences
+A scan code (modified and unmodified) can be bound to a key sequence rather
+than generating a single character or acting as a modifier. When it is bound
+to a key sequence, a series of character invocations and modifier actions are
+automatically generated rather than a single keystroke.
+.PP
+Each mapping may contain zero or more key sequence records. The title
+.SM `SEQUENCES'
+is printed along with the count of sequence records which follow. For example:
+.PP
+.RS
+.nf
+SEQUENCES [3]
+sequence 0: "f" "o" "o"
+sequence 1: {alternate} "b" "a" "r" {unmodify}
+sequence 2: [home] "b" "a" "z"
+.fi
+.RE
+.PP
+The notation used to represent the sequence of generated characters is
+identical to the notation already described in the
+.I Characters
+section above, with the exception that modifier actions may be interposed
+between generated characters. Such modifier actions are represented by the
+modifier's name enclosed in braces. The special name `{unmodify}' indicates
+the release of the modifier keys.
+.PP
+Thus, the sequences in the above example can be interpreted as follows:
+.BG
+.BU
+Sequence\ #0 generates `foo'.
+.BU
+Sequence\ #1 invokes the
+.I alternate
+modifier, generates `bar', and then releases
+.I alternate.
+.BU
+Sequence\ #2 invokes the
+.I home
+key and then generates `baz'. In a text editor, this would probably result in
+`baz' being prepended to the line of text on which the cursor resides.
+.BE
+.SH Special Keys
+Certain keyboards feature keys which perform some type of special purpose
+function rather than generating a character or acting as a modifier. For
+instance, Apple keyboards often contain a
+.I power
+key, and
+.SM NeXT
+keyboards have historically featured screen brightness and volume control keys.
+.PP
+Each mapping may contain zero or more special-key records which associate
+hardware scan codes with such special purpose functions. The title
+.SM `SPECIALS'
+is printed along with the count of records which follow. For each record, the
+special function's name is printed along with a list of scan codes, in
+hexadecimal format, which are bound to that function. For example:
+.PP
+.RS
+.nf
+SPECIALS [6]
+alpha-lock: 0x39
+brightness-down: 0x79
+brightness-up: 0x74
+power: 0x7f
+sound-down: 0x77
+sound-up: 0x73
+.fi
+.RE
+.SH FILES
+.IP *.keymapping
+A key mapping file which precisely defines the relationship of all
+hardware-specific keyboard scan-codes with their associated functionality.
+.IP *.keyboard
+A file describing the physical layout of keys on a particular type of
+keyboard. Each `key' token in this file defines the position and shape of the
+key on the keyboard, as well as the associated scan code which that key
+generates. A
+.I .keymapping
+file, on the other hand, defines the characters which are generated by a
+particular scan code depending upon the state of the various modifier keys
+(such as
+.I shift,
+.I control,
+etc.). The `interface' and `handler_id' values from a
+.I .keymapping
+file are matched against those in each
+.I .keyboard
+file in order to associate a particular
+.I .keyboard
+file with a key mapping. Various
+.SM GUI
+programs use the
+.I .keyboard
+file to display a visual representation of a keyboard for the user. Since
+these files are just plain text, they can be easily viewed and interpreted
+without the aid of a specialized program, thus
+.I dumpkeymap
+leaves these files alone.
+.PP
+/System/Library/Keyboards
+.br
+/Network/Library/Keyboards
+.br
+/Local/Library/Keyboards
+.br
+/Library/Keyboards
+.RS
+Repositories for
+.I .keymapping
+and
+.I .keyboard
+files for MacOS/X, Darwin, and MacOS/X Server.
+.RE
+.PP
+/NextLibrary/Keyboards
+.br
+/LocalLibrary/Keyboards
+.RS
+Repositories for
+.I .keymapping
+and
+.I .keyboard
+files for OpenStep and NextStep.
+.RE
+.IP $(HOME)/Library/Keyboards
+Repository for personal
+.I .keymapping
+and
+.I .keyboard
+files.
+.SH DIGANOSTICS
+The following diagnostic messages may be issued to the standard error stream.
+.TG "Unrecognized option."
+An unrecognized option was specified on the command-line. Invoke
+.I dumpkeymap
+with the
+.B "\-\^\-help"
+option to view a list of valid options.
+.TG "Insufficient data in keymapping data stream."
+The key mapping file or data stream is corrupt. Either the file has been
+incorrectly truncated or a field, such as those which indicates the number of
+variable records which follow, contains a corrupt value.
+.PP
+The following diagnostic messages have significance only when trying to print
+.I .keymapping
+files mentioned on the command-line.
+.TG "Bad magic number."
+The mentioned file is not a
+.I .keymapping
+file. The file's content does not start with the string `KYM1'.
+.TG "Unable to open key mapping file."
+The call to fopen() failed; probably because the specified path is invalid or
+.I dumpkeymap
+does not have permission to read the file.
+.TG "Unable to determine key mapping file size."
+The call to fstat() failed, thus memory can not be allocated for loading the
+file.
+.TG "Unable to read key mapping file."
+The call to fread() failed.
+.PP
+The following diagnostic messages have significance only when trying to print
+the currently active key mapping when no
+.I .keymapping
+files have been mentioned on the command-line.
+.TG "Unable to open event status driver."
+The call to NXOpenEventStatus() failed.
+.TG "Bad key mapping length."
+The call to NXKeyMappingLength() returned a bogus value.
+.TG "Unable to get current key mapping."
+The call to NXGetKeyMapping() failed.
+.PP
+The following diagnostic messages have significance only when using
+.I dumpkeymap
+on a non-Apple/\c
+.SM NeXT
+platform.
+.TG "Must specify at least one .keymapping file."
+No
+.I .keymapping
+files were mentioned on the command-line. On non-Apple/\c
+.SM NeXT
+platforms, there is no concept of a currently active
+.I .keymapping
+file, so at least one file must be mentioned on the command-line.
+.SH AUTHOR
+Eric Sunshine <sunshine@sunshineco.com> wrote
+.I dumpkeymap
+and this document, the
+.I "dumpkeymap user's manual."
+Both
+.I dumpkeymap
+and this document are copyright \(co1999,2000 by Eric Sunshine
+<sunshine@sunshineco.com>. All rights reserved.
+.PP
+The implementation of
+.I dumpkeymap
+is based upon information gathered on September 3, 1997 by Eric Sunshine
+<sunshine@sunshineco.com> and Paul S. McCarthy <zarnuk@zarnuk.com> during an
+effort to reverse engineer the format of the
+.SM NeXT
+.I .keymapping
+file.
+.if n .PP
+.if n Version \n(VE \-\-
+.if n .UP
--- /dev/null
+/* x-hash.c - basic hash tables
+ $Id: x-hash.c,v 1.7 2003/07/17 05:25:44 jharper Exp $
+
+ Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
+
+ Permission is hereby granted, free of charge, to any person
+ obtaining a copy of this software and associated documentation files
+ (the "Software"), to deal in the Software without restriction,
+ including without limitation the rights to use, copy, modify, merge,
+ publish, distribute, sublicense, and/or sell copies of the Software,
+ and to permit persons to whom the Software is furnished to do so,
+ subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT
+ HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ DEALINGS IN THE SOFTWARE.
+
+ Except as contained in this notice, the name(s) of the above
+ copyright holders shall not be used in advertising or otherwise to
+ promote the sale, use or other dealings in this Software without
+ prior written authorization. */
+
+#include "x-hash.h"
+#include "x-list.h"
+#include <stdlib.h>
+#include <assert.h>
+
+struct x_hash_table_struct {
+ unsigned int bucket_index;
+ unsigned int total_keys;
+ x_list **buckets;
+
+ x_hash_fun *hash_key;
+ x_compare_fun *compare_keys;
+ x_destroy_fun *destroy_key;
+ x_destroy_fun *destroy_value;
+};
+
+#define ITEM_NEW(k, v) X_PFX (list_prepend) ((x_list *) (k), v)
+#define ITEM_FREE(i) X_PFX (list_free_1) (i)
+#define ITEM_KEY(i) ((void *) (i)->next)
+#define ITEM_VALUE(i) ((i)->data)
+
+#define SPLIT_THRESHOLD_FACTOR 2
+
+/* http://planetmath.org/?op=getobj&from=objects&name=GoodHashTablePrimes */
+static const unsigned int bucket_sizes[] = {
+ 29, 53, 97, 193, 389, 769, 1543, 3079, 6151, 12289, 24593, 49157,
+ 98317, 196613, 393241, 786433, 1572869, 3145739, 6291469, 12582917,
+ 25165843, 50331653, 100663319, 201326611, 402653189, 805306457,
+ 1610612741
+};
+
+#define N_BUCKET_SIZES (sizeof (bucket_sizes) / sizeof (bucket_sizes[0]))
+
+static inline unsigned int
+hash_table_total_buckets (x_hash_table *h)
+{
+ return bucket_sizes[h->bucket_index];
+}
+
+static inline void
+hash_table_destroy_item (x_hash_table *h, void *k, void *v)
+{
+ if (h->destroy_key != 0)
+ (*h->destroy_key) (k);
+
+ if (h->destroy_value != 0)
+ (*h->destroy_value) (v);
+}
+
+static inline unsigned int
+hash_table_hash_key (x_hash_table *h, void *k)
+{
+ if (h->hash_key != 0)
+ return (*h->hash_key) (k);
+ else
+ return (unsigned int) k;
+}
+
+static inline int
+hash_table_compare_keys (x_hash_table *h, void *k1, void *k2)
+{
+ if (h->compare_keys == 0)
+ return k1 == k2;
+ else
+ return (*h->compare_keys) (k1, k2) == 0;
+}
+
+static void
+hash_table_split (x_hash_table *h)
+{
+ x_list **new, **old;
+ x_list *node, *item, *next;
+ int new_size, old_size;
+ unsigned int b;
+ int i;
+
+ if (h->bucket_index == N_BUCKET_SIZES - 1)
+ return;
+
+ old_size = hash_table_total_buckets (h);
+ old = h->buckets;
+
+ h->bucket_index++;
+
+ new_size = hash_table_total_buckets (h);
+ new = calloc (new_size, sizeof (x_list *));
+
+ if (new == 0)
+ {
+ h->bucket_index--;
+ return;
+ }
+
+ for (i = 0; i < old_size; i++)
+ {
+ for (node = old[i]; node != 0; node = next)
+ {
+ next = node->next;
+ item = node->data;
+
+ b = hash_table_hash_key (h, ITEM_KEY (item)) % new_size;
+
+ node->next = new[b];
+ new[b] = node;
+ }
+ }
+
+ h->buckets = new;
+ free (old);
+}
+
+X_EXTERN x_hash_table *
+X_PFX (hash_table_new) (x_hash_fun *hash,
+ x_compare_fun *compare,
+ x_destroy_fun *key_destroy,
+ x_destroy_fun *value_destroy)
+{
+ x_hash_table *h;
+
+ h = calloc (1, sizeof (x_hash_table));
+ if (h == 0)
+ return 0;
+
+ h->bucket_index = 0;
+ h->buckets = calloc (hash_table_total_buckets (h), sizeof (x_list *));
+
+ if (h->buckets == 0)
+ {
+ free (h);
+ return 0;
+ }
+
+ h->hash_key = hash;
+ h->compare_keys = compare;
+ h->destroy_key = key_destroy;
+ h->destroy_value = value_destroy;
+
+ return h;
+}
+
+X_EXTERN void
+X_PFX (hash_table_free) (x_hash_table *h)
+{
+ int n, i;
+ x_list *node, *item;
+
+ assert (h != NULL);
+
+ n = hash_table_total_buckets (h);
+
+ for (i = 0; i < n; i++)
+ {
+ for (node = h->buckets[i]; node != 0; node = node->next)
+ {
+ item = node->data;
+ hash_table_destroy_item (h, ITEM_KEY (item), ITEM_VALUE (item));
+ ITEM_FREE (item);
+ }
+ X_PFX (list_free) (h->buckets[i]);
+ }
+
+ free (h->buckets);
+ free (h);
+}
+
+X_EXTERN unsigned int
+X_PFX (hash_table_size) (x_hash_table *h)
+{
+ assert (h != NULL);
+
+ return h->total_keys;
+}
+
+static void
+hash_table_modify (x_hash_table *h, void *k, void *v, int replace)
+{
+ unsigned int hash_value;
+ x_list *node, *item;
+
+ assert (h != NULL);
+
+ hash_value = hash_table_hash_key (h, k);
+
+ for (node = h->buckets[hash_value % hash_table_total_buckets (h)];
+ node != 0; node = node->next)
+ {
+ item = node->data;
+
+ if (hash_table_compare_keys (h, ITEM_KEY (item), k))
+ {
+ if (replace)
+ {
+ hash_table_destroy_item (h, ITEM_KEY (item),
+ ITEM_VALUE (item));
+ ITEM_KEY (item) = k;
+ ITEM_VALUE (item) = v;
+ }
+ else
+ {
+ hash_table_destroy_item (h, k, ITEM_VALUE (item));
+ ITEM_VALUE (item) = v;
+ }
+ return;
+ }
+ }
+
+ /* Key isn't already in the table. Insert it. */
+
+ if (h->total_keys + 1
+ > hash_table_total_buckets (h) * SPLIT_THRESHOLD_FACTOR)
+ {
+ hash_table_split (h);
+ }
+
+ hash_value = hash_value % hash_table_total_buckets (h);
+ h->buckets[hash_value] = X_PFX (list_prepend) (h->buckets[hash_value],
+ ITEM_NEW (k, v));
+ h->total_keys++;
+}
+
+X_EXTERN void
+X_PFX (hash_table_insert) (x_hash_table *h, void *k, void *v)
+{
+ hash_table_modify (h, k, v, 0);
+}
+
+X_EXTERN void
+X_PFX (hash_table_replace) (x_hash_table *h, void *k, void *v)
+{
+ hash_table_modify (h, k, v, 1);
+}
+
+X_EXTERN void
+X_PFX (hash_table_remove) (x_hash_table *h, void *k)
+{
+ unsigned int hash_value;
+ x_list **ptr, *item;
+
+ assert (h != NULL);
+
+ hash_value = hash_table_hash_key (h, k);
+
+ for (ptr = &h->buckets[hash_value % hash_table_total_buckets (h)];
+ *ptr != 0; ptr = &((*ptr)->next))
+ {
+ item = (*ptr)->data;
+
+ if (hash_table_compare_keys (h, ITEM_KEY (item), k))
+ {
+ hash_table_destroy_item (h, ITEM_KEY (item), ITEM_VALUE (item));
+ ITEM_FREE (item);
+ item = *ptr;
+ *ptr = item->next;
+ X_PFX (list_free_1) (item);
+ h->total_keys--;
+ return;
+ }
+ }
+}
+
+X_EXTERN void *
+X_PFX (hash_table_lookup) (x_hash_table *h, void *k, void **k_ret)
+{
+ unsigned int hash_value;
+ x_list *node, *item;
+
+ assert (h != NULL);
+
+ hash_value = hash_table_hash_key (h, k);
+
+ for (node = h->buckets[hash_value % hash_table_total_buckets (h)];
+ node != 0; node = node->next)
+ {
+ item = node->data;
+
+ if (hash_table_compare_keys (h, ITEM_KEY (item), k))
+ {
+ if (k_ret != 0)
+ *k_ret = ITEM_KEY (item);
+
+ return ITEM_VALUE (item);
+ }
+ }
+
+ if (k_ret != 0)
+ *k_ret = 0;
+
+ return 0;
+}
+
+X_EXTERN void
+X_PFX (hash_table_foreach) (x_hash_table *h,
+ x_hash_foreach_fun *fun, void *data)
+{
+ int i, n;
+ x_list *node, *item;
+
+ assert (h != NULL);
+
+ n = hash_table_total_buckets (h);
+
+ for (i = 0; i < n; i++)
+ {
+ for (node = h->buckets[i]; node != 0; node = node->next)
+ {
+ item = node->data;
+ (*fun) (ITEM_KEY (item), ITEM_VALUE (item), data);
+ }
+ }
+}
--- /dev/null
+/* x-hash.h -- basic hash table class
+ $Id: x-hash.h,v 1.4 2003/04/16 00:42:14 jharper Exp $
+
+ Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
+
+ Permission is hereby granted, free of charge, to any person
+ obtaining a copy of this software and associated documentation files
+ (the "Software"), to deal in the Software without restriction,
+ including without limitation the rights to use, copy, modify, merge,
+ publish, distribute, sublicense, and/or sell copies of the Software,
+ and to permit persons to whom the Software is furnished to do so,
+ subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT
+ HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ DEALINGS IN THE SOFTWARE.
+
+ Except as contained in this notice, the name(s) of the above
+ copyright holders shall not be used in advertising or otherwise to
+ promote the sale, use or other dealings in this Software without
+ prior written authorization. */
+
+#ifndef X_HASH_H
+#define X_HASH_H 1
+
+typedef struct x_hash_table_struct x_hash_table;
+
+typedef int (x_compare_fun) (const void *a, const void *b);
+typedef unsigned int (x_hash_fun) (const void *k);
+typedef void (x_destroy_fun) (void *x);
+typedef void (x_hash_foreach_fun) (void *k, void *v, void *data);
+
+/* for X_PFX and X_EXTERN */
+#include "x-list.h"
+
+X_EXTERN x_hash_table *X_PFX (hash_table_new) (x_hash_fun *hash,
+ x_compare_fun *compare,
+ x_destroy_fun *key_destroy,
+ x_destroy_fun *value_destroy);
+X_EXTERN void X_PFX (hash_table_free) (x_hash_table *h);
+
+X_EXTERN unsigned int X_PFX (hash_table_size) (x_hash_table *h);
+
+X_EXTERN void X_PFX (hash_table_insert) (x_hash_table *h, void *k, void *v);
+X_EXTERN void X_PFX (hash_table_replace) (x_hash_table *h, void *k, void *v);
+X_EXTERN void X_PFX (hash_table_remove) (x_hash_table *h, void *k);
+X_EXTERN void *X_PFX (hash_table_lookup) (x_hash_table *h,
+ void *k, void **k_ret);
+X_EXTERN void X_PFX (hash_table_foreach) (x_hash_table *h,
+ x_hash_foreach_fun *fun,
+ void *data);
+
+#endif /* X_HASH_H */
--- /dev/null
+/* x-hook.c
+ $Id: x-hook.c,v 1.2 2003/04/16 00:42:14 jharper Exp $
+
+ Copyright (c) 2003 Apple Computer, Inc. All rights reserved.
+
+ Permission is hereby granted, free of charge, to any person
+ obtaining a copy of this software and associated documentation files
+ (the "Software"), to deal in the Software without restriction,
+ including without limitation the rights to use, copy, modify, merge,
+ publish, distribute, sublicense, and/or sell copies of the Software,
+ and to permit persons to whom the Software is furnished to do so,
+ subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT
+ HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ DEALINGS IN THE SOFTWARE.
+
+ Except as contained in this notice, the name(s) of the above
+ copyright holders shall not be used in advertising or otherwise to
+ promote the sale, use or other dealings in this Software without
+ prior written authorization. */
+
+#include "x-hook.h"
+#include <stdlib.h>
+#include <assert.h>
+
+#define CELL_NEW(f,d) X_PFX (list_prepend) ((x_list *) (f), (d))
+#define CELL_FREE(c) X_PFX (list_free_1) (c)
+#define CELL_FUN(c) ((x_hook_function *) ((c)->next))
+#define CELL_DATA(c) ((c)->data)
+
+X_EXTERN x_list *
+X_PFX (hook_add) (x_list *lst, x_hook_function *fun, void *data)
+{
+ return X_PFX (list_prepend) (lst, CELL_NEW (fun, data));
+}
+
+X_EXTERN x_list *
+X_PFX (hook_remove) (x_list *lst, x_hook_function *fun, void *data)
+{
+ x_list *node, *cell;
+ x_list *to_delete = NULL;
+
+ for (node = lst; node != NULL; node = node->next)
+ {
+ cell = node->data;
+ if (CELL_FUN (cell) == fun && CELL_DATA (cell) == data)
+ to_delete = X_PFX (list_prepend) (to_delete, cell);
+ }
+
+ for (node = to_delete; node != NULL; node = node->next)
+ {
+ cell = node->data;
+ lst = X_PFX (list_remove) (lst, cell);
+ CELL_FREE (cell);
+ }
+
+ X_PFX (list_free) (to_delete);
+}
+
+X_EXTERN void
+X_PFX (hook_run) (x_list *lst, void *arg)
+{
+ x_list *node, *cell;
+ x_hook_function **fun;
+ void **data;
+ int length, i;
+
+ length = X_PFX (list_length) (lst);
+ fun = alloca (sizeof (x_hook_function *) * length);
+ data = alloca (sizeof (void *) * length);
+
+ for (i = 0, node = lst; node != NULL; node = node->next, i++)
+ {
+ cell = node->data;
+ fun[i] = CELL_FUN (cell);
+ data[i] = CELL_DATA (cell);
+ }
+
+ for (i = 0; i < length; i++)
+ {
+ (*fun[i]) (arg, data[i]);
+ }
+}
+
+X_EXTERN void
+X_PFX (hook_free) (x_list *lst)
+{
+ x_list *node;
+
+ for (node = lst; node != NULL; node = node->next)
+ {
+ CELL_FREE (node->data);
+ }
+
+ X_PFX (list_free) (lst);
+}
--- /dev/null
+/* x-hook.h -- lists of function,data pairs to call.
+ $Id: x-hook.h,v 1.2 2003/04/16 00:42:14 jharper Exp $
+
+ Copyright (c) 2003 Apple Computer, Inc. All rights reserved.
+
+ Permission is hereby granted, free of charge, to any person
+ obtaining a copy of this software and associated documentation files
+ (the "Software"), to deal in the Software without restriction,
+ including without limitation the rights to use, copy, modify, merge,
+ publish, distribute, sublicense, and/or sell copies of the Software,
+ and to permit persons to whom the Software is furnished to do so,
+ subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT
+ HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ DEALINGS IN THE SOFTWARE.
+
+ Except as contained in this notice, the name(s) of the above
+ copyright holders shall not be used in advertising or otherwise to
+ promote the sale, use or other dealings in this Software without
+ prior written authorization. */
+
+#ifndef X_HOOK_H
+#define X_HOOK_H 1
+
+#include "x-list.h"
+
+typedef void x_hook_function (void *arg, void *data);
+
+X_EXTERN x_list *X_PFX (hook_add) (x_list *lst, x_hook_function *fun, void *data);
+X_EXTERN x_list *X_PFX (hook_remove) (x_list *lst, x_hook_function *fun, void *data);
+X_EXTERN void X_PFX (hook_run) (x_list *lst, void *arg);
+X_EXTERN void X_PFX (hook_free) (x_list *lst);
+
+#endif /* X_HOOK_H */
--- /dev/null
+/* x-list.c
+ $Id: x-list.c,v 1.16 2003/07/18 00:52:19 jharper Exp $
+
+ Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
+
+ Permission is hereby granted, free of charge, to any person
+ obtaining a copy of this software and associated documentation files
+ (the "Software"), to deal in the Software without restriction,
+ including without limitation the rights to use, copy, modify, merge,
+ publish, distribute, sublicense, and/or sell copies of the Software,
+ and to permit persons to whom the Software is furnished to do so,
+ subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT
+ HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ DEALINGS IN THE SOFTWARE.
+
+ Except as contained in this notice, the name(s) of the above
+ copyright holders shall not be used in advertising or otherwise to
+ promote the sale, use or other dealings in this Software without
+ prior written authorization. */
+
+#include "x-list.h"
+#include <stdlib.h>
+#include <assert.h>
+#include <pthread.h>
+
+/* Allocate in ~4k blocks */
+#define NODES_PER_BLOCK 508
+
+typedef struct x_list_block_struct x_list_block;
+
+struct x_list_block_struct {
+ x_list l[NODES_PER_BLOCK];
+};
+
+static x_list *freelist;
+
+static pthread_mutex_t freelist_lock = PTHREAD_MUTEX_INITIALIZER;
+
+static inline void
+list_free_1 (x_list *node)
+{
+ node->next = freelist;
+ freelist = node;
+}
+
+X_EXTERN void
+X_PFX (list_free_1) (x_list *node)
+{
+ assert (node != NULL);
+
+ pthread_mutex_lock (&freelist_lock);
+
+ list_free_1 (node);
+
+ pthread_mutex_unlock (&freelist_lock);
+}
+
+X_EXTERN void
+X_PFX (list_free) (x_list *lst)
+{
+ x_list *next;
+
+ pthread_mutex_lock (&freelist_lock);
+
+ for (; lst != NULL; lst = next)
+ {
+ next = lst->next;
+ list_free_1 (lst);
+ }
+
+ pthread_mutex_unlock (&freelist_lock);
+}
+
+X_EXTERN x_list *
+X_PFX (list_prepend) (x_list *lst, void *data)
+{
+ x_list *node;
+
+ pthread_mutex_lock (&freelist_lock);
+
+ if (freelist == NULL)
+ {
+ x_list_block *b;
+ int i;
+
+ b = malloc (sizeof (x_list_block));
+
+ for (i = 0; i < NODES_PER_BLOCK - 1; i++)
+ b->l[i].next = &(b->l[i+1]);
+ b->l[i].next = NULL;
+
+ freelist = b->l;
+ }
+
+ node = freelist;
+ freelist = node->next;
+
+ pthread_mutex_unlock (&freelist_lock);
+
+ node->next = lst;
+ node->data = data;
+
+ return node;
+}
+
+X_EXTERN x_list *
+X_PFX (list_append) (x_list *lst, void *data)
+{
+ x_list *head = lst;
+
+ if (lst == NULL)
+ return X_PFX (list_prepend) (NULL, data);
+
+ while (lst->next != NULL)
+ lst = lst->next;
+
+ lst->next = X_PFX (list_prepend) (NULL, data);
+
+ return head;
+}
+
+X_EXTERN x_list *
+X_PFX (list_reverse) (x_list *lst)
+{
+ x_list *head = NULL, *next;
+
+ while (lst != NULL)
+ {
+ next = lst->next;
+ lst->next = head;
+ head = lst;
+ lst = next;
+ }
+
+ return head;
+}
+
+X_EXTERN x_list *
+X_PFX (list_find) (x_list *lst, void *data)
+{
+ for (; lst != NULL; lst = lst->next)
+ {
+ if (lst->data == data)
+ return lst;
+ }
+
+ return NULL;
+}
+
+X_EXTERN x_list *
+X_PFX (list_nth) (x_list *lst, int n)
+{
+ while (n-- > 0 && lst != NULL)
+ lst = lst->next;
+
+ return lst;
+}
+
+X_EXTERN x_list *
+X_PFX (list_pop) (x_list *lst, void **data_ret)
+{
+ void *data = NULL;
+
+ if (lst != NULL)
+ {
+ x_list *tem = lst;
+ data = lst->data;
+ lst = lst->next;
+ X_PFX (list_free_1) (tem);
+ }
+
+ if (data_ret != NULL)
+ *data_ret = data;
+
+ return lst;
+}
+
+X_EXTERN x_list *
+X_PFX (list_filter) (x_list *lst,
+ int (*pred) (void *item, void *data), void *data)
+{
+ x_list *ret = NULL, *node;
+
+ for (node = lst; node != NULL; node = node->next)
+ {
+ if ((*pred) (node->data, data))
+ ret = X_PFX (list_prepend) (ret, node->data);
+ }
+
+ return X_PFX (list_reverse) (ret);
+}
+
+X_EXTERN x_list *
+X_PFX (list_map) (x_list *lst,
+ void *(*fun) (void *item, void *data), void *data)
+{
+ x_list *ret = NULL, *node;
+
+ for (node = lst; node != NULL; node = node->next)
+ {
+ X_PFX (list_prepend) (ret, fun (node->data, data));
+ }
+
+ return X_PFX (list_reverse) (ret);
+}
+
+X_EXTERN x_list *
+X_PFX (list_copy) (x_list *lst)
+{
+ x_list *copy = NULL;
+
+ for (; lst != NULL; lst = lst->next)
+ {
+ copy = X_PFX (list_prepend) (copy, lst->data);
+ }
+
+ return X_PFX (list_reverse) (copy);
+}
+
+X_EXTERN x_list *
+X_PFX (list_remove) (x_list *lst, void *data)
+{
+ x_list **ptr, *node;
+
+ for (ptr = &lst; *ptr != NULL;)
+ {
+ node = *ptr;
+
+ if (node->data == data)
+ {
+ *ptr = node->next;
+ X_PFX (list_free_1) (node);
+ }
+ else
+ ptr = &((*ptr)->next);
+ }
+
+ return lst;
+}
+
+X_EXTERN unsigned int
+X_PFX (list_length) (x_list *lst)
+{
+ unsigned int n;
+
+ n = 0;
+ for (; lst != NULL; lst = lst->next)
+ n++;
+
+ return n;
+}
+
+X_EXTERN void
+X_PFX (list_foreach) (x_list *lst,
+ void (*fun) (void *data, void *user_data),
+ void *user_data)
+{
+ for (; lst != NULL; lst = lst->next)
+ {
+ (*fun) (lst->data, user_data);
+ }
+}
+
+static x_list *
+list_sort_1 (x_list *lst, int length,
+ int (*less) (const void *, const void *))
+{
+ x_list *mid, *ptr;
+ x_list *out_head, *out;
+ int mid_point, i;
+
+ /* This is a standard (stable) list merge sort */
+
+ if (length < 2)
+ return lst;
+
+ /* Calculate the halfway point. Split the list into two sub-lists. */
+
+ mid_point = length / 2;
+ ptr = lst;
+ for (i = mid_point - 1; i > 0; i--)
+ ptr = ptr->next;
+ mid = ptr->next;
+ ptr->next = NULL;
+
+ /* Sort each sub-list. */
+
+ lst = list_sort_1 (lst, mid_point, less);
+ mid = list_sort_1 (mid, length - mid_point, less);
+
+ /* Then merge them back together. */
+
+ assert (lst != NULL && mid != NULL);
+
+ if ((*less) (mid->data, lst->data))
+ out = out_head = mid, mid = mid->next;
+ else
+ out = out_head = lst, lst = lst->next;
+
+ while (lst != NULL && mid != NULL)
+ {
+ if ((*less) (mid->data, lst->data))
+ out = out->next = mid, mid = mid->next;
+ else
+ out = out->next = lst, lst = lst->next;
+ }
+
+ if (lst != NULL)
+ out->next = lst;
+ else
+ out->next = mid;
+
+ return out_head;
+}
+
+X_EXTERN x_list *
+X_PFX (list_sort) (x_list *lst, int (*less) (const void *, const void *))
+{
+ int length;
+
+ length = X_PFX (list_length) (lst);
+
+ return list_sort_1 (lst, length, less);
+}
--- /dev/null
+/* x-list.h -- simple list type
+ $Id: x-list.h,v 1.10 2003/07/18 00:52:19 jharper Exp $
+
+ Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
+
+ Permission is hereby granted, free of charge, to any person
+ obtaining a copy of this software and associated documentation files
+ (the "Software"), to deal in the Software without restriction,
+ including without limitation the rights to use, copy, modify, merge,
+ publish, distribute, sublicense, and/or sell copies of the Software,
+ and to permit persons to whom the Software is furnished to do so,
+ subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT
+ HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ DEALINGS IN THE SOFTWARE.
+
+ Except as contained in this notice, the name(s) of the above
+ copyright holders shall not be used in advertising or otherwise to
+ promote the sale, use or other dealings in this Software without
+ prior written authorization. */
+
+#ifndef X_LIST_H
+#define X_LIST_H 1
+
+/* This is just a cons. */
+
+typedef struct x_list_struct x_list;
+
+struct x_list_struct {
+ void *data;
+ x_list *next;
+};
+
+#ifndef X_PFX
+# define X_PFX(x) x_ ## x
+#endif
+
+#ifndef X_EXTERN
+# define X_EXTERN __private_extern__
+#endif
+
+X_EXTERN void X_PFX (list_free_1) (x_list *node);
+X_EXTERN x_list *X_PFX (list_prepend) (x_list *lst, void *data);
+
+X_EXTERN x_list *X_PFX (list_append) (x_list *lst, void *data);
+X_EXTERN x_list *X_PFX (list_remove) (x_list *lst, void *data);
+X_EXTERN void X_PFX (list_free) (x_list *lst);
+X_EXTERN x_list *X_PFX (list_pop) (x_list *lst, void **data_ret);
+
+X_EXTERN x_list *X_PFX (list_copy) (x_list *lst);
+X_EXTERN x_list *X_PFX (list_reverse) (x_list *lst);
+X_EXTERN x_list *X_PFX (list_find) (x_list *lst, void *data);
+X_EXTERN x_list *X_PFX (list_nth) (x_list *lst, int n);
+X_EXTERN x_list *X_PFX (list_filter) (x_list *src,
+ int (*pred) (void *item, void *data),
+ void *data);
+X_EXTERN x_list *X_PFX (list_map) (x_list *src,
+ void *(*fun) (void *item, void *data),
+ void *data);
+
+X_EXTERN unsigned int X_PFX (list_length) (x_list *lst);
+X_EXTERN void X_PFX (list_foreach) (x_list *lst, void (*fun)
+ (void *data, void *user_data),
+ void *user_data);
+
+X_EXTERN x_list *X_PFX (list_sort) (x_list *lst, int (*less) (const void *,
+ const void *));
+
+#endif /* X_LIST_H */